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

前端 未结 8 1322
余生分开走
余生分开走 2020-12-07 22:09

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

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


        
相关标签:
8条回答
  • 2020-12-07 22:13

    Sorry for the response to an old post, but I figure this is useful to others, and it's the first response on 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:

    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
    

    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.

    0 讨论(0)
  • 2020-12-07 22:15

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

    f() { echo "Hello I'm a background task" >&2; }
    { f 2>&3 &} 3>&2 2>/dev/null
    
    0 讨论(0)
  • 2020-12-07 22:17

    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
    
    0 讨论(0)
  • 2020-12-07 22:26

    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:

    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.

    0 讨论(0)
  • 2020-12-07 22:27

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

    (echo "Hello I'm a background task" &)
    
    0 讨论(0)
  • 2020-12-07 22:29

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

    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.

    0 讨论(0)
提交回复
热议问题