Próbowałem wykonać kopię zapasową niektórych plików przez SSH, ale zamiast tar
tych, które chciałem, dostałem swój folder domowy. Zrobiłem kilka dalszych testów i sprowadza się to do tego:
ssh root@server /bin/sh -c "cd /boot && ls -l"
Który do moich plików list niespodzianka w /root
nie /boot
. Ale jeśli uruchomię całe /bin/sh
polecenie z terminala, to odpowiednio cd
s wydrukuje /boot
pliki.
Co tu się dzieje?
shell
ssh
cd-command
Ambroz Bizjak
źródło
źródło
ssh root@server /bin/sh -c "ls -l /boot"
?Odpowiedzi:
ssh nie pozwala ci precyzyjnie określić polecenia, tak jak to zrobiłeś, jako serii argumentów, które mają zostać przekazane do execvp na zdalnym hoście. Zamiast tego łączy wszystkie argumenty w ciąg i przepuszcza je przez zdalną powłokę. Moim zdaniem wyróżnia się to jako poważna wada projektowa ssh ... jest to dobrze zachowujące się narzędzie unixowe pod wieloma względami, ale kiedy przychodzi czas na określenie polecenia, wybrał użycie pojedynczego monolitycznego łańcucha zamiast argumentu argv, jak został zaprojektowany dla MSDOS lub coś takiego!
Ponieważ ssh przekaże twoje polecenie jako pojedynczy ciąg
sh -c
, nie musisz podawać własnegosh -c
. Kiedy to zrobisz, wynik będziez oryginalnym cytatem utraconym. Tak więc polecenia rozdzielone przez
&&
:Pierwszy z nich uruchamia powłokę z tekstem polecenia „cd” i
$0
="boot"
. Polecenie „cd” zakończyło się pomyślnie, nie$0
ma znaczenia, a/bin/sh -c
oznacza sukces, a potem sięls -l
dzieje.źródło
ssh
tak się zachowują, gdyby tak nie było, trzeba by to nazwaćsexec
, niessh
.ssh
jest bezpieczną wersjąrsh
(która zachowywała się pod tym względem) irlogin
(rsh
wywoływana,rlogin
gdy nie została przekazana linia poleceń). Szkoda, że nie wdraża sięrexec
również."`printf "%q " "$@"`"
pomocą bash,printf
aby zacytować łańcuch lub łańcuchy z ucieczką powłoki.To kwestia cytowania. Ssh już uruchamia polecenie, które przekazujesz w powłoce. Po przekazaniu wielu parametrów są one łączone ze spacją między nimi, aby utworzyć ciąg. Tak więc zdalne polecenie uruchamiane zdalnie to
/bin/sh -c cd /boot && ls -l
(bez cudzysłowów, ponieważ cudzysłowy w twoim poleceniu zostały zinterpretowane przez lokalną powłokę)./bin/sh -c cd /boot
uruchamia się/bin/sh
i każe mu uruchomić polecenie,cd
a także ustawić$0
na/boot
. Po wykonaniu tej czynności uruchomiona jest powłoka nadrzędna (ta uruchomiona przezsshd
)ls -l
.W twoim przypadku po prostu usuń ten,
sh -c
który jest całkowicie bezużyteczny, chyba że zdalna powłoka (jak wskazano w/etc/passwd
lub w innej bazie danych haseł) nie zrozumie tego polecenia.Jeśli potrzebujesz wywołać inną powłokę, musisz zacytować komendę zdalną, aby chronić ją przed rozszerzeniem przez zdalną powłokę wywoływaną przez
sshd
. Na przykład, jeśli twoja powłoka logowania to myślnik i chcesz uruchomić polecenie bash:źródło
Myślę, że ma to więcej wspólnego z tym, jak opcje są analizowane przez powłokę. Na przykład to działa:
Ma to ten sam problem, co twoje polecenie:
Jeśli włączysz
-v
przełącznikssh
, możesz zobaczyć, co się dzieje:1. polecenie:
2. polecenie:
Zazwyczaj wysyłając polecenia za pośrednictwem
ssh
, należy zwrócić szczególną uwagę na cytowanie i zawijać cytaty w cudzysłowy, gdy różne warstwy je usuwają. Również nie zawracaj sobie głowy wysyłaniem/bin/sh
.Możesz zrobić bardzo przydatną rzecz, gdy zrozumiesz cytowanie
ssh
takich jak następujące. Spowoduje to uruchomienie polecenia na zdalnym serwerze, ale zebranie wyników w pliku lokalnie w systemie, w którym uruchomionossh
polecenie:lub to, gdzie zapisujesz katalog na zdalnym serwerze i tworzysz go w systemie lokalnym:
Referencje
źródło
Zazwyczaj nie musisz określać, jakiej powłoki użyć. To działa:
Ale jeśli twoja domyślna powłoka jest problematyczna, upewnij się, że zacytowałeś całe polecenie, w tym wywołanie powłoki. Każda z poniższych prac
źródło
cd /boot && pwd
działa we wszystkich powłokach głównych rodzin (Bourne, csh, rc),/bin/sh -c "cd /boot && pwd"
nie działałby, jeśli zdalna powłoka należy dorc
rodziny, w której"
nie jest wyjątkowa.