介绍
我有一个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