Why does a background process, started in bash, print stdout to screen?

10

8

I have trouble understanding my situation and Google was not very helpful so far.

I started a bash background job:

ping google.com &

First I get the process ID, than Bash prints stdout to screen.

user@host:~$ ping google.com &
[1] 14004
user@host:~$ PING google.com (173.194.44.66) 56(84) bytes of data.
64 bytes from ham02s14-in-f2.1e100.net (173.194.44.66): icmp_seq=1 ttl=54 time=26.3 ms
64 bytes from ham02s14-in-f2.1e100.net (173.194.44.66): icmp_seq=2 ttl=54 time=27.4 ms
64 bytes from ham02s14-in-f2.1e100.net (173.194.44.66): icmp_seq=3 ttl=54 time=29.2 ms
...

This contradicts everything I read today. I have a standard Debian Jessie setup running GNU bash, version 4.3.30(1)-release (x86_64-pc-linux-gnu).

Can anyone explain this to me? Thanks.

Katja Eichelberger

Posted 2015-09-14T18:25:54.320

Reputation: 111

Answers

14

By default, at least for POSIX compliant systems, running a command in background, with &, only detaches stdin, so you'll be able to run other commands. stdout and stderr are still attached to the parent shell.

If you don't want to see stdout and/or stderr you can just redirect them to a file or /dev/null:

command &>log.txt &                #stdout and stderr to log.txt
command 1>/dev/null &               #stdout to /dev/null, stderr still attached to shell
command 1>output.log 2>error.log &  #stdout to output.log, stderr to error.log

petry

Posted 2015-09-14T18:25:54.320

Reputation: 266

On MacOSX this does not work. – Ogier Schelvis – 2018-03-13T09:33:08.117

@OgierSchelvis: Of course it does. – Nick Matteo – 2018-11-27T23:27:28.137

Is there a way to reattach stdin in this case? – alecov – 2019-01-16T04:51:11.893

7

Whether stdout of a background process is shown on the terminal is up to you. You can change the behavior with the stty utility.

Example

The default allows a background process to write to terminal:

$ echo Hello &
[1] 25850
Hello
$

That behavior can be changed with the stty command:

$ stty tostop
$ echo Hello &
[2] 25873

[2]+  Stopped                 echo Hello
$ 

With tostop specified, the background process is stopped when it attempts to write to stdout. If you want to allow it to continue, you can bring it back to the foreground:

$ fg
echo Hello
Hello
$

To switch back, run stty -tostop. After this is run, new background jobs that are created will be allowed to write to stdout. (Existing jobs will not be affected.)

Documentation

man stty explains the tostop option as follows:

* [-]tostop
stop background jobs that try to write to the terminal

The leading * above is used by the man page to identify this option as non-POSIX.

John1024

Posted 2015-09-14T18:25:54.320

Reputation: 13 893