Intereting Posts

проблема с паролем при подаче удаленного файла в diff

Когда я хочу сравнить локальный файл с удаленным файлом, любой из них обычно работает:

$ ssh remote cat file | diff file - $ diff file <(ssh remote cat file) 

Однако иногда (особенно когда требуется пароль) они терпят неудачу следующим образом:

 $ ssh remote cat file | diff file - 1,162d0 < ... < ... Password: 

Здесь diff не ждет завершения ssh и считает, что второй файл пуст. Только после того, как diff закончен, ssh запрашивает пароль, но уже слишком поздно.

 $ diff file <(ssh remote cat file) Password: Password: # asking again after a few seconds #&%Pasword: # the typed raw password leaks into the terminal user@remote's password: Permission denied, please try again. user@remote's password: Permission denied, please try again. user@remote's password: Received disconnect from XXX.XX.XX.XX: 2: Too many authentication failures for user 1,162d0 < ... < ... 

На этот раз ssh запрашивает пароль, но введенный пароль возвращается к терминалу, а ssh не получает его. Наконец, сбой ssh и diff продолжается с пустым вторым файлом.

Можете ли вы объяснить, почему это происходит, или что происходит в деталях под капотом ?

Когда вы сначала запустите ssh:

 ssh remote 'cat file' | cat 

ssh получает ваш управляющий терминал как stdin, поэтому вы можете вводить свой пароль без проблем.

Когда вы используете подстановку процессов bash, stdin остается подключенным к первой команде, а выходной канал субпроцесса передается первой команде в качестве аргумента:

 cat <(ssh remote 'cat file') 

Если совпадение ssh преуспело, /dev/fd/63 будет каналом, содержащим вывод ssh remote 'cat file' .

Это можно продемонстрировать с помощью следующей команды:

 $ echo <(ls) /dev/fd/63 

Важная часть этого заключается в том, что ваш терминал подключен к cat stdin, а не ssh . Когда это выполняется, cat получает аргумент командной строки, например /dev/fd/63 . Поэтому кошка игнорирует stdin вообще; однако он по-прежнему связан с процессом cat, а не с ssh , поэтому ваш пароль не идет нигде.

Если вы хотите изменить это, вам нужно сначала запустить ssh и передать вывод на diff , как вы уже показали выше:

 ssh remote 'cat file' | diff file -