我试图在后台使用bash在paralel中运行一些命令.这是我正在尝试做的事情:
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,给它一组命令并告诉它去后台吗?
我没有测试过这个但是怎么样
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:~$
其他想法不起作用,因为它们在后台启动每个命令,而不是命令序列(这在我的情况下很重要!).
再次感谢你!
另一种方法是使用以下语法:
{ command1; command2; command3; } & wait
请注意,它&
位于命令组的末尾,而不是在每个命令之后.最后一个命令之后的分号是必要的,第一个括号之后和最后一个括号之前的空格也是必需的.所述wait
在端部保证了衍生的子进程(命令组)结束之前父进程不杀死.
你也可以做重定向stderr
等奇特的东西stdout
:
{ command1; command2; command3; } 2>&2 1>&1 &
你的例子看起来像:
forloop() { { touch .file1.lock; cp bigfile1 /destination; rm .file1.lock; } & } # ... do some other concurrent stuff wait # wait for childs to end
for command in $commands do "$command" & done wait
命令末尾的&符号在后台运行它,wait
等待后台任务完成.
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存储库(或类似文件).如果是这样,您可以考虑复制/重命名策略而不是锁定文件(但这是另一个主题).