Is there a way to make bash job control quiet?

前端 未结 5 1375
无人及你
无人及你 2020-12-02 13:25

Bash is quite verbose when running jobs in the background:

$ echo toto&
toto
[1] 15922
[1]+  Done                    echo toto

Since I\

相关标签:
5条回答
  • 2020-12-02 13:43

    Note: The following applies to interactive Bash sessions. In scripts, job-control messages are never printed.

    There are 2 basic scenarios for silencing Bash's job-control messages:


    Launch-and-forget:

    CodeGnome's helpful answer answer suggests enclosing the background command in a simple subshell - e.g, (sleep 10 &) - which effectively silences job-control messages - both on job creation and on job termination.

    This has an important side effect:

    • By using control operator & inside the subshell, you lose control of the background job - jobs won't list it, and neither %% (the spec. (ID) of the most recently launched job) nor $! (the PID of the (last) process launched (as part of) the most recent job) will reflect it.[1]

    For launch-and-forget scenarios, this is not a problem:

    • You just fire off the background job,
    • and you let it finish on its own (and you trust that it runs correctly).

    [1] Conceivably, you could go looking for the process yourself, by searching running processes for ones matching its command line, but that is cumbersome and not easy to make robust.


    Launch-and-control-later:

    If you want to remain in control of the job, so that you can later:

    • kill it, if need be.
    • synchronously wait (at some later point) for its completion,

    a different approach is needed:

    • Silencing the creation job-control messages is handled below, but in order to silence the termination job-control messages categorically, you must turn the job-control shell option OFF:

      • set +m (set -m turns it back on)
      • Caveat: This is a global setting that has a number of important side effects, notably:
        • Stdin for background commands is then /dev/null rather than the current shell's.
        • The keyboard shortcuts for suspending (Ctrl-Z) and delay-suspending (Ctrl-Y) a foreground command are disabled.
        • For the full story, see man bash and (case-insensitively) search for occurrences of "job control".
    • To silence the creation job-control messages, enclose the background command in a group command and redirect the latter's stderr output to /dev/null

      { sleep 5 & } 2>/dev/null
      

    The following example shows how to quietly launch a background job while retaining control of the job in principle.

    $ set +m; { sleep 5 & } 2>/dev/null # turn job-control option off and launch quietly
    $ jobs # shows the job just launched; it will complete quietly due to set +m 
    

    If you do not want to turn off the job-control option (set +m), the only way to silence the termination job-control message is to either kill the job or wait for it:

    Caveat: There are two edge cases where this technique still produces output:

    • If the background command tries to read from stdin right away.
    • If the background command terminates right away.

    To launch the job quietly (as above, but without set +m):

    $ { sleep 5 & } 2>/dev/null
    

    To wait for it quietly:

    $ wait %% 2>/dev/null    # use of %% is optional here
    

    To kill it quietly:

    { kill %% && wait; } 2>/dev/null
    

    The additional wait is necessary to make the termination job-control message that is normally displayed asynchronously by Bash (at the time of actual process termination, shortly after the kill) a synchronous output from wait, which then allows silencing.

    But, as stated, if the job completes by itself, a job-control message will still be displayed.

    0 讨论(0)
  • 2020-12-02 13:43

    Interactively, no. It will always display job status. You can influence when the status is shown using set -b.

    There's nothing preventing you from using the output of your commands (via pipes, or storing it variables, etc). The job status is sent to the controlling terminal by the shell and doesn't mix with other I/O. If you're doing something complex with jobs, the solution is to write a separate script.

    The job messages are only really a problem if you have, say, functions in your bashrc which make use of job control which you want to have direct access to your interactive environment. Unfortunately there's nothing you can do about it.

    0 讨论(0)
  • 2020-12-02 13:45

    One solution (in bash anyway) is to route all the output to /dev/null

        echo 'hello world' > /dev/null &
    

    The above will not give you any output other than the id for the bg process.

    0 讨论(0)
  • 2020-12-02 13:56

    You can use parentheses to run a background command in a subshell, and that will silence the job control messages. For example:

    (sleep 10 & )
    
    0 讨论(0)
  • 2020-12-02 13:56

    Wrap it in a dummy script:

    quiet.sh:

    #!/bin/bash
    $@ &
    

    then call it, passing your command to it as an argument:

    ./quiet.sh echo toto
    

    You may need to play with quotes depending on your input.

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