How To Run Long-running Scripts on a Raspberry Pi
Keep a script running forever over SSH.
When I first got started with a Raspberry Pi, I would often use it to tackle some long running scripts - like the continuous monitoring of a video feed, or a small script that gathered data from the web. The problem I faced was how to stay connected to the Pi long enough so that the script wouldn’t terminate.
You could connect a keyboard, monitor, and keep the pi running that way - but I prefer to work with my Raspberry Pi over SSH, so I can have all the comforts of my regular computer.
So how do you keep a script on your Pi running for a long time over SSH so it doesn’t time out and fail? There are a few ways.
What You’ll Need For This Project
- Raspberry Pi 4 or Raspberry Pi 3 with power adapter
- 2x8 GB (or larger) microSD cards, one for Raspberry Pi, another for the camera
How to run long-running scripts on your Raspberry Pi
Before you get started, get your Raspberry Pi set up. If you haven’t done this before, see our article on how to set up a Raspberry Pi for the first time or how to do a headless Raspberry Pi install (without the keyboard and screen). For this project, we recommend a headless Raspberry Pi install.
Depending on the project you’re working on - there are two methods we’ll cover for handling long running scripts. If you’re running a script just once or twice - use the tmux method. If you’re setting up your Pi for a long-term project and want a script that restarts automatically - skip to the “service” method.
Using tmux on your Raspberry Pi
The tmux package allows you to create a separate shell which you can detach from and let it run in the background. If you had a one-off program that you know is going to take a long time (a make build command for instance), you can create a tmux session, run your long running command, detach from that session, and logout of the pi without worry. As long as you don’t interrupt the pi’s power supply, your script should continue to run. You can attach to the session and check in on it periodically and detach to let it run.
If this sounds like it fits your use case; here’s how to use it.
Stay On the Cutting Edge: Get the Tom's Hardware Newsletter
Get Tom's Hardware's best news and in-depth reviews, straight to your inbox.
1. Install the tmux package.
sudo apt-get install -y tmux
2. Create a new tmux session.
# pick any session name you like
tmux new -s your_session_name
python3 my_really_long_running_script.py
3. Detach from the session by using the following keys:
Hit “Ctrl + B”
Then hit “D”
You’ll be returned to your original session, with your long running script running in the background. You can log out at this point.
4. To re-attach to the session to check how it’s going, simply run the following
# list all the sessions running
tmux list-sessions
# attach to your session
tmux a -t your_session_name
And that’s it. You can detach as described in step 4 again if you like. Tmux is best used for commands that you’re running one-off, like an installation step. If you’re looking to run something long term, continuously, with automatic restarting - you’ll want to create a service.
Creating A Service on your Raspberry Pi
A service is best used for an application you’d like to run continuously on your pi. Maybe it’s a script that’s constantly checking for weather station data and sending it to the cloud, or a simple app that listens for requests to change a LED strip’s color. If you’re looking for something that can handle restarts automatically, and starts when the Pi starts - a service is a great solution.
1. To create a service, first test if the script you’d like to run is functioning properly. Make sure to use the full path to the file when invoking it.
python3 /home/pi/my_script.py
2. Next, we’ll create a file in /etc/systemd/system to define our service:
sudo touch /etc/systemd/system/myscript.service
3. We’ll then edit the file, adding the required information to define the service and allow it to restart on failure.
sudo nano /etc/systemd/system/myscript.service
Add the following lines to the file
[Unit]
Description=My long running script
After=network.target
StartLimitIntervalSec=0[Service]
Type=simple
User=pi
Restart=always
RestartSec=1
ExecStart=python3 /home/pi/my_script.py
[Install]
WantedBy=multi-user.target
4. Once you’ve saved your file, start and enable the service - allowing it to run immediately, and also when the pi restarts.
sudo systemctl start myscript && sudo systemctl enable myscript
5. Your script will now run on your pi in the background, restarting automatically when it fails. You can check on it with the following command:
sudo systemctl status myscript
And that’s it. Many services are already running on your Pi as a part of it’s normal operation. By defining and enabling this service, you simply add your script to the rest of the things your Pi does just by being plugged in. If at any point you need to stop the service, you can do it with the following command:
sudo systemctl stop myscript
There are many other ways to accomplish running scripts in the background, but for Raspberry Pi projects, these two are my go-to commands. Happy building!
# pick any session name you like
tmux new -s your_session_name
Ryder Damer is a Freelance Writer for Tom's Hardware US covering Raspberry Pi projects and tutorials.
-
gazzat5 If you're using tmux and you only have one session, it's far easier to reconnect with tmux attach-sessionReply
But by far the easiest method of running a script without it being terminated when you disconnect from SSH is using nohup -
1_rick Unless it isn't on the Pi for some reason, if you have a long-running script that you don't necessarily need to connect back to you can always nohup it.Reply -
Weaver1985 Great tutorial! Tmux is a great tool for running one-off, long running scripts. I'm also a big fan of supervisor.Reply -
rocketron999 I tried the tutorial but I get an error message when I enterReply
pi@raspberrypi:~ $ sudo systemctl start myscript && sudo systemctl enable myscript
Failed to start myscript.service: Unit myscript.service has a bad unit file setting.
See system logs and 'systemctl status myscript.service' for details.
I named my script my_script.py and copied and pasted from the website so there should be no spelling or syntax errors