Dec 292014
 
Article Server Administration

Sometimes, a process that we have started from a terminal might be taking longer to complete than what we had estimated. The process has already been running for a long time, and we want it to continue executing, but we need to detach the process from the terminal to close the interactive session.

This post explains how to detach from the terminal a process that has been started from a bash shell on a linux system.

Redirecting standard output and standard error to files

The main issue in detaching a process from a terminal is redirecting the output and error streams. We can decide to redirect the streams to log files, or just to discard any output redirecting the streams to /dev/null.

To test our procedure, we will write a simple PHP script “test.php”. The script will just write to standard output the time (in UNIX timestamp format), every two seconds:

<?php
while (true) {
    echo time() . "\n";
    sleep(2);
}

Now, start the execution of the script. After a couple of lines have been written to the terminal, press Control-z to suspend the process.

$ php test.php 
1419504170
1419504172
1419504174
^Z
[1]+  Stopped                 php test.php
$

Obtain the process identifier with the builtin command “jobs”:

$ jobs -l
[1]+ 12212 Stopped                 php test.php

You can also verify the file descriptors in use by the process with a query to the pseudo-filesystem “/proc”:

$ ls -l /proc/12212/fd
total 0
lrwx------ 1 openalfa openalfa 64 Dec 30 08:54 0 -> /dev/pts/5
lrwx------ 1 openalfa openalfa 64 Dec 30 08:54 1 -> /dev/pts/5
lrwx------ 1 openalfa openalfa 64 Dec 30 08:54 2 -> /dev/pts/5

Next, create the files “/tmp/test.stdout” and “/tmp/test.stderr” where the output of the program will be redirected:

$ touch /tmp/test.stdout
$ touch /tmp/test.stderr

Next, execute the “bg” builtin command to resume executing process in background, and connect to it with gdb:

$ bg
$ gdb -p $!
GNU gdb (GDB) 7.4.1-debian
...
Attaching to process 12212

Program received signal SIGTSTP, Stopped (user).
...
(gdb)

In gdb, assign the file descriptors 1 (STDOUT) and 2 (STDERR) to the files created:

p dup2(open("/tmp/test.stdout", 1), 1)
p dup2(open("/tmp/test.stderr", 1), 2)
detach
quit

Finally, remove the process from the list of jobs with the “disown” builtin command:

$ disown

You can now query “/proc” again to verify that the process is running with the new assignments:

$ ls -l /proc/19732/fd
total 0
lrwx------ 1 openalfa openalfa 64 Dec 30 08:54 0 -> /dev/pts/5
lrwx------ 1 openalfa openalfa 64 Dec 30 08:54 1 -> /tmp/test.stdout
lrwx------ 1 openalfa openalfa 64 Dec 30 08:54 2 -> /tmp/test.stderr
l-wx------ 1 openalfa openalfa 64 Dec 30 09:01 3 -> /tmp/test.stdout
l-wx------ 1 openalfa openalfa 64 Dec 30 09:01 4 -> /tmp/test.stderr

And also verify that the process is running and writing to /tmp/stdout:

$ tail -f /tmp/test.stdout
1419504184
1419504186
...

How to prevent this situation: use screen

It is a good idea to get acquainted with the “screen” utility. “screen” allows the user to run one or several terminal sessions under “virtual” terminals. These terminals can be easily detached from the “physical” terminal with a simple key combination (default is Ctrl-A + D), and any process that was running on them will continue running. Later, the user can connect again to the virtual terminal with the command “screen -r”.

If we are working connected to a remote server, using “screen” also helps in case of network connectivity issues. If connectivity is lost, the virtual terminal just detaches itself from the controlling terminal, and processes that might be running on it will just continue executing.

 Posted by at 1:47 pm

 Leave a Reply

(required)

(required)