Use case: Let’s say you logged into a remote machine, you executed a command, it is taking time, and you want to logout but you want the process to keep running in the background, you can follow the below steps to accomplish that.

Suspend process (Ctrl-z)

For example, you have a long running process like below.

# for demo, creating a long process
for i in $(seq 1 10);do;echo $i;sleep 3;done

Ctrl-z suspends the process and gives back the focus to the command prompt; it does not kill the process. (I have seen few developers using Ctrl-z hoping that it would kill the process.).

$ for i in $(seq 1 10);do;echo $i;sleep 3;done
1
^Z[1]  + 72403 suspended  sleep 3

In the above example, the running process is suspended using Ctrl-z, and the focus on the command prompt is given back to us. The process id is 72403, and the job id is 1. You can view the suspended process using the jobs command.

$ jobs
[1]  + suspended  sleep 3

# process still exists
$  ps -ef | grep 72403
  501 72403  2015   0  5:35PM ttys016    0:00.00 sleep 3

At this point, if you try to exit the shell, it will complain.

[1]  + 72403 suspended  sleep 3
zsh: you have suspended jobs.

Note: jobs will show all suspended and running jobs in current shell. If you want to kill the jobs, use kill %n where n is the job number. For example kill %2 to kill job 2.

Resume process (fg or bg)

Now you have 2 options,

  • fg to resume and bring the process running to the foreground (process won’t give prompt to you)
  • bg to resume and keep the process running in the background

The fg option will not help in this use case because it will bring back the process and not focus on the command prompt. Use bg to resume the process and keep it running in the background.

Note: You can use jobid with fg %n or bg %n to resume that specific job.

At this point, we have the process running in the background; now we have the prompt. If you try to exit, you will error like below.

exit
[1]  + 81703 running    for i in $(seq 1 10); do; echo $i; sleep 3; done
zsh: you have running jobs.

Disown process (disown)

disown will disown all processes running in the current shell. Now execute disown -a or disown %1 (to target a specific job).

To summarize, below are the steps that are done to keep the process running background.

# execute long running process
# Ctrl-z to suspend the process
➜  ~ for i in $(seq 1 10);do;echo $i;sleep 3;done > /tmp/tout
^Z[1]  + 83100 suspended  sleep 3

# verify jobs
➜  ~ jobs
[1]  + suspended  sleep 3

# resume the process in background
➜  ~ bg %1            
[1]  + 83100 continued  sleep 3

# disown the process
➜  ~ disown %1

# safe to exit
➜  ~ exit

Sending process to the background using &

By having the & at the end of the command, the process is sent to the background; this is the same as running a command, suspending the process using Ctrl-z, and resuming the process using bg. You still need to use disown to run in the background even after exiting the current shell.

For example, below is the script we want to run in the background.

$ more /tmp/test.sh

for i in $(seq 1 10)
do
    echo $i
    sleep 3
done

Another file which runs above with &.

$ more /tmp/run_test_bg.sh
/tmp/test.sh > /tmp/tout &

Now if you run /tmp/run_test_bg.sh & exit the shell, the process will be still running in background.

Ignore SIGHUP on exit using nohup

Usually, the kernel will send a SIGHUP signal to all the processes that are started if the shell is exited. In this case, you can use nohup. If you do nohup /tmp/test.sh &, you will get appending output to nohup.out. nohup expects the output of the process to be redirected using >; if not given, it will create nohup.out in the folder where nohup is executed, this file will have the output of the process.

We can use nohup /tmp/test.sh > /tmp/tout &, this will redirect the output to a file (and it won’t create nohup.out). If you do not want to capture the output of the process, use /dev/null to redirect process output (nohup command > /dev/null)

Capture process errors 2>&1

If you want to capture process errors that are sent to STDERR, you can redirect errors to STDOUT. The file descriptor for STDERR is 2 and STDOUT is 1, so 2>&1, will redirect all the errors to STDOUT.

With that final command would be like below

nohup /tmp/test.sh 2>&1 > /tmp/tout &

I hope the above helped you understand how to send a process background.

– RC