介绍
我有一个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:-t
您可能需要将标志加倍为-tt
,具体取决于您实际调用此行的方式。但是,潜在的问题似乎是您需要一个交互式 shell 来设置 conda 环境。几乎可以肯定的是,它是在
~/.bashrc
. 您可以.
显式或提取相关命令并在脚本中使用它们。我不熟悉
conda
自己,但问题是如何在我的 .bashrc 中激活 conda 环境?在 AskUbuntu 上似乎引用了~/.bashrc
您需要的相关部分。