loading...

Running A Detached Process In Linux

pete_speth profile image Peter Spethmann ・Updated on ・3 min read

Motivation

I was working on a project that involved reading from a load cell on my Raspberry Pi. I wanted to confirm that the weight measurements would stay consistent, even when the cell was loaded for a weeks at a time. To do this, I needed to find a way to continue recording measurements without keeping an ssh session open on my laptop the entire time.

Let's Figure It Out

For the sake of this example, lets say we want to run a python script (call it test.py) that continuously prints the current time to a file (kind of pointless but... 🀷 ).

import datetime,time

with open('output.txt','w+') as outfile:
  while True:
    outfile.write(str(datetime.datetime.now())+'\n')
    time.sleep(1)

To test it out, we run python test.py. We let the script run for a while, then interrupt it with CTRL+C. If we check the file we'll see each timestamp output on a separate line.

Now instead, we can run the process in the background by adding an ampersand & to the end of the command. When we run it, we get an output that tells us the process id (PID).

$ python test.py &
[1] 4424

We can see a list of our current running processes using the ps command.

$ ps

  PID TTY          TIME CMD
 4376 pts/1    00:00:00 bash
 4424 pts/1    00:00:00 python
 4425 pts/1    00:00:00 ps

We can end this process using the kill -INT <PID> command.

If we send the default signal (kill 4424), the program won't have a chance to clean up, and everything that we wrote to the file buffer will be lost. In our case, that will be everything, since we never call flush(). If we check our output.txt, it will be empty. We need to send a signal that kills the program gracefully. Sending kill -INT 4424 will have the same effect as pressing CTRL+C when the process was running in the foreground. More info about kill can be found by running man kill or at linuxcommand.org

We still haven't achieved our goal. This background process will be killed automatically when we logout. We need to use disown to decouple the process from our session. Taking it from the top:

$ python test.py &
[1] 4432

$ disown 4432

Now, we logout and log back in. When we run ps, we no longer see our process. But don't worry, it's still there! By default, we are only shown the processes attached to our current session. We can use ps -U <username> to see all the processes created by a given user (in my case, pi). The -f option provides more information and a nicer format.

$ ps -U pi -f

UID        PID  PPID  C STIME TTY          TIME CMD
pi        1793     1  0 Aug07 ?        00:00:00 /lib/systemd/systemd --user
pi        1796  1793  0 Aug07 ?        00:00:00 (sd-pam)
pi        4452  4441  0 22:12 ?        00:00:00 sshd: pi@pts/2
pi        4455  4452  0 22:12 pts/2    00:00:00 -bash
pi        4432     1  0 22:15 pts/2    00:00:00 python test.py
pi        4485  4455  0 22:16 pts/2    00:00:00 ps -U pi -f

We can leave this process running for as long as we want. Days, weeks, months --- there's no rules! (Except in this case we will run out of memory in the file buffer eventually, but you get the point). Whenever we're done, we can gracefully kill the process using kill -INT 4432, and make off with our super useful data.

Discussion

pic
Editor guide