הפרוצדורה הנ"ל שהיא Extended Stored Procedure מאפשרת להריץ Command Lines שהשרת תומך בהם, מתוך SQL Server.
קודם כל הכוונה לפקודות הוותיקות המוכרות לנו מימי DOS העליזים- Copy, Dir, Type, Del, MD, RD וכו',
ובהמשך לכך Command Lines של מערכות שונות שהותקנו על השרת: SQL Server עצמו עם פקודות כמו BCP או SQLCMD, ועוד.
החל מגרסת 2005 הפרוצדורה מנוטרלת כברירת מחדל בשל בעיות האבטחה הכרוכות בהפעלתה: הפקודה מופעלת על ידי השרת עם ההרשאות של ה-Agent בהתייחס ל-SQL Server ולשרת הפיזי, ומכיוון שיש לו בדרך כלל הרשאות גבוהות שאין לכל משתמש או מתכנת – ניתן להריץ בעזרת xp_cmdshell פקודות שונות מול ה-File System של השרת (כולל מחיצות שלמשתמש עצמו אין הרשאה לגשת אליהן), ובעזרת SQLCMD להריץ פקודות SQL שלמשתמש עצמו אין הרשאה לבצע.
ניתן להתגבר על הבעייה תוך שימוש ב-Proxy.
כך מאפשרים את השימוש בפרוצדורה כך:
Exec sp_configure 'show advanced options', 1
GO
ReConfigure
GO
Exec sp_configure 'xp_cmdshell', 1
GO
ReConfigure
יתכן ובמקום Reconfigure צריך להשתמש ב-ReConfigure With Override בשל רגישות הנושא (כלומר- המערכת מוגדרת כך שיש צורך באישור מיוחד בגלל הבעייתיות בפרוצדורה).
השימוש בפרוצדורה:
Exec master..xp_cmdshell 'Dir C:\'
והפלט המוצג ב-SSMS בצורת Grid הוא הפלט שהיינו רואים לו הרצנו את פקודת \:Dir C ממסך Cmd.
את הפלט ניתן "ללכוד" כך:
Create Table #Tmp(Txt Varchar(Max));
Go
Insert Into #Tmp(Txt)
Exec master..xp_cmdshell 'Dir C:\/b';
Go
Select * From #Tmp;
במקרה זה השתמשתי בפקודה Dir C:\/b שמחזירה רשימת קבצים נקיה ללא תאריכים, גדלים וכותרות.
דוגמה לשימוש בשיטה זו לקליטת תוכן של קובץ לתוך טבלה ניתן לראות בפוסט קודם שלי (יש לחפש שם את xp_cmdshell).
אפשרות אחרת לשלוף את שמות הקבצים מהמחיצה כפקודת Select היא באופן הבא:
Select *
From Openrowset ('Sqloledb','Server=localhost;Trusted_Connection=Yes','Set Fmtonly Off Exec Master..Xp_Cmdshell ''Dir C:\/b''')
כאשר במקום localhost ניתן לציין את שם השרת במפורש (למשל כאשר פונים מתוך Instance).
במקרה זה ניתן למיין את הרשימה, להוסיף תנאי Where וכו'.
לפרטים נוספים ניתן לעיין בפוסט של אלי לייבה ב-www.sqlserver.co.il.
ולבסוף דוגמה לשימוש ב-xp_cmdshell תוך גיבוי הפלט למחיצה נפרדת כששם קובץ הגיבוי כולל את התאריך השוטף, כדי שניתן יהיה לעקוב אחר מה שנעשה.
אני מדגים שמירת קובץ עם Dir של מחיצה בדיסק, כשהכוונה שלי להמחיש כיצד ניתן ללכוד את הפלט של כל מה שמופעל מה-Command Line ולשמור אותו לבקרה:
Declare @File Varchar(8000),
@Cmd Varchar(8000);
Set @File=Convert(NVarChar(20),GetDate(),112)+'.txt';
Set @Cmd='dir c:\ > C:\Gibuy\'+@File;
Exec master..xp_cmdshell @Cmd;
משום מה, xp_cmdshell מסרב להפעיל פקודות השמורות במשתני (Varchar(Max ולכן "הסתפקתי" ב-(Varchar(8000.
קצת "מורשת קרב" אישית: לפני מספר שנים עבדתי במקום בו השתמשו ב-DataStage (כלי ETL) ליצוא נתונים ממערכות מסויימות ולקליטתן באחרות,
כאשר הכל נוהל על ידי מערכת Control M (מערכת לתזמון תהליכים) שהייתה אחראית על הפעלת יצוא הנתונים בעזרת ה-DataStage, העברת קבצי הפלט למחיצת הקלט, והפעלת ה-DataStage לקליטתם ביעד.
המשימה שלי פחות או יותר הייתה ליצור Command Lines בעזרת xp_cmdshell שייצרו ג'ובים מתאימים ב-Control M, שהם עצמם יפעילו בעזרת Command Lines את ה-DataStage..
בקיצור- אפשר לנהל את כל העולם עם xp_cmdshell!
[...] מי שמתעצל יכול כך (ניתן לקרוא כאן על XP_CmdShell): [...]
פינגבאק מאת ABCD הכנסת ערכים לעמודת Identity - גרי רשף — 12/03/2012 @ 20:49
[...] XP_CmdShell אינה מאופשרת אצלו שיאפשר אותה לפי ההנחיות כאן. לחילופין ניתן להריץ ממסך ה-Cmd את פקודת ה-BCP שבין [...]
פינגבאק מאת שמירת קבצים בתוך טבלה - גרי רשף — 09/01/2012 @ 20:34
[...] שלו לשם שכולל את התאריך והשעה, ומפעילה את הפקודה בעזרת XP_CmdShell. הערות: יש להקפיד שהפלט של הצעד בו הפרוצדורה מופעלת לא [...]
פינגבאק מאת הפרדה בין קבצי Trace של ג'ובים - גרי רשף — 14/11/2011 @ 20:03
[...] ומפעילה את הפקודה בעזרת XP_CmdShell. [...]
פינגבאק מאת הפרדה בין קבצי Trace של ג’ובים « הבלוג של גרי רשף — 14/11/2011 @ 19:58
[...] הערה טכנית- מי שפקודת XP_CmdShell אינה מאופשרת אצלו שיאפשר אותה לפי ההנחיות כאן. [...]
פינגבאק מאת שמירת קבצים בתוך טבלה « הבלוג של גרי רשף — 18/09/2011 @ 18:42