这似乎是一件非常微不足道的事情,但我很困难.
要在后台执行某些操作,请使用&:
>>> sleep 5 &
[1] 21763
>>> #hit enter
[1]+ Done sleep 5
Run Code Online (Sandbox Code Playgroud)
但有一个.bashrc的来源背景脚本输出作业信息是非常令人沮丧的,所以你可以做这个来解决它:
>>> (sleep 5 &)
Run Code Online (Sandbox Code Playgroud)
好的,所以现在我想获得sleepfor wait或的PID kill.不幸的是它在子shell中运行所以典型的$!方法不起作用:
>>> echo $!
21763
>>> (sleep 5 &)
>>> echo $!
21763 #hasn't changed
Run Code Online (Sandbox Code Playgroud)
所以我想,也许我可以通过这种方式获得子shell来打印它的PID:
>>> sleep 5 & echo $!
[1] 21803 #annoying job-start message (stderr)
21803 #from the echo
Run Code Online (Sandbox Code Playgroud)
但是现在当我在子shell中抛出它时,无论我如何尝试捕获子shell的stdout,它似乎都会阻塞直到sleep完成.
>>> pid=$(sleep 5 & echo $!)
Run Code Online (Sandbox Code Playgroud)
如何在后台运行某些内容,获取其PID并停止打印作业信息和" Done"?
召唤进程时,将shell的stderr重定向到>/dev/null该召唤实例.我们可以通过复制fd 2来做到这一点,这样我们仍然可以使用重复的fd进行处理.我们在一个块中执行所有这些操作以使重定向临时:
{ sleep 5 2>&3 & pid=$!; } 3>&2 2>/dev/null
Run Code Online (Sandbox Code Playgroud)
现在为了防止以后显示"完成"消息,我们从作业表中排除了该过程,这是通过以下disown命令完成的:
{ sleep 5 2>&3 & disown; pid=$!; } 3>&2 2>/dev/null
Run Code Online (Sandbox Code Playgroud)
如果未启用作业控制则没有必要.可以使用set +m或禁用作业控制shopt -u -o monitor.
我们也可以使用命令替换来召唤进程.我们唯一的问题是进程仍然将自己挂钩到$()读取stdout 创建的管道,但我们可以通过在它之前复制原始stdout然后使用该文件描述符来解决这个问题:
{ pid=$( sleep 200s >&3 & echo $! ); } 3>&1
Run Code Online (Sandbox Code Playgroud)
如果我们将进程的输出重定向到某个地方,则可能没有必要/dev/null:
pid=$( sleep 200s >/dev/null & echo $! )
Run Code Online (Sandbox Code Playgroud)
与流程替换类似:
{ read pid < <(sleep 200s >&3 & echo $!); } 3>&1
Run Code Online (Sandbox Code Playgroud)
有些人可能会说重定向不是必需的,process substitution但问题是可能正在访问它的进程stdout会很快死亡.例如:
$ function x { for A in {1..100}; do echo "$A"; sleep 1s; done }
$ read pid < <(x & echo $!)
$ kill -s 0 "$pid" &>/dev/null && echo "Process active." || echo "Process died."
Process died.
$ read pid < <(x > /dev/null & echo $!)
$ kill -s 0 "$pid" &>/dev/null && echo "Process active." || echo "Process died."
Process active.
Run Code Online (Sandbox Code Playgroud)
exec 3>&1这样您就可以pid=$( sleep 200s >&3 & echo $! )在下一行中使用.