3

X-posting from unix.SE on recommendation.

I have a bash script called testing saved within /usr/local/bin.

In one Terminal window in macOS I run sudo testing. In a second terminal window, I generate a list of processes:

ps -axo tty,pid,ppid,args | { head -1; grep "bash\|testing" | grep -v grep; }

Which returns as expected:

TTY        PID  PPID ARGS
ttys000  73674 73673 -bash                              # login shell used to run sudo
ttys000  73701 73674 sudo testing                       # sudo process
ttys000  73702 73701 /bin/bash /usr/local/bin/testing   # "testing" bash script being run by sudo
ttys001   3714  3713 -bash                              # second login shell used to generate this process list

However, after quitting the first Terminal window (while testing is still running within it), the process list looks like this:

TTY        PID  PPID ARGS
??       73701     1 sudo testing
??       73702 73701 /bin/bash /usr/local/bin/testing
ttys001   3714  3713 -bash

As expected, the first login shell has been terminated and the second login shell is still running. But the sudo process and its forked (now-orphaned) child, the testing script, are still running!

I suspect this is because the user, not root, is the one closing the Terminal window, and as such does not have the necessary permissions to affect root processes. Is this correct? I feel like I'm missing something basic here. Is there some way to allow the root processes to be terminated by closing the Terminal window?

3

You are talking about orphan processes. As you will see, your question has little to do with sudo. Orphans are assigned to process 1. This process 1 is called init and is a daemon process that continues running until the system is shut down. Here are two simple examples where orphans are created. The macOS is High Sierra which uses bash as the default shell.

If you choose to repeat the examples, you will have to replace the process ids with the ones you get.

When the parent windows terminates, a hang up signal (SIGHUP) is sent to the child processes. Normally, this causes each child processes to terminate. However, if a child chooses not to terminate or is never sent a hangup signal (SIGHUP), then the child can become an orphan.

Example 1

Open a new Terminal window and enter the command shopt -s huponexit. This command is necessary because bash is a login shell. Output shown below.

Last login: Thu Mar 12 17:02:31 on ttys008
Marlin:~ davidanderson$ shopt -s huponexit
Marlin:~ davidanderson$

Enter the command { trap '' hup; sleep 60000; } &, as shown below.

Marlin:~ davidanderson$ { trap '' hup; sleep 60000; } &
[1] 8993
Marlin:~ davidanderson$

Here a new process 8993 is created as job 1. The trap '' hup command causes the hang up signal (SIGHUP) to be ignored. Next, open a another Terminal window and enter the command ps -axo tty,pid,ppid,args 8993, as shown below.

Last login: Thu Mar 12 17:09:12 on ttys008
Marlin:~ davidanderson$ ps -axo tty,pid,ppid,args 8993
TTY        PID  PPID ARGS
ttys008   8993  8972 -bash
Marlin:~ davidanderson$ 

This shows the first window was assigned ttys008 and has a process id of 8972. Next, the first window is closed. In the popup window, Terminate is selected. A hang up signal (SIGHUP) is sent to process 8972, which is ignored. Process 8972 is now orphaned and will be assigned to process 1. Repeating the ps -axo tty,pid,ppid,args 8993 command in the second window will show this. See below.

Marlin:~ davidanderson$ ps -axo tty,pid,ppid,args 8993
TTY        PID  PPID ARGS
??        8993     1 -bash
Marlin:~ davidanderson$

Finally, the commands shown below are entered to send a terminal signal (SIGTERM) to process 8993 and show that the process has terminated.

Marlin:~ davidanderson$ kill 8993
Marlin:~ davidanderson$ ps -axo tty,pid,ppid,args 8993
TTY        PID  PPID ARGS
Marlin:~ davidanderson$

Example 2

This is basically the same as example 1, except instead of having the process ignore the hangup signal (SIGHUP), the disown %1 command is used to prevent a hangup signal (SIGHUP) from being sent to the process. Open a new Terminal window and enter the command shopt -s huponexit. This command is necessary because bash is a login shell. Output shown below.

Last login: Thu Mar 12 17:02:31 on ttys008
Marlin:~ davidanderson$ shopt -s huponexit
Marlin:~ davidanderson$

Next, enter sleep 60000 & followed by disown %1. The %1 parameter represents job 1. The results are shown below.

Last login: Thu Mar 12 17:14:54 on ttys010
Marlin:~ davidanderson$ sleep 60000 &
[1] 9139
Marlin:~ davidanderson$ disown %1
Marlin:~ davidanderson$

In the second window, enter ps -axo tty,pid,ppid,args 9139. The results are shown below.

Marlin:~ davidanderson$ ps -axo tty,pid,ppid,args 9139
TTY        PID  PPID ARGS
ttys008   9139  9130 sleep 60000
Marlin:~ davidanderson$

After closing the third window, enter ps -axo tty,pid,ppid,args 9139 in the second window. The results are shown below. Another orphan has been created.

Marlin:~ davidanderson$ ps -axo tty,pid,ppid,args 9139
TTY        PID  PPID ARGS
??        9139     1 sleep 60000
Marlin:~ davidanderson$ 

Finally, enter kill 9139 and ps -axo tty,pid,ppid,args 9139, as shown below.

Marlin:~ davidanderson$ kill 9139
Marlin:~ davidanderson$ ps -axo tty,pid,ppid,args 9139
TTY        PID  PPID ARGS
Marlin:~ davidanderson$ 

References

Orphan process
Zombie process
init
Daemon

| improve this answer | |
  • Thanks so much for the incredibly detailed explanation! It looks like in addition to trap '' hup and disown, sudo commands will also ignore SIGHUP. Is there any way that I can kill the sudo process by closing the Terminal window? – NomadGnome Mar 12 at 23:56
  • The sudo command does past the SIGHUP signal to the script provided the sender is a root user. Which is basically what you posted in you question. I can not exactly reproduce the example posted in you question. When I try to close the window, I do not get an orphan unless the script is running in the background. – David Anderson Mar 14 at 8:16
  • Interesting. Not sure how much it would matter, but my script is just a while true; do ... loop, and I've tried on both macOS 10.14 and 10.13 with the same result. – NomadGnome Mar 17 at 18:42

You must log in to answer this question.

Not the answer you're looking for? Browse other questions tagged .