如何解决sem --wait 在从文件读取的 while 循环后不等待 MCVE预期与实际输出
我正在尝试在 bash 中使用 GNU parallel 来并行运行一个程序的多个实例,每个实例都有不同的参数。此外,我希望能够从文件中读取这些参数,并让脚本等待所有并行化作业完成。 GNU parallel 的 parallel --semaphore
,又名 sem
,似乎是一种简单的方法。
MCVE
使用 sem
文档中 basic example 的修改版本,我创建了一个最小的测试用例来说明我的问题:
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'
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
作业在后台运行并打印各自的输出!为什么会这样?在 while 循环内初始化所有 sem --wait
作业后,如何让 sem
真正等待?
有趣的是,导致问题的是从文件中读取,而不是 while 循环本身。也就是说,以下按预期工作:
i=1;
while (( $i <= 4 )); do
echo -n "$i "
sem -j 4 "sleep $i && echo $i finished"
let i=i+1
done
echo
echo 'Started wait'
sem --wait
echo 'Done waiting'
但我的实际用例有一个包含更复杂参数组合的文件,所以我真的很想从文件中读取参数。
解决方法
--信号量
-
[...]
-
--semaphore 暗示 --semaphorename
tty
除非 --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
都会在 stdin 上调用 ttyname
。因为 stdin 来自文件,所以它不再相同。您可以:
- 使用
--id <some unique name>
手动传递名称 - 使用不同的文件描述符
while read -u 3 ...; do ..; done 3<file
。
版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。