42

For example, when I type ping 8.8.8.8 &, why can we see ping process working? And when I type find / -name '*test*' & , it's also seen on monitor.

Why is that? Is it not really in background?

Braiam
  • 67,791
  • 32
  • 179
  • 269
NoFence
  • 769

3 Answers3

59

The & directs the shell to run the command in the background, i.e, it is forked and run in a separate sub-shell, as a job, asynchronously.

Note that when you put & the output - both stdout and stderr - will still be printed onto the screen. If you do not want to see any output on the screen, redirect both stdout and stderr to a file by:

myscript > ~/myscript.log 2>&1 &

Usually you may want to discard the stderr by redirecting it to /dev/null if you are not worried about analyzing errors later.

You can also even run commands/scripts at the same time, in separate sub-shells. For eg;

./script1 & ./script2 & ./script3 & 

A background job can be brought back to the command line before it finishes with the command:

fg <job-number>

The job-number can be obtained by running

jobs
Zanna
  • 70,465
Ron
  • 20,638
  • Good answer. You could include that one can also use /dev/null as a file to redirect terminal output if one wants to discard the output instead of saving it somewhere. And am I right that 2>&1 redirects stderr to stdout? Maybe you want to clarify that too... Thanks. – Byte Commander Aug 18 '15 at 09:44
  • @ByteCommander Thanks :) edited, hope it is clear now. Yes, you are right, 2>&1 redirects stderr to stdout. – Ron Aug 18 '15 at 10:27
  • 3
    I think it would be worth mentioning that stty tostop will cause background jobs to be suspended if they try to write to the terminal. – kasperd Aug 18 '15 at 11:12
  • cmd_with_params >/dev/null 2>/dev/null & – tgkprog May 22 '17 at 16:11
  • The only downside of doing that is that the order of the outputs to stdout and stderr can get mixed up in the log file. – matthieu Apr 07 '19 at 10:44
  • Great! Just a small correction to @Ron 's answer. job-number in fg should be prefixed with %. ex: fg %2 will bring a job with ID 2 to foreground – mitsos1os Dec 18 '20 at 10:40
12

When you use &, the process is running in background. But its standard output is still the terminal.

In fact, you may run ping 8.8.8.8 & and find / -name '*test*' & at the same time (resulting in a mixed output), but you may not run ping 8.8.8.8 and find / -name '*test*' at the same time on the same shell.

If you don't want to see anything, use something like ping 8.8.8.8 &> /dev/null &.


Additionally, you may want to learn about nohup and disown.

1

I wanted to try and answer specifically the why part:

Why is that?

POSIX implementation of job control, choose to attach STDOUT,STDERR to the parent terminal[1]. I suspect this was the default choice historically perhaps because there used to be just one physical terminal and no emulators back in the day, and so the terminal was the only choice where all jobs could write output to(?)

And STDOUT/ERR seems to be rather hard to get back if you have created the the terminal without a program like screen and your terminal and the shell in it is in-accessible or susceptible to die if you closed your SSH: https://superuser.com/questions/50058/after-the-fact-remote-nohup-with-tcsh/50077#50077 Though as the answer there indicates, it could be done by attaching gdb if the parent shell has disowned the process. It's also an important reason why Terminal Emulators are so useful because interactive processes can't really generally survive without each one getting its own terminal..

[1] https://www.gnu.org/software/libc/manual/html_node/Access-to-the-Terminal.html

sid
  • 11