紹介する
bash
で動作するスクリプトがありssh
、parallel
並列バージョンではGNUを使用し、順次バージョンではforループを使用します。
スクリプトは次のように使用されます。
foreach_server "cd $dir && find -name '*.png' | wc -l"
foreach_server "cd $dir && git --no-pager status"
conda
時には環境で実行可能ファイルにアクセスする必要があります(https://docs.conda.io/en/latest/)、これを行うために私が見つけた唯一の方法は、対話型シェルを使用することです。つまり、bash -ic
実行したいコマンドの直前にthisを使用してssh $host bash -ic $cmd
conda環境がロードされるようにします。残念ながら、これはstderr
回避できない2つのエラーメッセージを生成します。
bash: cannot set terminal process group (-1): Inappropriate ioctl for device
bash: no job control in this shell
sed
だから、これら2つの行を削除し、stderr
次に別の行を渡すフィルタを作成しましたstderr
。
ssh $host "$@" 2> >(sed -e "$filter1" -e "$filter2" >&2)
問題:sedフィルタは並列バージョンを中断します。
フィルタはsed
順次バージョンではうまく機能しますが、並列バージョンはスクリプトの最後で中断され、sedプロセスはアクティブですが、何もしません。これが起こらないようにするにはどうすればよいですか?
問題がプロセスの代替であると疑われますが、実際に問題を診断することはできません。
参照スクリプト
#!/bin/bash
set -u
exit_trap() {
echo "Interrupted"
exit 1
}
trap exit_trap SIGINT
filter1='/^bash: cannot set terminal process group/d'
filter2='/^bash: no job control in this shell/d'
hosts=("host1" "host2") # more hosts in the real file
if [ -z ${serial+x} ];
then
# Parallel version ==> THIS VERSION HANGS AT THE END, AFTER ALL OUTPUT HAS BEEN WRITTEN
echo ${hosts[@]} | sed 's/ /\n/g' | parallel "echo ----- {} ----- && ssh {} \"$@\"" 2> >(sed -e "$filter1" -e "$filter2" >&2)
else
# Serial version ==> THIS VERSION WORKS FINE
for host in ${hosts[@]};
do
echo "------------------ $host ------------------"
ssh $host "$@" 2> >(sed -e "$filter1" -e "$filter2" >&2)
echo "--------------------------------------$(echo $host | sed 's/./-/g')"
done
fi
答え1
エラーメッセージの症状を取り除こうとするよりも、エラーメッセージの原因を取り除く方が良いでしょう。
ssh
これにより、端末ioctlを適用できるようにセッションにttyが割り当てられます。
ssh -t $host "$@"
実際に行を呼び出す方法によっては、フラグを2倍にする必要があります-t
。-tt
しかし、根本的な問題は、conda環境を設定するためにインタラクティブシェルが必要であるようです。その理由は にあるからがほぼ確実です~/.bashrc
。.
これを明示的に実行するか、関連コマンドを抽出してスクリプトで使用できます。
私もよくわかりませんが、conda
質問です。.bashrcでconda環境を有効にする方法は?~/.bashrc
必要な関連部分はAskUbuntuで参照されているようです。