sem --wait 在从文件读取的 while 循环后不等待
sem --wait does not wait after a while loop that reads from a file
我正在尝试在 bash 到 运行 中并行使用 GNU 并行程序的多个实例,每个实例都有不同的参数。此外,我希望能够从文件中读取这些参数,并让脚本等待所有并行化作业完成。 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'
此处,args.txt
是一个仅包含以下内容的文件:
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
作业后,如何让 sem --wait
真正等待?
有趣的是,导致问题的是读取文件,而不是 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
[...]
--semaphore implies --semaphorename tty
unless --semaphorename is
specified.
--semaphorename name
--id name
Use name as the name of the semaphore. Default is the name of the controlling tty (output from tty).
The default normally works as expected when used interactively, but when used in a script name should be set. $$ or my_task_name are often a good value.
The semaphore is stored in ~/.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
。
我正在尝试在 bash 到 运行 中并行使用 GNU 并行程序的多个实例,每个实例都有不同的参数。此外,我希望能够从文件中读取这些参数,并让脚本等待所有并行化作业完成。 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'
此处,args.txt
是一个仅包含以下内容的文件:
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
作业后,如何让 sem --wait
真正等待?
有趣的是,导致问题的是读取文件,而不是 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
[...]
--semaphore implies --semaphorename
tty
unless --semaphorename is specified.--semaphorename name --id name
Use name as the name of the semaphore. Default is the name of the controlling tty (output from tty).
The default normally works as expected when used interactively, but when used in a script name should be set. $$ or my_task_name are often a good value.
The semaphore is stored in ~/.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
。