Bash
通過 sed 過濾標準錯誤時,Bash 腳本掛起
介紹
我有一個
bash
腳本可以通過ssh
. 它在並行版本中使用 GNUparallel
,在順序版本中使用 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/),而我發現使這項工作正常工作的唯一方法是使用互動式 shell,即bash -ic
在命令之前使用我想像這樣執行,以便ssh $host bash -ic $cmd
載入 conda 環境。不幸的是,這會導致兩個錯誤消息stderr
,我無法阻止:bash: cannot set terminal process group (-1): Inappropriate ioctl for device bash: no job control in this shell
所以我做了一個過濾器,用
sed
它刪除這兩行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
與其費力地試圖消除錯誤消息的症狀,不如消除原因。
這將為
ssh
會話分配一個 tty,以便可以應用終端 ioctl:ssh -t $host "$@"
-t
您可能需要將標誌加倍為-tt
,具體取決於您實際呼叫此行的方式。但是,潛在的問題似乎是您需要一個互動式 shell 來設置 conda 環境。幾乎可以肯定的是,它是在
~/.bashrc
. 您可以.
顯式或提取相關命令並在腳本中使用它們。我不熟悉
conda
自己,但問題是如何在我的 .bashrc 中啟動 conda 環境?在 AskUbuntu 上似乎引用了~/.bashrc
您需要的相關部分。