Время от времени я буду делать что-то вроде
ssh user@host sudo thing
и мне напомнили, что ssh по умолчанию не выделяет псевдо-tty. Почему не так? Какую пользу я бы проиграл, если бы я стал псевдонимом ssh
в ssh -t
?
Время от времени я буду делать что-то вроде
ssh user@host sudo thing
и мне напомнили, что ssh по умолчанию не выделяет псевдо-tty. Почему не так? Какую пользу я бы проиграл, если бы я стал псевдонимом ssh
в ssh -t
?
Основное различие заключается в интерактивность, Он похож на выполнение команд локально внутри скрипта, а также набирает их самостоятельно. Другое дело в том, что удаленная команда должна выбрать по умолчанию, а неинтерактивная - самая безопасная. (и обычно самый честный)
Ctrl-c
break обычно приводит к тому, что цикл команды ssh прерывается немедленно, ваши контрольные последовательности будут отправляться на удаленный сервер. Это приводит к необходимости «забивать» нажатие клавиши, чтобы гарантировать, что она поступит, когда управление листья команда ssh, но перед следующей командой ssh.Я бы предостерег от использования ssh -t
в автоматических сценариях, таких как коронки. Неинтерактивная оболочка, запрашивающая удаленную команду для интерактивного ввода данных, запрашивает всевозможные проблемы.
Вы также можете проверить наличие терминала в своих собственных сценариях оболочки. Чтобы проверить STDIN с более новыми версиями bash:
# fd 0 is STDIN
[ -t 0 ]; echo $?
ssh
в ssh -t
, вы можете ожидать получить дополнительный возврат каретки в своих концах строки. Это может быть не видно вам, но оно есть; он будет отображаться как ^M
при подаче на cat -e
, Затем вы должны потратить дополнительные усилия на то, чтобы этот управляющий код не был привязан к вашим переменным, особенно если вы собираетесь вставить этот вывод в базу данных.Вот такой же тест bash, как и раньше, но для STDOUT:
# fd 1 is STDOUT
[ -t 1 ]; echo $?
Хотя можно обойти эти проблемы, вы неизбежно забудете разработать сценарии вокруг них. Мы все в какой-то момент. Члены вашей команды также могут не осознавать / помнить, что этот псевдоним на месте, что, в свою очередь, создает проблемы для вас, когда Oни писать сценарии, которые используют ваш псевдоним.
Aliasing ssh
в ssh -t
это очень важный случай, когда вы будете нарушать принцип проектирования наименее; люди будут сталкиваться с проблемами, которые они не ожидают, и могут не понимать, что их вызывает.
Одно из преимуществ, которое не было упомянуто в других ответах, заключается в том, что при работе без псевдотерминала, SSH escape-символы такие как ~C
находятся не поддерживается; это делает его безопасным для программ для передачи двоичных файлов, которые могут содержать эти последовательности.
Скопируйте двоичный файл с помощью псевдотерминала:
$ ssh -t anthony@remote_host 'cat /usr/bin/free' > ~/free
Connection to remote_host closed.
Скопируйте двоичный файл без использования псевдотерминала:
$ ssh anthony@remote_host 'cat /usr/bin/free' > ~/free2
Эти два файла не совпадают:
$ diff ~/free*
Binary files /home/anthony/free and /home/anthony/free2 differ
Тот, который был скопирован с псевдотерминалом, поврежден:
$ chmod +x ~/free*
$ ./free
Segmentation fault
а другой - нет:
$ ./free2
total used free shared buffers cached
Mem: 2065496 1980876 84620 0 48264 1502444
-/+ buffers/cache: 430168 1635328
Swap: 4128760 112 4128648
Это особенно важно для таких программ, как scp
или rsync
которые используют SSH для передачи данных. Эта подробное описание работы протокола SCP объясняет, как протокол SCP состоит из смеси текстовых сообщений протокола и двоичных файлов.
Стоит отметить, что даже если -t
используется флаг, OpenSSH ssh
клиент отказывается выделять псевдотерминал, если он обнаруживает, что его stdin
поток не является терминалом:
$ echo testing | ssh -t anthony@remote_host 'echo $TERM'
Pseudo-terminal will not be allocated because stdin is not a terminal.
dumb
Вы все равно можете заставить клиента OpenSSH выделить псевдотерминал с помощью -tt
:
$ echo testing | ssh -tt anthony@remote_host 'echo $TERM'
xterm
В любом случае, это (разумно) не волнует, если stdout
или stderr
перенаправляются:
$ ssh -t anthony@remote_host 'echo $TERM' >| ssh_output
Connection to remote_host closed.
На удаленном хосте мы имеем дело с этим параметром:
/etc/sudoers
...
Defaults requiretty
Без sudo
$ ssh -T user@host echo -e 'foo\\nbar' | cat -e
foo$
bar$
И с sudo
$ ssh -T user@host sudo echo -e 'foo\\nbar' | cat -e
sudo: sorry, you must have a tty to run sudo
С помощью sudo мы получаем возврат дополнительной каретки
$ ssh -t user@host sudo echo -e 'foo\\nbar' | cat -e
foo^M$
bar^M$
Connection to localhost closed.
Решение состоит в том, чтобы отключить перевести новую строку в карету return-newline с stty -onlcr
$ ssh -t user@host stty -onlcr\; sudo echo -e 'foo\\nbar' | cat -e
foo$
bar$
Connection to localhost closed.
Подумайте о обратной совместимости.
2 основных режима ssh являются интерактивными входами с tty и заданной командой без tty, поскольку это были точные возможности rlogin
а также rsh
соответственно. ssh необходимо для обеспечения надмножества rlogin
/rsh
чтобы быть успешными в качестве замены.
Таким образом, дефолты были определены до появления ssh. Комбинации типа «Я хочу указать команду а также получить tty "должен был быть доступен с новыми вариантами. Будьте рады, что по крайней мере мы иметь этот вариант теперь, в отличие от того, когда мы использовали rsh
, Мы не использовали никаких полезных функций для получения зашифрованных соединений. У нас есть бонусные функции!
Из man ssh
:
-t Force pseudo-tty allocation. This can be used to execute arbi-
trary screen-based programs on a remote machine, which can be
very useful, e.g. when implementing menu services. Multiple -t
options force tty allocation, even if ssh has no local tty.
Это позволяет вам получить «оболочку» на удаленном сервере. Для серверов, которые делают не предоставить доступ к оболочке оболочки, но разрешить SSH (т. е. Github - известный пример для доступа SFTP), использование этого флага приведет к тому, что сервер отклонит ваше соединение.
Оболочка также имеет все ваши переменные окружения (например, $PATH
), поэтому выполнение скриптов обычно требует работы tty.