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

Mad*_*Ady 44 bash command background

我试图在后台使用bash在paralel中运行一些命令.这是我正在尝试做的事情:

forloop {
  //this part is actually written in perl
  //call command sequence
  print `touch .file1.lock; cp bigfile1 /destination; rm .file1.lock;`;
}
Run Code Online (Sandbox Code Playgroud)

反引号(``)之间的部分产生一个新的shell并连续执行命令.问题是,只有在执行完最后一个命令后,对原始程序的控制才会返回.我想在后台执行整个语句(我不期待任何输出/返回值),我想循环继续运行.

调用程序(具有循环的程序)在所有生成的shell完成之前不会结束.

我可以在perl中使用线程来生成调用不同shell的不同线程,但它似乎有点过分......

我可以启动一个shell,给它一组命令并告诉它去后台吗?

Hug*_*len 30

我没有测试过这个但是怎么样

print `(touch .file1.lock; cp bigfile1 /destination; rm .file1.lock;) &`;
Run Code Online (Sandbox Code Playgroud)

括号表示在子shell中执行但不应该受到伤害.

  • 你不想要打印或反引号 - 即使这些命令确实提供了有用的输出在后台运行它们也意味着反引号看不到它 (5认同)
  • 非常感谢!它还帮助我解决了一个不同的问题,使用bash脚本,其中一些对外部进程的调用仍在stdout中打印输出,即使我使用"&>/dev/null",但解决了调用方式:\`(./ call_the_proccess &>/dev/null)&\` (4认同)
  • (我不喜欢反叛,我发现$()更容易阅读,但这与此无关) (2认同)

Mad*_*Ady 20

谢谢休,这样做了:

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:~$ 
Run Code Online (Sandbox Code Playgroud)

其他想法不起作用,因为它们在后台启动每个命令,而不是命令序列(这在我的情况下很重要!).

再次感谢你!

  • 除了调试一点时间外,你不会"睡3" (10认同)

lec*_*hup 19

另一种方法是使用以下语法:

{ command1; command2; command3; } &
wait
Run Code Online (Sandbox Code Playgroud)

请注意,它&位于命令组的末尾,而不是在每个命令之后.最后一个命令之后的分号是必要的,第一个括号之后和最后一个括号之前的空格也是必需的.所述wait在端部保证了衍生的子进程(命令组)结束之前父进程不杀死.

你也可以做重定向stderr等奇特的东西stdout:

{ command1; command2; command3; } 2>&2 1>&1 &
Run Code Online (Sandbox Code Playgroud)

你的例子看起来像:

forloop() {
    { touch .file1.lock; cp bigfile1 /destination; rm .file1.lock; } &
}
# ... do some other concurrent stuff
wait # wait for childs to end
Run Code Online (Sandbox Code Playgroud)


Gav*_*ell 14

for command in $commands
do
    "$command" &
done
wait
Run Code Online (Sandbox Code Playgroud)

命令末尾的&符号在后台运行它,wait等待后台任务完成.

  • 不行,因为每个命令都会在后台运行,而不是命令序列. (7认同)
  • @Gavin - 你需要**$ command**(注意"$"). (6认同)
  • 如果命令包含空格这不起作用,他们通常会这样做 (4认同)

NVR*_*RAM 5

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
Run Code Online (Sandbox Code Playgroud)

顺便说一句,看起来您正在将新文件复制到FTP存储库(或类似文件).如果是这样,您可以考虑复制/重命名策略而不是锁定文件(但这是另一个主题).