Я пытался сделать резервную копию некоторых файлов через SSH, но вместо того tar
, чтобы найти те, которые я хотел, я получил свою домашнюю папку. Я провел дополнительное тестирование, и оно сводится к следующему:
ssh root@server /bin/sh -c "cd /boot && ls -l"
Который к моему удивлению перечисляет файлы в /root
нет /boot
. Но если я запускаю всю /bin/sh
команду из терминала, она корректно cd
распечатывает /boot
файлы.
Что тут происходит?
shell
ssh
cd-command
Амброз Бижак
источник
источник
ssh root@server /bin/sh -c "ls -l /boot"
?Ответы:
ssh не позволяет вам точно указывать команду, как вы это сделали, в виде последовательности аргументов, передаваемых execvp на удаленном хосте. Вместо этого он объединяет все аргументы в строку и запускает их через удаленную оболочку. На мой взгляд, это серьезный недостаток дизайна в ssh: в большинстве случаев это хорошо работающий инструмент unix, но когда приходит время указать команду, она выбрала одну монолитную строку вместо argv, например это было разработано для MSDOS или что-то!
Поскольку ssh передаст вашу команду в виде одной строки
sh -c
, вам не нужно указывать свою собственнуюsh -c
. Когда вы делаете, результатс оригинальным цитированием потерял. Таким образом, команды, разделенные
&&
:Первый из них запускает оболочку с текстом команды "cd" и
$0
="boot"
. Команда "cd" завершается успешно, не$0
имеет значения, и/bin/sh -c
указывает на успех, затемls -l
происходит.источник
ssh
себя вести, если бы это было не так, его нужно было бы назватьsexec
, а неssh
.ssh
является безопасной версиейrsh
(которая вела себя то же самое в этом отношении) иrlogin
(rsh
называется ,rlogin
когда не передается из командной строки). Просто прискорбно, что это также не реализуетсяrexec
."`printf "%q " "$@"`"
с bashprintf
для цитирования строки или строк с экранированием оболочки.Это вопрос цитирования. Ssh уже запускает команду, которую вы передаете в оболочке. Когда вы передаете несколько параметров, они объединяются с пробелом между ними для построения строки. Таким образом, удаленная команда, которую вы запускаете удаленно
/bin/sh -c cd /boot && ls -l
(без кавычек, потому что кавычки в вашей команде были интерпретированы локальной оболочкой)./bin/sh -c cd /boot
запускает/bin/sh
и говорит ему выполнить команду,cd
а также установить$0
в/boot
. После этого запускается родительская оболочка (запущенная пользователемsshd
)ls -l
.В вашем случае просто удалите тот,
sh -c
который совершенно бесполезен, если ваша удаленная оболочка (как указано в/etc/passwd
другой базе паролей) не понимает эту команду.Если вам нужно вызвать другую оболочку, вы должны указать удаленную команду в кавычках, чтобы защитить ее от раскрытия, вызванного удаленной оболочкой
sshd
. Например, если ваша оболочка входа в систему dash и вы хотите выполнить команду bash:источник
Я думаю, что это больше связано с тем, как параметры интерпретируются оболочкой. Например, это работает:
Это та же проблема, что и ваша команда:
Если вы включите
-v
переключатель,ssh
вы сможете увидеть, что происходит:1-я команда:
2-я команда:
Как правило, при отправке команд через них
ssh
вы должны обращать особое внимание на цитаты и заключать их в кавычки, поскольку различные слои удаляют их. Также не беспокойтесь об отправке/bin/sh
.Вы можете сделать очень полезную вещь, как только вы поймете цитату,
ssh
например, следующее. Это запустит команду на удаленном сервере, но соберет результаты в файл локально в системе, где вы выполнилиssh
команду:или это, где вы tar каталог на удаленном сервере и создать его в локальной системе:
Ссылки
источник
Обычно вам не нужно указывать, какую оболочку использовать. Это работает:
Но если ваша оболочка по умолчанию проблематична, просто убедитесь, что вы заключили в кавычки всю команду, включая вызов оболочки. Любая из следующих работ
источник
cd /boot && pwd
работает во всех оболочках основных семейств (Bourne, csh, rc),/bin/sh -c "cd /boot && pwd"
не будет работать, если удаленная оболочка принадлежит кrc
семейству, где"
не является особенным.