[PL] SQL Server–Obejście problemu z xp_cmdshell
Procedura rozszerzona xp_cmdshell dostępna w SQL Server bywa przedmiotem dyskusji na temat bezpieczeństwa i tego, czy system zarządzania bazami danych powinien mocno integrować się z systemem operacyjnym. Domyślnie procedura ta jest wyłączona dzięki jednej z opcji serwera, ale często jest włączana i wykorzystywana, głównie do uruchamiania zewnętrznych aplikacji z poziomu kodu T-SQL.
Ostatnio natknąłem się na problem, którego rozwiązanie zajęło mi chwilę. I postanowiłem, że swoim rozwiązaniem się podzielę.
Na początek włączamy xp_cmdshell na instancji SQL Servera:
EXEC sp_configure 'show advanced options', 1; RECONFIGURE; GO EXEC sp_configure 'xp_cmdshell', 1; RECONFIGURE; GO
Próba uruchomienia xp_cmdshell:
EXEC master.dbo.xp_cmdshell 'dir "C:\Program Files"'; GO
Wynikiem jest lista katalogów i plików z folderu Program Files na dysku C:. Warto tu zwrócić uwagę na fakt, że parametr polecenia dir (listowanie plików i katalogów w systemie Windows) został otoczony cudzysłowami, ponieważ zawierał spację (gdyby cudzysłowów nie dać, napis zostałby potraktowany jako dwa parametry).
Problem pojawia się, gdy chcemy uruchomić zewnętrzną aplikację / wsad (.bat lub .cmd), do której ścieżka zawiera spacje z parametrem, w którym spacje również występują. Przykład:
EXEC master.dbo.xp_cmdshell '"D:\SQL Server\ProcessCube.bat" "My DB" "My Cube"'; GO
Próba wykonania powyższego kodu, przy założeniu, że wsad ProcessCube.bat naprawdę istnieje w lokalizacji D:\SQL Server, zakończy się komunikatem:
Nazwa ‘D:\SQL’ nie jest rozpoznawana jako polecenie wewnętrzne lub zewnętrzne, program wykonywalny lub plik wsadowy.
Szczerze mówiąc, nie wiem, jaka jest przyczyna problemu, ale obstawiam jakiś błąd w xp_cmdshell.
Obejście problemu jest dość proste:
EXEC master.dbo.xp_cmdshell 'call "D:\SQL Server\ProcessCube.bat" "My DB" "My Cube"'; GO
Trzeba zapewnić, że pierwsze w ciągu znaków podawanym jako parametr procedury xp_cmdshell będzie polecenie systemowe (do którego nie potrzeba podawać pełnej ścieżki). Może to być, jak powyżej, polecenie CALL (uruchamianie wsadu z innego wsadu – tak naprawdę można w ten sposób uruchamiać także wsady z konsoli).
Ot, czym czasem musi zajmować się konsultant Business Intelligence ;-)

Nazywam się Paweł Potasiński i pracuję w polskim oddziale Microsoft w dziale Small and Midmarket Solutions & Partners (SMS&P) jako Partner Technology Advisor.





2010/10/27 - 23:11
Nie jest to błąd xp_cmdshell, ale zachowanie procesora poleceń cmd. Zakładam, że xp_cmdshell używa go w połączeniu z parametrem “/C”, czyli wykonuje polecenie określone poprzez podany w parametrze ciąg i wymusza zakończenie jego działania. Ma to na celu uniemożliwienie wstrzymania wykonania procedury xp_cmdshell, ze względu na oczekiwanie uruchamianego programu/wsadu na reakcję użytkownika.
Dowodem potwierdzającym moją tezę będzie wykonanie następującej instrukcji:
EXEC master.dbo.xp_cmdshell ‘pause’;
które nie zachowa się zgodnie oczekiwaniami, tj. nie wstrzyma wykonania procedury xp_cmdshell, a jedynie wyświetli stosowny komunikat.
Identyczny efekt do przedstawionego we wpisie można uzyskać wywołując z okna wiersza poleceń, następującą komendę:
cmd /C “D:\SQL Server\ProcessCube.bat” “My DB” “My Cube”
Oczywiście także w tym przypadku zadziała zaproponowane obejście:
cmd /C call “D:\SQL Server\ProcessCube.bat” “My DB” “My Cube”
Co ciekawe – nie jest to jedyne rozwiązanie. Innym jest ujęcie całości wywołania w dodatkowe cudzysłowy (nawiasem mówiąc dziwi, że te wewnętrzne nie muszą być podwójne).
cmd /C “”D:\SQL Server\ProcessCube.bat” “My DB” “My Cube”"
i to samo dla xp_cmdshell:
EXEC master.dbo.xp_cmdshell ‘”"D:\SQL Server\ProcessCube.bat” “My DB” “My Cube”"‘;
To tyle ;).
P.S. Przyznam, że komentarz w tym maleńkim okienku piszę się karkołomnie ;). Ale może jego rozmiar ma na celu zapobieganie swawoli komentującego :P.
2010/10/28 - 00:21
@Paweł: Bardzo ładne wyjaśnienie. Tak czułem, że być może czegoś nie wziąłem pod uwagę. Dzięki za wyjaśnienie problemu. A co do okna komentarza, to takie niestety jest i raczej się nie zmieni. Bynajmniej nie po to, by uniknąć komentarzy, bo, jak widać, mogę się z nich sporo dowiedzieć ;-)
2010/10/28 - 22:20
@Paweł: Jako człowiek dociekliwy (by nie rzecz upierdliwy ;) ) upewniam się, że w kwestii niezmienności okna komentarza przyczyną są kwestie estetyczne, a nie przeszkody techniczne (bo jeśli te drugie, to służę pomocą i okno zyska na ergonomii).
2010/10/28 - 23:02
@Paweł: Dzięki Twojej dociekliwości postanowiłem poszukać w gąszczu stron i szablonów Wordpressa tego nieszczęsnego pola do wpisywania komentarzy i efektem jest jego podwojona szerokość ;-)