8

From my understanding, jobs are pipelines (http://web.mit.edu/gnu/doc/html/features_5.html) started from a certain shell and you can manage these jobs (fg, bg, ctrl-z) from within this shell. A job can consist of multiple processes/commands.

My question is what happens to these jobs when the original, containing shell exits? Suppose huponexit is not set so background processes keep running after the shell exits.

Suppose I have done:

run.sh | grep 'abc' &

[1] job_id

Then I exit this shell. I'll enter a new shell and run jobs and see nothing obviously. But I can do ps aux | grep run.sh and see this process running and I'll also do ps aux | grep grep and see the process for grep 'abc' running too.

Is there a way to just get the job ID for the full pipeline so that I can kill it in one go, or do I have to kill all the processes separately from another shell once I have exited the original shell? ( I have tried the latter and it works, but it seems like a hassle to keep track of all the processes. )

6

When the shell exits, it might send the HUP signal to background jobs, and this might cause them to exit. The SIGHUP signal is only sent if the shell itself receives a SIGHUP, i.e. only if the terminal goes away (e.g. because the terminal emulator process dies) and not if you exit the shell normally (with the exit builtin or by typing Ctrl+D). See In which cases is SIGHUP not sent to a job when you log out? and Is there any UNIX variant on which a child process dies with its parent? for more details. In bash, you can set the huponexit option to also send SIGHUP to background jobs on a normal exit. In ksh, bash and zsh, calling disown on a job removes it from the list of jobs to send SIGHUP to. A process that receives SIGHUP may ignore or catch the signal, and then it won't die. Using nohup when you run a program makes it immune to SIGHUP.

If the process isn't killed due to a possible SIGHUP then it remains behind. There's nothing left to relate it to job numbers in the shell.

The process may still die if it tries to access the terminal but the terminal no longer exists. That depends how the program reacts to a non-existent terminal.

If the job contains multiple processes (e.g. a pipeline), then all these processes are in one process group. Process groups were invented precisely to capture the notion of a shell job that is made up of multiple related processes. You can see processes grouped by process group by displaying their process group ID (PGID — normally the process ID of the first process in the group), e.g. with ps l under Linux or something like ps -o pid,pgid,tty,etime,comm portably.

You can kill all the processes in a group by passing a negative argument to kill. For example, if you've determined that the PGID for the pipeline you want to kill is 1234, then you can kill it with

kill -TERM -1234
2

In general they still run, but you should use nohup, if you forgot or changed your mind use disown.

mike@mike-laptop4:~$ sleep 500
^Z
[1]+  Stopped                 sleep 500
mike@mike-laptop4:~$ bg
[1]+ sleep 500 &
mike@mike-laptop4:~$ jobs
[1]+  Running                 sleep 500 &
mike@mike-laptop4:~$ disown %1
mike@mike-laptop4:~$ jobs
mike@mike-laptop4:~$ 
  • and to kill you can check the parent bash with ps -ef --forest, if the bash has background functions you may need to also kill these – mikejonesey Oct 23 '16 at 20:12

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.