|unix.ba||text • research • links • about|
If you are an old-school UNIX user, chances are that you prefer the traditional way of switching to root with su rather than using its more convenient counterpart sudo. If you need to switch between regular user and root frequently within a single session, you might find it inconvenient to have to type in the root password each time you execute su.
A convenient solution for this problem would be to use the shell's job control functionality and type CTRL-Z to suspend the root shell, then re-activate it with fg when it's needed again. Unfortunately, this doesn't work for the reasons discussed below.
Luckily, it is possible to emulate this functionality by manually sending a SIGSTOP signal to the root shell. Here is an example session:
$ whoami user $ su - Password: password not shown # whoami root # kill -STOP $$ + Stopped su - $ whoami user $ fg su - # whoami root # █
So instead of pressing CTRL-Z, we execute kill -STOP $$ from within the root shell to suspend it, which drops us back to the original user shell. Later on, we can activate the root shell again by bringing it into the foreground with fg.
To understand why suspending the root shell with CTRL-Z doesn't work, let us examine the relationships between processes involved in this entire session. The session is started with the user shell, from within which we execute su to get the root shell. We then use ps and grep to display part of the process tree associated with our terminal (whose name we obtained with tty):
$ su - Password: password not shown # tty /dev/pts/1 # ps auf | grep pts/1 user 1812 0.3 0.0 116540 4640 pts/1 Ss 14:34 0:00 sh root 1837 0.3 0.0 200372 5996 pts/1 S 14:35 0:00 \_ su - root 1842 0.6 0.0 116452 4620 pts/1 S 14:35 0:00 \_ -sh root 1872 0.0 0.0 123356 2608 pts/1 R+ 14:35 0:00 \_ ps auf root 1873 0.0 0.0 112672 2168 pts/1 S+ 14:35 0:00 \_ grep pts/1 # █
At the top of the hierarchy we see the original user shell, below which is su running as its child process. Upon successful authentication, su spawned another process, in which the root shell is being executed. Finally, we see ps and grep running as children of the root shell.
What happens when we press CTRL-Z while interacting with the root shell?
The root shell interprets the CTRL-Z key combination as an instruction to suspend the currently executing foreground job. This works only with processes running as children of the root shell, not the root shell itself nor its parents. What we would like, however, is instructing the user shell to suspend su and its children. Since this cannot be achieved with CTRL-Z, as a workaround, we manually stop the root shell by sending it the SIGSTOP signal. This, in turn, makes su stop itself, which is detected by the user shell, whose job control moves su into the background and marks its state as stopped. This enables us to re-activate su at a later time by using the job control command fg. Once activated, su returns the root shell to the foreground by sending it a SIGCONT signal.
• • •