以下のような現象。
多段scpを試みたときに出会った現象。ProxyCommandによる多段scpができなかったので、しょうがなく愚直に2回scpをしようとした。
expectで踏み台サーバーにsshして、ls
。lsの結果をfzfで絞り込んでscpする以下のようなスクリプトを組んだ。
serverFiles=`expect -c " spawn ssh -t serverA \"ssh $targetServer\" expect \"$USER\" send \"ls -1\n\" expect \"]\" expect \"$USER\" send \"exit\n\" "` # 先頭行から6行目まではexpectの実行コマンドなので削除し、lsの結果だけを表示する targetFile=`echo "${serverFiles}"| sed -e '1,6d' | grep -v $USER | fzf` # 対象サーバーからserverAにコピー ssh serverA "scp -r $USER@$targetServer:$targetFile $LOCAL_PATH" # ローカルにコピー scp -r serverA:$targetFile $LOCAL_PATH # serverAにコピーしたファイルを削除 ssh serverA "rm -r $targetFile"
実行結果
▶sh scpServer.sh
: No such file...
scpで「そんなファイルないよ」と怒られる。
末尾の「?」は改行コードのCRだった
結論から言うと
targetFile=`echo "${serverFiles}"| sed -e '1,6d' | grep -v $USER | fzf`
を
targetFile=`echo "${serverFiles}"| tr -d '\r' | sed -e '1,6d' | grep -v $USER | fzf`
のようにtr -d '\r'
をすればうまくいった。
どうやらlsした結果にCRが紛れ込んでいたようだった。
CRにたどり着くまでの道のり
推測1:fzfで絞り込んだ結果の$targetFileが空になっている?
targetFile=`echo "${serverFiles}"| sed -e '1,6d' | grep -v $USER | fzf` echo $targetFile # 実行結果 ~ ▶sh scpServer.sh hoge.txt
変数名にはちゃんと入っているようだ。
推測2:「?」を消してみる
tr -d "?"
で削除を試みたが結果は変わらず。。。
推測3:文字コードがおかしい?
どうやら目には見えないが内部的になにか変化しているのだろうと推測し、まずは文字コードからあたってみることにした。
nkf --guess
をしてみる。
targetFile=`echo "${serverFiles}"| sed -e '1,6d' | grep -v $USER | fzf` echo $targetFile | nkf --guess # 実行結果 ▶sh scpServer.sh ASCII (CRLF)
ほうほうなるほど。試しに普通にechoで文字列をawk --guess
したときどうなるか見てみる
▶echo "hoge" | nkf --guess ASCII (LF)
ここで理解した。CRが紛れ込んでいたんだなと。
ecpect -c
内の\n
がsendでやると\r
に変換されるのかなあ。
なぜCRが紛れ込むのかはまだ調査中だが、とりあえず一件落着だった。