Выделение терминала приводит к поломке файлов при использовании ssh для передачи

Выделение терминала приводит к поломке файлов при использовании ssh для передачи

Раньше я 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).

Связанный контент