Create a Systemd Entry
sudo nano /etc/systemd/system/myapp.service[Unit]
# After=network.service
Description=My App
[Service]
Type=simple
# WorkingDirectory=/code/python/myapp
ExecStart=/code/scripts/myapp.sh
# User=do-user
[Install]
WantedBy=multi-user.target
# WantedBy=default.targetNOTE: Use After=network.service if you require network.
Create Bash Script
nano /code/scripts/myapp.sh#!/bin/bash# cd /code/python/myapppython3 /code/python/myapp/run.py >> /code/logs/myapp.log 2>&1mkdir /code/logsCreate Python Script
nano /code/python/myapp/run.pyimport signalimport timeimport datetimeis_shutdown = Falsedef stop(sig, frame): print(f"SIGTERM at {datetime.datetime.now()}") global is_shutdown is_shutdown = Truedef ignore(sig, frsma): print(f"SIGHUP at {datetime.datetime.now()}")signal.signal(signal.SIGTERM, stop)signal.signal(signal.SIGHUP, ignore)print(f"START at {datetime.datetime.now()}")while not is_shutdown: print('.', end='', flush=True) time.sleep(1)print(f"END at {datetime.datetime.now()}")Test Systemd
Set file permission
sudo chmod 744 /code/scripts/myapp.shsudo chmod 664 /etc/systemd/system/myapp.serviceEnable Service
sudo systemctl daemon-reloadsudo systemctl enable myapp.serviceTest Service
sudo systemctl start myapp.serviceCheck Status
sudo systemctl start status.serviceCheck Log
tail -f /code/logs/myapp.logStop Service
sudo systemctl stop myapp.serviceRestart server to test if the service started on reboot
sudo rebootAnaconda
Systemd is run as root by default. If you are using Anaconda (or maybe pyenv), current user might not run the same python version/environment as root.
NOTE: I tried changing the user via Service.User, but it still uses the system default python interpreter
python -Vsudo python -VYou can find the python interpreter path using which python or python -c "import sys; print(sys.executable)"
which pythonsudo which pythonEdit the bash script to use the correct python interpreter
/opt/conda/bin/python3 /code/python/myapp/run.py >> /code/logs/myapp.log 2>&1