Я пытался скопировать некоторые файлы через SSH, но вместо tar
'луг те, которых я хотел, я получил свою домашнюю папку. Я сделал некоторое дальнейшее тестирование, и оно сводится к этому:
ssh root@server /bin/sh -c "cd /boot && ls -l"
Который к моему удивлению перечисляет файлы в /root
нет /boot
. Но если я выполняю все /bin/sh
команда от терминала это правильно cd
s и печать /boot
файлы.
Что происходит здесь?
ssh не позволяет Вам указать команду точно, поскольку Вы сделали как серия аргументов, которые будут переданы execvp на удаленном хосте. Вместо этого это связывает все аргументы в строку и выполняет их через удаленную оболочку. Это выделяется как главный недостаток дизайна в ssh, по-моему... это - инструмент Unix хорошего поведения большинством способов, но когда он прибывает время для определения команды, он принял решение использовать единственную монолитную строку вместо argv, как он был разработан для MS-DOS или чего-то!
Так как ssh передаст Вашу команду как единственную строку к sh -c
, Вы не должны обеспечивать свое собственное sh -c
. Когда Вы делаете, результат
sh -c '/bin/sh -c cd /boot && ls -l'
с исходным потерянным заключением в кавычки. Так команды, разделенные &&
:
`/bin/sh -c cd /boot`
`ls -l`
Первое из тех выполнений оболочка с текстом команды "CD" и $0
="boot"
. Команда "CD" завершается успешно, $0
не важно, и /bin/sh -c
указывает на успех, затем ls -l
происходит.
İt проблема заключения в кавычки. 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
или другая база данных пароля), не понимает эту команду.
ssh root@server "cd /boot && ls -l"
Если необходимо вызвать другую оболочку, необходимо заключить удаленную команду в кавычки для защиты ее от расширения удаленной оболочкой, вызванной sshd
. Например, если Ваша оболочка входа в систему является тире, и Вы хотите выполнить команду удара:
ssh root@server 'bash -c "cd ~bob && ls -l"'
Я думаю, что это имеет больше, чтобы сделать с тем, как опции становятся проанализированными оболочкой. Например, это работает:
$ ssh root@server /bin/sh -c '"cd /boot && ls -l"'
Это имеет ту же проблему как Ваша команда:
$ ssh root@server /bin/sh -c 'cd /boot && ls -l'
Если Вы включаете -v
переключатель к ssh
Вы видите то, что продолжается:
1-я команда:
debug1: команда Sending:/bin/sh-c "CD / загружают && ls-l"
2-я команда:
debug1: команда Sending:/bin/sh-c CD / загружают && ls-l
Обычно при отправке команд через ssh
необходимо обратить особое внимание на заключение в кавычки и перенести кавычки в кавычках, поскольку различные слои снимают их. Также не потрудитесь отправлять /bin/sh
.
Можно сделать очень полезную вещь, после того как Вы понимаете заключение в кавычки ssh
такой как следующее. Это выполнит команду на удаленном сервере, но соберет результаты в файле локально в системе, куда Вы работали ssh
команда:
$ ssh root@server 'free -m' > /tmp/memory.status
или это, где Вы смолите каталог на удаленном сервере и создаете его в локальной системе:
$ ssh remotehost 'tar zcvf - SOURCEDIR' | cat > DESTFILE.tar.gz
Обычно Вы не должны указывать что оболочку использовать. Это работает:
ssh user@host "cd /boot && pwd"
Но если Ваша оболочка по умолчанию проблематична, то просто удостоверяются, что Вы заключаете всю команду в кавычки, включая вызов оболочки. Любая из следующих работ
ssh user@host '/bin/sh -c "cd /boot && pwd"'
ssh user@host "/bin/sh -c \"cd /boot && pwd\""
cd /boot && pwd
работы во всех оболочках главных семейств (Граница, csh, дистанционное управление), /bin/sh -c "cd /boot && pwd"
не работал бы, если удаленная оболочка имеет rc
семейство, где "
не является особенным.
– Stéphane Chazelas
27.06.2013, 12:09
ssh
ведите себя как этот, если бы это не было, то это нужно было бы назватьsexec
, нетssh
.ssh
защищенная версияrsh
(который вел себя то же в том отношении), иrlogin
(rsh
названныйrlogin
при отсутствии передачи командная строка). Просто неудачно, что это не реализуетrexec
также. – Stéphane Chazelas 27.06.2013, 12:02"`printf "%q " "$@"`"
с ударомprintf
заключить в кавычки строку или строки с Escape оболочки. – Sam Watkins 28.05.2016, 05:23