ローカルファイルをリモートファイルと比較する場合は、通常、次のいずれかが機能します。
$ ssh remote cat file | diff file -
$ diff file <(ssh remote cat file)
しかし、時には(特にパスワードを要求するとき)、次のように失敗します。
$ ssh remote cat file | diff file -
1,162d0
< ...
< ...
Password:
ここでは、完了をdiff
待たずにssh
2番目のファイルが空であると見なします。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
2番目のファイルに進みます。
なぜこれが起こるのかを説明してください。それとも何が起こっているのかを詳しく説明してください。フード?
答え1
SSHを最初に実行すると:
ssh remote 'cat file' | cat
sshは制御端末を標準入力として使用するため、問題なくパスワードを入力できます。
バッシュ使用時プロセスの交換、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
、catはstdinを完全に無視しますが、代わりにまだcatプロセスに接続されているため、ssh
パスワードは使用できません)。
これを変更するには、まず上記のようにssh
出力を実行してからパイプする必要があります。diff
ssh remote 'cat file' | diff file -