bash:在后台启动多个链接命令

时间:2020-03-06 15:00:52  来源:igfitidea点击:

我正在尝试使用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存储库(或者类似文件)。如果是这样,我们可以考虑使用复制/重命名策略而不是锁定文件(但这是另一个主题)。