Skip to content

Instantly share code, notes, and snippets.

@comhad
Last active April 3, 2024 16:10
Show Gist options
  • Star 5 You must be signed in to star a gist
  • Fork 1 You must be signed in to fork a gist
  • Save comhad/de830d6d1b7ae1f165b925492e79eac8 to your computer and use it in GitHub Desktop.
Save comhad/de830d6d1b7ae1f165b925492e79eac8 to your computer and use it in GitHub Desktop.
How to setup a systemctl service for running your bot on a linux system
[Unit]
Description=My discord bot service
After=network.target
[Service]
ExecStart=/usr/bin/python3 mybot.py
WorkingDirectory=/home/user/bots/mybot
StandardOutput=inherit
StandardError=inherit
Restart=always
User=user
[Install]
WantedBy=multi-user.target

systemctl setup

You can set up a custom systemctl service for running your bot on a linux system, this has several benefits because :

  • You can do this easily from the command line, it's SSH friendly.
  • It can restart your bot on crash.
  • It can start on boot.
  • Logs are stored by journalctl and can be accessed easily.

The service file

Below I've made an example of a service file, this is a template and you can download it and replace it with what's specefic to your bot, here's what each thing means :

  • Description - More for clarity, describes what the service is in the systemctl menu.
  • After - The service to wait for before booting up, leave this as network.target as the bot will probably crash if it starts when the server has no internet.
  • ExecStart - The full path to the executable, it has to be a full path to the first item, although if it's something like python you don't have to put the full path to the script, see the example (it needs to be in the same WorkingDirectory though.
  • WorkingDirectory - The full path to the working directory, should be the one that contains your code.
  • StandardOutput - What to do with the standard output, leave as inherit so it gets captured in the journalctl logs.
  • StandardError - What to do with the standard error, leave as inherit so it gets captured in the journalctl logs.
  • Restart - Leave at always to restart on exit or no to never restart on exit.
  • User - The user to process runs as, don't run it as root.
  • WantedBy - Honestly not sure, but all the examples have this.

Whatever you name your service file will mean what it is referenced as in commands, naming it mybot.service will result in you having to issue commands like systemctl status mybot and so on.

Before you test it, you should cd into the WorkingDirectory and execute the ExecStart command, this will tell you if you have any libraries missing or things that might stop your bot from running.

You'll need sudo for the next steps, once you have done the file, copy it to /etc/systemd/system/ and try it, run systemctl start <service> and then systemctl status <service> to make sure it didn't crash. If it works and you want to make it start at boot, run systemctl enable <service>.

You can access logs by typing journalctl -u <service> -r, you can search for more systemctl and journalctl commands on google.

Things to know

  • Restarting on crash is a great thing and has saved my bot from downtime many times, but if your bot crashes after connecting to discord, the service will restart it, and if your app connects to discord to many times within a short time period discord will regenerate your token.
  • In my experience using this with python apps, you must flush the output of the print command for it to log in journalctl, it will still buffer and log in the end when the app stops, but it may be confusing if you get no log lines for ages and then a huge amount at once.
@BurningNacho
Copy link

BurningNacho commented Dec 15, 2022

You can use the logger feature with Python to log to journalctl

import logging
logging.basicConfig(
    format="%(asctime)s - %(name)s - %(levelname)s - %(message)s", level=logging.INFO
)
logger = logging.getLogger(__name__)
logger.warning('Hello World :)')

@BPowell76
Copy link

BPowell76 commented Oct 10, 2023

Could reorganize this so to have better structure. Also, this guide doesn't work when trying to start an index.js Discord bot with NPM installed.

@comhad
Copy link
Author

comhad commented Oct 12, 2023

Could reorganize this so to have better structure. Also, this guide doesn't work when trying to start an index.js Discord bot with NPM installed.

@BPowell76 how do you start your discord bot, what command do you use?

@BPowell76
Copy link

BPowell76 commented Oct 15, 2023

forever start path/to/file is how I used to do it on Ubuntu Desktop 20.04. For Ubuntu 22.04, I'm using the server installation and setting the service like this doesn't work nor does starting a cronjob @reboot.

The service is recognized by the OS, but it can't start. Fails every time.

@comhad
Copy link
Author

comhad commented Oct 21, 2023

forever start path/to/file is how I used to do it on Ubuntu Desktop 20.04. For Ubuntu 22.04, I'm using the server installation and setting the service like this doesn't work nor does starting a cronjob @reboot.

The service is recognized by the OS, but it can't start. Fails every time.

@BPowell76 I've never used forever before, but it looks like that starts it as a daemon when systemctl already does that for you. It's also possible that it's trying to start before it can connect to the internet, then crashing, and repeating this process enough times that systemctl stops it because it thinks it doesn't work properly. It's hard to know without seeing the error log.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment