sem–wait在从文件读取的while循环后不等待

我正在尝试在 bash 中使用 GNU parallel 并行运行程序的多个实例,每个实例都有不同的参数。此外,我希望能够从文件中读取这些参数,并让脚本等待所有并行化作业完成。GNU 并行的parallel --semaphore,又名sem,似乎是一种简单的方法来做到这一点。

MCVE

使用修改后的版本基本的例子从sem文档,我创建了一个最小的测试案例来说明我的问题:

while read i; do
    echo -n "$i "
    sem -j 4 "sleep $i && echo $i finished"
done < args.txt
echo
echo 'Started wait'
sem --wait
echo 'Done waiting'

args.txt是一个仅包含以下内容的文件:

1
2
3
4
1
2
3
4

预期与实际输出

我希望看到类似于以下内容的输出:

user@host:~$ ./test-sem.sh
1 2 3 4 
Started wait
1 finished
2 finished
3 finished
4 finished
Done waiting

但是,令人惊讶的是,sem --wait实际上并没有等待任务完成,而是得到如下输出:

user@host:~$ ./test-sem.sh
1 2 3 4 
Started wait
Done waiting
user@host:~$ 1 finished
2 finished
3 finished
4 finished

也就是说,脚本执行并终止,然后sem作业在后台运行并打印各自的输出!为什么会这样?sem --wait初始化所有内容后如何才能真正等待sem在 while 循环中作业?

有趣的是,它正在读取导致问题的文件,而不是 while 循环本身。也就是说,以下按预期工作:

但是我的实际用例有一个包含更复杂参数组合的文件,所以我真的很想从文件中读取参数。

回答

来自gnu 并行文档:

- 信号

  • [...]

  • --semaphore 意味着 --semaphorenametty除非指定了 --semaphorename。

--semaphorename 名称 --id 名称

使用 name 作为信号量的名称。默认是控制 tty 的名称(来自 tty 的输出)。

默认值在交互使用时通常按预期工作,但在脚本名称中使用时应设置。$$ 或 my_task_name 通常是一个很好的价值。

信号量存储在 ~/.parallel/semaphores/

您必须使用相同的名称才能使信号量相同!以下代码:

while read i; do
    tty
done < somefile
tty

输出:

not a tty
/dev/pts/0

所有tty做它调用ttyname标准输入。因为 stdin 来自文件,所以它不再相同。你可以:

  • 手动传递名称 --id <some unique name>
  • 使用不同的文件描述符while read -u 3 ...; do ..; done 3<file

以上是sem–wait在从文件读取的while循环后不等待的全部内容。
THE END
分享
二维码
< <上一篇
下一篇>>