Quantcast
Viewing all articles
Browse latest Browse all 2722

ログイン時に何かを出力するようにしていると scp が失敗する問題の対処法

TL;DR

Fix scp command failure · noraworld/dotfiles@4d7cf4f

はじめに

たとえば ~/.bashrcなどで、echoコマンドなどを使って何かを出力するようにしていると scpコマンドが失敗します。

~/.bashrc
# リモートホスト側echo"something"
# クライアント側$ scp username@example.com:~/test .
something

ファイルがカレントディレクトリにダウンロードされるはずがダウンロードされず、"something" と表示されただけで終わってしまいます。

ログイン時に標準出力に何かを表示するようにしていると scpコマンドが失敗するらしいので、scpコマンド実行時のみ ~/.bashrcなどで何も出力しないようにします。

やり方

scpでのログインかどうかを判定する is_not_scp()関数を作ります。is_not_scp()関数は scpからのログインでなければ trueを返し、scpからのログインだったら falseを返します。

そして、scpだったら、ログイン時に何かを出力するようにしている部分を出力しないようにします。

~/.bashrc
is_not_scp(){if[!-f /proc/$PPID/cmdline ];then
    echo true
  elif[-f /proc/$PPID/cmdline ]&&[["$(cat /proc/$PPID/cmdline | sed's/\x0//g')"=~ sshd:([[:blank:]]+.*)@notty ]];then
    echo false
  else
    echo true
  fi}if"$(is_not_scp)";then
  echo"something"fi

解説

macOS では /proc/$PPID/cmdlineは存在しないのでスキップします。

Linux では /proc/$PPID/cmdlineに現在ログイン中の端末の情報が表示されます。たとえば SSH ログイン中に実行すると以下のように表示されます。

$ cat /proc/$PPID/cmdline
sshd: ubuntu@pts/0

これが scpコマンドだと以下のようになります。

sshd: ubuntu@notty

nottyは端末が割り当てられていないということなのですが、scpコマンドだと nottyと表示されるので、そうなっていれば scpコマンドからだと判断します1

sedコマンドを使っているのは、cat /proc/$PPID/cmdlineの出力にヌルバイトが混ざっているからです。sedでヌルバイトを除去しています。

ログイン時に何かを出力している箇所を if "$(is_not_scp)"; thenfiで囲めば scp時にはその部分は出力されなくなるので、scpがうまく機能するようになります。

~/.bashrcじゃなくて ~/.bash_profileに何かを出力していたり、Zsh を使っていて ~/.zshrcとかに何かを出力していた場合も同様です。適宜、ファイル名は読み替えてください。

参考サイト


  1. それ以外で sshd: ubuntu@nottyのように表示されるケースもありますが実用上はおそらく問題ないと思いますので割愛します。 


Viewing all articles
Browse latest Browse all 2722

Trending Articles