bash:默默杀死后台功能进程

rou*_*ble 55 unix linux bash shell scripting

贝壳大师,

我有一个bash shell脚本,我在其中启动一个后台函数,比如说foo(),显示一个无聊和长命令的进度条:

foo()
{
    while [ 1 ]
    do
        #massively cool progress bar display code
        sleep 1
    done
}

foo &
foo_pid=$!

boring_and_long_command
kill $foo_pid >/dev/null 2>&1
sleep 10
Run Code Online (Sandbox Code Playgroud)

现在,当foo我去世时,我看到以下文字:

/home/user/script: line XXX: 30290 Killed                  foo
Run Code Online (Sandbox Code Playgroud)

这完全摧毁了我的,非常酷的进度条显示的令人敬畏.

我如何摆脱这条消息?

Mar*_*gar 60

kill $foo_pid
wait $foo_pid 2>/dev/null
Run Code Online (Sandbox Code Playgroud)

顺便说一句,我不知道你的大量进展吧,但你见过Pipe Viewer(pv)吗? http://www.ivarch.com/programs/pv.shtml

  • 好东西; 我建议`{kill $ foo_pid && wait $ foo_pid; } 2>/dev/null`以便使目标进程不再存在的情况变得沉默. (4认同)

pix*_*pix 30

刚刚遇到这个问题,并意识到"被拒绝"是我们正在寻找的.

foo &
foo_pid=$!
disown

boring_and_long_command
kill $foo_pid
sleep 10
Run Code Online (Sandbox Code Playgroud)

正在打印死亡消息,因为该过程仍在被监视的"作业"的shell列表中.disown命令将从此列表中删除最近生成的进程,以便在被杀死时不会生成调试消息,即使使用SIGKILL(-9)也是如此.

  • 此外,似乎使用`disown`除了将当前shell与后台进程解除关联之外还有其他含义:http://unix.stackexchange.com/a/148698/54804 (4认同)
  • 优秀!这应该是公认的答案. (2认同)

Ser*_*kov 5

尝试用线替换你kill $foo_pid >/dev/null 2>&1的线:

(kill $foo_pid 2>&1) >/dev/null
Run Code Online (Sandbox Code Playgroud)

更新:

由于@ mklement0在他的评论中解释的原因,这个答案是不正确的:

这个答案对后台作业无效的原因是Bash本身异步,在kill命令完成后,输出一个关于被杀死作业的状态消息,你不能直接压制 - 除非你使用wait,就像在接受的答案中一样.


rou*_*ble 5

这个“黑客”似乎有效:

# Some trickery to hide killed message
exec 3>&2          # 3 is now a copy of 2
exec 2> /dev/null  # 2 now points to /dev/null
kill $foo_pid >/dev/null 2>&1
sleep 1            # sleep to wait for process to die
exec 2>&3          # restore stderr to saved
exec 3>&-          # close saved version
Run Code Online (Sandbox Code Playgroud)

它的灵感来自这里。世界秩序已经恢复。


bbb*_*bco 5

这是我针对类似问题提出的解决方案(希望在长时间运行的过程中显示时间戳)。这实现了killsub函数,只要您知道pid,就可以悄悄地杀死任何子shell。请注意,陷阱指令必须包括以下内容:如果脚本被中断,则子外壳程序将不会继续运行。

foo()
{
    while [ 1 ]
    do
        #massively cool progress bar display code
        sleep 1
    done
}

#Kills the sub process quietly
function killsub() 
{

    kill -9 ${1} 2>/dev/null
    wait ${1} 2>/dev/null

}

foo &
foo_pid=$!

#Add a trap incase of unexpected interruptions
trap 'killsub ${foo_pid}; exit' INT TERM EXIT

boring_and_long_command

#Kill foo after finished
killsub ${foo_pid}

#Reset trap
trap - INT TERM EXIT
Run Code Online (Sandbox Code Playgroud)