bash:在后台启动多个链接命令
我正在尝试使用bash在后台并行运行一些命令。这是我想做的事情:
forloop { //this part is actually written in perl //call command sequence print `touch .file1.lock; cp bigfile1 /destination; rm .file1.lock;`; }
反引号(``)之间的部分产生一个新的shell并连续执行命令。关键是,只有执行完最后一条命令后,对原始程序的控制才返回。我想在后台执行整个语句(我不希望有任何输出/返回值),并且我希望循环继续运行。
直到所有生成的shell完成后,调用程序(具有循环的程序)才会结束。
我可以在perl中使用线程来产生不同的线程,这些线程调用不同的shell,但这似乎是一个过大的选择...
我可以启动一个shell,给它提供一组命令,然后告诉它去后台吗?
解决方案
for command in $commands do "$command" & done wait
命令结尾的"&"号在后台运行," wait"等待直到后台任务完成。
尝试使用&s将命令放在大括号中,如下所示:
{command1 & ; command2 & ; command3 & ; }
这不会创建子外壳,而是在后台执行命令组。
高温超导
我还没有测试过
print `(touch .file1.lock; cp bigfile1 /destination; rm .file1.lock;) &`;
括号意味着在子shell中执行,但这应该不会受到伤害。
谢谢休,做到了:
adrianp@frost:~$ (echo "started"; sleep 15; echo "stopped") started stopped adrianp@frost:~$ (echo "started"; sleep 15; echo "stopped") & started [1] 7101 adrianp@frost:~$ stopped [1]+ Done ( echo "started"; sleep 15; echo "stopped" ) adrianp@frost:~$
其他想法不起作用,因为它们在后台启动每个命令,而不是在命令序列中启动(这对我来说很重要!)。
再次感谢你!
我不知道为什么没人回答正确的解决方案:
my @children; for (...) { ... my $child = fork; exec "touch .file1.lock; cp bigfile1 /destination; rm .file1.lock;" if $child == 0; push @children, $child; } # and if you want to wait for them to finish, waitpid($_) for @children;
这使Perl产生子代来运行每个命令,并允许我们等待所有子代完成后再继续。
顺便一提,
print `some command`
和
system "some command"
将相同的内容输出到stdout,但是第一个具有更高的开销,因为Perl必须捕获所有" some command"的输出
GavinCattell是最接近的(对于bash,IMO),但是正如Mad_Ady指出的那样,它不会处理"锁定"文件。这应该:
如果还有其他待处理的作业,则等待也将等待这些作业。如果只需要等待副本,则可以累积这些PID并仅等待它们。如果没有,我们可以使用" pids"删除3行,但它更通用。
另外,我添加了检查以完全避免复制:
pids= for file in bigfile* do # Skip if file is not newer... targ=/destination/$(basename "${file}") [ "$targ" -nt "$file" ] && continue # Use a lock file: ".fileN.lock" for each "bigfileN" lock=".${file##*/big}.lock" ( touch $lock; cp "$file" "$targ"; rm $lock ) & pids="$pids $!" done wait $pids
顺便说一句,我们似乎正在将新文件复制到FTP存储库(或者类似文件)。如果是这样,我们可以考虑使用复制/重命名策略而不是锁定文件(但这是另一个主题)。