I'm trying to have a systemd service run on boot on a raspberry pi. It is a bash script that checks a github repository and keeps a python script running and up to date. I have tried various configurations for the service file noticing that some network errors occurred but I can't seem to have it run as the tmux task doesn't start properly.
[Unit]
Description=Sensor API Service
Wants=network-online.target
After=network.target network-online.target
[Service]
Type=simple
Restart=always
ExecStart=/usr/bin/bash /home/pi/sensor/update.sh
[Install]
WantedBy=network-online.target
After boot tmux doesn't even run properly with the following error:
error connecting to /tmp//tmux-100/default (No such file or directory)
This is the bash script I'm trying to run.
#!/bin/bash
session="sensorInput"
workingDir="/home/pi/sensor"
if [ ! -d $workingDir ]; then
mkdir $workingDir
cd $workingDir
else
cd $workingDir
fi
function UOI () {
cd $workingDir
git clone {githublink}
shopt -s dotglob
mv -u sensor/* ./
rm -fr sensor
git reset --hard
git pull --force
git checkout .
pip3 install -r requirements.txt
}
function run () {
git fetch
if [ ! -f "app.py" ]; then
echo "Python app not found, running update/install function."
UOI
echo "Finished installing the script."
tmux new -d -s $session 'python3 app.py'
echo "Script is now running in session \'sensorInput\'"
elif git status --branch --porcelain -uno | grep behind; then
echo "Differences from main branch found, updating script."
echo "Terminating python script session."
tmux kill-session -t $session
UOI
echo "Finished updating the script."
tmux new -d -s $session 'python3 app.py'
echo "Script is now running in session \'sensorInput\'."
else
echo "No differences found, no action taken."
tmux has-session -t $session 2>/dev/null
if [ $? != 0 ]; then
echo "The script is not running, rebooting the script."
tmux new -d -s $session 'python3 app.py'
echo "Script is now running in session \'sensorInput\'."
fi
fi
}
while true; do run & sleep 60m; done
I have honestly ran out of ideas I searched in quite a bit of other questions and tried modifying the service file but I can't seem to figure it out.
I'm sorry if I somehow missed the question already being answered here before. Hope someone can help me.
After boot tmux doesn't even run properly with the following error:
error connecting to /tmp//tmux-100/default (No such file or directory)
This error indicates that no tmux server is currently running. A tmux server is started automatically the first time you create a new session (via tmux new -s <session name>
) or by explicitly starting it with tmux start
. I’ve done some limited testing to verify that this is the case at boot with the targets you specify in your service file (though there are caveats to this point).
You did not post the entire log for this service beyond the one tmux error, but I believe this error is being thrown by either the call to tmux kill-session ...
or tmux has-session ...
since neither of those commands will start the tmux server and (by inspection) there are certainly logical conditions by which you would call them first when the service starts. And since your call to tmux has-session ...
redirects stderr to /dev/null, your error must be coming from the tmux kill
command.
The easiest way to fix this is to explicitly check if tmux is running and start it if it isn’t at the very top of your script. I recommend adding the following to the top of your bash script (update.sh I presume from your service file).
if [[ ! tmux info &> /dev/null ]]; then
echo “Starting tmux server”
tmux start
fi
In addition to the above, there are a few things you may want to consider to make this all a little more robust.
The network-online.target
is a pretty strange target. As far as I know, this target is usually postponed until the very end of boot (if it is started at all) since it has no dependencies that are tied to the normal boot services, so making it dependent on your service is pretty meaningless. A more reasonable target would be something like multi-user.target
.
User=
and Group=
If you put this service file in the systemd path, it would run by root by default. There is also a user service directory that will run services as a specific user, but doing so will only run when that user is logged in I believe. Instead, I recommend adding User=
and Group=
options to your [Service]
section. This will make systemd to run your service as a user. I would recommend it in this case since you are only touching files in a users directory (pi) and do not need root privileges.
WorkingDir=home/pi/sensor
Instead of setting a string in your script and calling cd
to it, just set the working directory for the service by setting WorkingDir=
in the [Service]
section. This will make it so your service starts in the specified directory. No cd
necessary. Note, however, that the unit will not create the directory if it doesn’t exist.