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

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/7686989/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-09-09 21:06:14  来源:igfitidea点击:

Running bash commands in the background without printing job and process ids

bashbash-completion

提问by Alex Spurling

To run a process in the background in bash is fairly easy.

在 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"

However the output is verbose. On the first line is printed the job id and process id of the background task, then we have the output of the command, finally we have the job id, its status and the command which triggered the job.

然而,输出是冗长的。第一行打印了后台任务的作业 ID 和进程 ID,然后是命令的输出,最后是作业 ID、状态和触发作业的命令。

Is there a way to suppress the output of running a background task such that the output looks exactly as it would without the ampersand at the end? I.e:

有没有办法抑制运行后台任务的输出,使输出看起来与最后没有&符号的输出完全一样?IE:

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

The reason I ask is that I want to run a background process as part of a tab-completion command so the output of that command must be uninterrupted to make any sense.

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

回答by Dimitre Radoulov

Not related to completion, but you could supress that output by putting the call in a subshell:

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

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

回答by shellter

In some newer versions of bash and in ksh93 you can surround it with a sub-shell or process group (i.e. { ... }).

在一些较新版本的 bash 和 ksh93 中,您可以用子 shell 或进程组(即{ ... })包围它。

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

回答by Tyzoid

Building off of @shellter's answer, this worked for me:

基于@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:~$

I don't know the reasoning behind this, but I remembered from an old post that disown prevents bash from outputting the process ids.

我不知道这背后的原因,但我从一篇旧帖子中记得,disown 会阻止 bash 输出进程 ID。

回答by pajamian

Building on the above answer, if you need to allow stderr to come through from the command:

基于上述答案,如果您需要允许 stderr 从命令中通过:

f() { echo "Hello I'm a background task" >&2; }
{ f 2>&3 &} 3>&2 2>/dev/null

回答by Tom Hale

Based on this answer, I came up with the more concise and correct:

基于这个答案,我想出了更简洁和正确的:

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

回答by mark_infinite

Try:

尝试:

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

And you have hidden both the outputand the PID. Note that you can still retrieve the PIDfrom $REPLY

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

回答by The Tomahawk

Sorry for the response to an old post, but I figure this is useful to others, and it's the first response on Google.

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

I was having an issue with this method (subshells) and using 'wait'. However, as I was running it inside a function, I was able to do this:

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

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

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

And when I run it:

当我运行它时:

$ 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

And there's a delay of 5 seconds before I get my prompt back.

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

回答by ExpertNoob1

The subshell solution works, but I also wanted to be able to wait on the background jobs (and not have the "Done" message at the end). $!from a subshell is not "waitable" in the current interactive shell. The only solution that worked for me was to use my own wait function, which is very simple:

subshel​​l 解决方案有效,但我也希望能够等待后台作业(并且最后没有“完成”消息)。$!在当前交互式 shell 中,来自子 shell 不是“可等待的”。唯一对我有用的解决方案是使用我自己的等待函数,这非常简单:

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[*]}

Easy enough.

很容易。