
Раньше я ssh
распаковывал удаленный файл с помощью:
ssh host "cat file.tgz" | tar xf -
Это работает отлично. Однако, играя с принудительными командами, я заметил, что pty-allocation изменяет вывод команды:
ssh host -T "cat file.tgz" >first_file
ssh host -t "cat file.tgz" >second_file
Здесь первый файл в порядке, а второй файл сломан.
Почему именно выделение pty изменяет вывод?
решение1
Это помогает читатьssh
страница руководства:
-T Disable pseudo-tty allocation.
-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.
Когда вы говорите этовыделятьапсевдо-tty, любой процесс на удаленной стороне может видеть, что соединение является "реальным" терминалом, и будет отправлять дополнительные сообщения, поскольку соединение является интерактивным. В инициализации вашей оболочки он также может устанавливать режимы терминала, которые вы можете проверить с помощью stty -a
. Режимы терминала используются дляпереводитьмежду вводом с клавиатуры и хостом, а также между текстом, отправленным с хоста на ваш терминал:
- Безинициализируется, соединение не является терминальным и трансляция не выполняется.
- Синициализируясь, терминал будет переводить новую строку (
\n
) в возврат каретки и перевод строки (0x0d, 0x0a). Он также будет (для большинства пользователей) переводить табуляции в пробелы.
Описанный эффект предназначен дляперевод. Без этого вашинтерактивныйсеанс будет «лестничать» по всему экрану и станет непригодным для использования.
Ваша оболочка также может выводить дополнительную информацию, но для одной командыпредположениеот @kba вводит в заблуждение, поскольку оболочка обычно не отправляетподсказки, и элементы управления ssh, такие как ~C
упомянутые, применяются квходскорее, чемвыход.
При запуске на терминале ssh также выведет сообщение при закрытии соединения. Но оно записывается в стандартный поток ошибок.
решение2
Почему именно выделение pty изменяет вывод?
Поскольку удаленная сторона (с выделенным терминалом) будет «вводить» управляющие символы для вашего локального терминала (в основном коды управления C0 и C1). А поскольку ваша локальная сторона не является терминалом, а файлом, она просто сбрасывает их в этот файл.
SSH пытается сделать все возможное, чтобы угадать, что вы хотите (если stdin не TTY, то он не выделит удаленный TTY, если вы не добавите -tt
переключатели). Эта опция существует не просто так, и если вам нужна двоичная передача, вы не хотите, чтобы терминалы портили ваш файл.
Вы можете увидеть это поведение, просто передав небольшие файлы и выполнив их шестнадцатеричный дамп:
$ ssh -t host "cat test" > /tmp/test.t
$ ssh host "cat test" > /tmp/test
$ hexdump -C /tmp/test
00000000 0a 2a 20 46 72 69 20 46 65 62 20 31 32 20 32 30 |.* Fri Feb 12 20|
00000030 6d 3e 20 33 2e 34 2e 31 2d 31 0a 2d 20 4e 65 77 |m> 3.4.1-1.- New|
$ hexdump -C /tmp/test.t
00000000 0d 0a 2a 20 46 72 69 20 46 65 62 20 31 32 20 32 |..* Fri Feb 12 2|
00000030 6f 6d 3e 20 33 2e 34 2e 31 2d 31 0d 0a 2d 20 4e |om> 3.4.1-1..- N|
Для меня разница только в двух байтах 0d 0a
перед каждой новой строкой, но их может быть больше (в Linux Newline — это только \n
, но терминал получает оба \r\n
).