Bash

通過 sed 過濾標準錯誤時,Bash 腳本掛起

  • March 8, 2022

介紹

我有一個bash腳本可以通過ssh. 它在並行版本中使用 GNU parallel,在順序版本中使用 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您需要的相關部分。

引用自:https://unix.stackexchange.com/questions/693399