在后台运行bash命令而不打印作业和进程ID


83

在bash中在后台运行进程非常容易。

$ echo "Hello I'm a background task" &
[1] 2076
Hello I'm a background task
[1]+  Done                    echo "Hello I'm a background task"

但是输出是冗长的。在第一行上打印后台任务的作业ID和进程ID,然后我们获得命令的输出,最后获得作业ID,其状态和触发该作业的命令。

有没有一种方法可以抑制运行后台任务的输出,以使输出看起来与没有“ and”符的情况完全相同?即:

$ echo "Hello I'm a background task" &
Hello I'm a background task

我问的原因是我想将后台进程作为tab-completion命令的一部分运行,因此该命令的输出必须不间断才能有意义。


我想你应该添加2>的/ dev / null以任何你做中使用bash脚本完成
sehe

Answers:


98

与完成无关,但是您可以通过将调用放在子外壳中来抑制输出:

(echo "Hello I'm a background task" &)

3
谢谢,那绝对行得通。不幸的是,当从bash-completion函数运行这样的脚本时,bash似乎要等到子进程完成才给出完成结果。这很不幸,因为这意味着似乎不可能让bash完成触发后台工作人员。
Alex Spurling

13
如果要wait完成后台作业,则不能使用此功能。
arekolek '17

13

以@shellter的答案为基础,这对我有用:

tyler@Tyler-Linux:~$ { echo "Hello I'm a background task" & disown; } 2>/dev/null; sleep .1;
Hello I'm a background task
tyler@Tyler-Linux:~$

我不知道其背后的原因,但我记得在一篇旧文章中,该文章被拒绝阻止bash输出进程ID。


@Tyzoid。我在bash shell(v 4.2.37)中尝试了您的解决方案,并获得了有趣的结果。1.我得到的结果只是;在最后添加。(不睡觉)。2.但是注意到,当我echo STDERR 2>&1在“ next”行上添加内容时,该[1]+ Done ...东西出现了!。3.我的解决方案(如我现在已经指出的)可以使用,ksh并且echo STDERR 2>&1仅产生输出STDERR。好吧,为我们俩生活和学习。祝你们好运。
剥壳机'17

12

在某些较新版本的bash和ksh93中,您可以用子外壳程序或进程组(例如{ ... })将其包围。

/home/shellter $ { echo "Hello I'm a background task" & } 2>/dev/null
Hello I'm a background task
/home/shellter $

5
当我使用花括号时,输出的最后一行仍然显示(我不确定为什么看不到它)。
亚历克斯·斯普林

我完全复制了此内容,但对我不起作用,它仍然显示输出,如@AlexSpurling所说。可能是我做错了,因为其他人对此表示反对,但我担心我必须给它-1。
Mark

1
@Mark:我刚刚对此进行了一些快速测试,我看到的问题是我继续将其ksh93+用作原始外壳程序。此代码按ksh中的承诺工作。但由于OP带有标记,因此bash我了解您的DVD。在@Tyzoid的答案中查看bash测试的结果。祝你们好运!
剥壳机'17

既然您已经明确指出这不适用于bash,所以我将删除-1。
Mark

1
对我来说,这在Bash函数中效果很好,还可以等待该过程wait $!,似乎接受的答案似乎并非如此。
JonatanÖström'17


6

基于此答案,我想出了更简洁,更正确的方法:

silent_background() {
    { 2>&3 "$@"& } 3>&2 2>/dev/null
    disown &>/dev/null  # Prevent whine if job has already completed
}
silent_background date

完善!并且可用于其他东西
user230910 '18

5

尝试:

user@host:~$ read < <( echo "Hello I'm a background task" & echo $! )
user@host:~$ echo $REPLY
28677

并且您已经隐藏了输出PID。请注意,您仍然可以从$ REPLY检索PID


1
太棒了!谢谢
Adham Atta

4

对旧帖子的回复很抱歉,但我认为这对其他人很有用,这是Google的第一个回复。

我在使用此方法(子外壳)和使用“等待”时遇到问题。但是,当我在函数中运行它时,我能够做到这一点:

function a {
    echo "I'm background task $1"
    sleep 5
}

function b {
    for i in {1..10}; do
        a $i &
    done
    wait
} 2>/dev/null

当我运行它时:

$ b
I'm background task 1
I'm background task 3
I'm background task 2
I'm background task 4
I'm background task 6
I'm background task 7
I'm background task 5
I'm background task 9
I'm background task 8
I'm background task 10

在我得到提示之前,有5秒钟的延迟。


1

该subshel​​l解决方案可以工作,但我也希望能够等待后台作业(并且最后不要显示“完成”消息)。$!在当前的交互式外壳程序中,从“子外壳程序”中获取消息是“不可等待的”。对我而言唯一有效的解决方案是使用我自己的等待函数,该函数非常简单:

myWait() {
  while true; do
    sleep 1; STOP=1
    for p in $*; do
      ps -p $p >/dev/null && STOP=0 && break
    done
    ((STOP==1)) && return 0
  done
}

i=0
((i++)); p[$i]=$(do_whatever1 & echo $!)
((i++)); p[$i]=$(do_whatever2 & echo $!)
..
myWait ${p[*]}

很简单。

By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.