disown command in Linux explained with Example usage
Executing long running process in Linux is a norm. For example, imagine you are compiling a very large program, and that is going to take really long. May be hours or even days. So basically you need a method to keep your program running longer even after you logout of the server. To put it in other words, you want a program to be running continuesly even after your shell session ends.
There are tools and even features of bash shell that you can use for this purpose. In this article, we will be discussing one such feature of bash shell called disown.
Well you might be thinking why am I calling this a feature of bash shell?. This is because disown command itself is part of bash shell. Its basically a shell builtin command similar to cd, pwd etc.
There is a command called type in bash shell, which you can use to find out whether a command is a shell feature or an external command. See below.
root@localhost:~# type cd cd is a shell builtin root@localhost:~# type pwd pwd is a shell builtin root@localhost:~# type disown disown is a shell builtin
Well type command itself is part of bash shell..See blow..root@localhost:~# type type type is a shell builtin
There is parent and child relationship for each and every process that runs in linux operating system. The below article might be helpful in understanding a bit more about processes in Linux.
Let's first log into a linux machine, then trigger a command and put it in background and see what happens when we logout.
ubuntu@localhost:~$ cat /dev/random > /dev/null &
The above command will start a process and put it in background. Now let's see who is the parent process of the command that we triggered. Parent processes of all running processes in Linux can be found using the below command.
ubuntu@localhost:~$ ps xao pid,ppid,comm
This will show the pid and the parent process id as well as the command that triggered the process. We can easily find the parent process id of our process(cat command in this case) using the above command.
ubuntu@localhost:~$ ps xao pid,ppid,comm | grep cat 11391 10659 cat /dev/random
So the parent process ID of our cat command is 10659, which is evident from the about result. Let's now see what actually is 10659.
ubuntu@localhost:~$ ps aux | grep 10659 ubuntu 10659 0.0 0.1 22916 5380 pts/1 Ss 14:01 0:00 -bash ubuntu 11401 0.0 0.0 10432 672 pts/1 S+ 14:42 0:00 grep --color=auto 10659
From the above output we can clearly see that 10659 is the bash shell process. The shell session where we are currently logged into. Anything that you trigger from this shell session, the bash shell process will become the parent. In our example we triggered a cat command and our bash shell process became its parent.
When you logout of the shell, the shell process will be killed. Which will cause all its children to be killed as well.
Basically when you logout from the shell, SIGHUP signal will be send to all children of the shell. So cat command will also be killed when you logout. Let's try logging out of the shell and see what happens.
ubuntu@localhost:~$ logout There are stopped jobs. ubuntu@localhost:~$ logout
In some cases, when you try to logout of the machine using CTRL + D OR logout command or exit command, the shell will alert you by saying that there are jobs that are owned by it, and is currently stopped. If you are willing to logout, you will have to execute CTRL + D OR logout command or exit command once again.
Now again login to the same machine, and see if the cat command process is still there. It wont be there. This is because when you logged out, the child process (cat command), also got a SIGHUP signal from parent shell.
One more important thing to note here is a bash shell setting called huponexit. Almost all modern distributions by default has this option disabled.
If you have huponexit option disabled, bash shell process will not send SIGHUP signal to the child processes launched by the shell on exit. You can toggle this setting in bash using the bash builtin command called shopt.
ubuntu@localhost:~$ shopt autocd off cdable_vars off cdspell off checkhash off checkjobs off checkwinsize on cmdhist on compat31 off compat32 off compat40 off compat41 off compat42 off complete_fullquote on
if you execute shopt command as shown above, it will print the current status of the settings (that is whether something is enabled or disabled ). Let's see the status of the setting called huponexit.
ubuntu@localhost:~$ shopt | grep hup huponexit off
You can enable this setting by using the below command.
shopt -s huponexit
Disabling this can be done using the below command(disabling will not send SIGHUP signal to processes launched by shell on exit, which is a good idea)shopt -u huponexit
To make the setting configured by shopt command permanent, you need to make an entry(simply enter the shopt commnd with required option) inside the file .bashrc (located inside users home directory).
So what happens if you have the option huponexit disabled. If you have it disabled, the shell wont sent SIGHUP signal to the child process(means your processes and commands will continue to run even after shell exits.). So the use of disown command becomes irrelevant in this case.
So who will be the parent of the process that you triggered after the shell exits?. Well INIT process will become the parent of the process that you triggered after the shell exits.
There are two solution for keeping a process running even after logging out of a shell that has huponexit enabled. You can use either nohup command or disown command.
nohup command needs to be prepended to the command that you want to keep running after you logout. The basic syntax of nohup command is nohup command &
However, nohup command is not quite helpful for already running processes. This is where disown command comes handy.
disown command works on jobs. Basically it deals with job table associated with shell. Currently running jobs that you triggered and kept in background can be seen using the below commands. Let's first fire up our old cat command, then see it in the job listing of bash shell.
ubuntu@localhost:~$ cat /dev/random > /dev/null &  5154 ubuntu@ip-10-12-2-73:~$ jobs + Running cat /dev/random > /dev/null &
We can see from the above output that our command is running in the background, and its job id number is 1. Let's now fireup disown command for our job, to prevent it from getting killed on exit.
ubuntu@localhost:~$ disown -h %1
jobs command will show you all the running jobs with their id numbers. disown command can be fired against any job id of your interest.
disown command without any option will only remove the last job (current job..the latest job) from the job table(it does not kill the process..but it simply removes it from shell's job table.). Seel the below example.
ubuntu@localhost:~$ ping google.com > /dev/null &  5175 ubuntu@localhost:~$ jobs + Running ping google.com > /dev/null & ubuntu@localhost:~$ cat /dev/random > /dev/null &  5176 ubuntu@localhost:~$ jobs - Running ping google.com > /dev/null & + Running cat /dev/random > /dev/null &
So now we have two jobs running and is in the job table. Let's now execute disown command(this shown remove the last job that we triggered..In this case its cat command.)
ubuntu@localhost:~$ jobs - Running ping google.com > /dev/null & + Running cat /dev/random > /dev/null & ubuntu@localhost:~$ disown ubuntu@localhost:~$ jobs + Running ping google.com > /dev/null &
You can also remove all the jobs that are currently running from the job table, using the below command.
ubuntu@localhost:~$ disown -a
Only running jobs can be removed from the job table, using the below command.
ubuntu@localhost:~$ disown -r