Red-discordbot: bot should restart by itself

Created on 23 Apr 2016  路  22Comments  路  Source: Cog-Creators/Red-DiscordBot

instead of running a second script calling python red.py every time it crashes.
should also have
!restart to re-init/login
!shutdown to shutdown

Most helpful comment

For almost everything I make I use a simple bash script (found it somewhere online) that starts the program and restarts it on exit code 2, so I can use exit() to shut it down and exit(2) to restart it (don't know if this is the good way to do it, but it works, used it for PHP scripts before):

#!/bin/sh
code=2
while [ $code -eq "2" ]
do
python start.py
code=$?
done

EDIT: Doesn't work for crashes of course :/

All 22 comments

How would you run !restart if the bot is already RIP? Or am I misunderstanding?

@xnaas if the bot is already RIP, it would restart before you notice

when the bot rips, it restarts itself.
!restart would.. force a restart. like a computer would
!shutdown would.. force a shutdown. like a computer would

Would be nice. At the very least I'd kill for a systemd port of the Upstart script... 馃槢

Thanks for the clarification @irdumbs and @FishyFing.

yeah I hope to throw away all those scripts n such :3

Could you not just have the startRedLoop.bat running? It should restart when the bot rips.

@Mortiferr instead of running a second script calling python red.py every time it crashes. the loop does this. what we're saying is that on shutdown, it starts by itself again with no script

@FishyFing Oops sorry, I need to learn to read.

or rather, whenever the bot crashes it restarts on it's own and on restart the bot restarts, whereas on shutdown, the bot shuts down

For almost everything I make I use a simple bash script (found it somewhere online) that starts the program and restarts it on exit code 2, so I can use exit() to shut it down and exit(2) to restart it (don't know if this is the good way to do it, but it works, used it for PHP scripts before):

#!/bin/sh
code=2
while [ $code -eq "2" ]
do
python start.py
code=$?
done

EDIT: Doesn't work for crashes of course :/

it's an improvement but we're talking about putting this functionality into the bot itself

This is a great idea

We need to add a global error catcher (somewhere in the main red.py near the main loop, as far as I understand it) and perform the loop restart over there. Need to have a closer look

If you want to try to do it within the bot loop try to take a look at overriding on_error(). I'm starting to think we should catch our own PID and then stick the bot in a forked process so we can monitor it.

This is a nice idea.

While in most cases the bot restarting itself will be sufficient, there could always be scenario's where the bot could crash or get killed by an oomkiller on the system. By mistake, etc.

I am in favor of using systemd instead of an upstart script.
However, you'll need a modern Linux system to do this.

Below is just an example configuration I made, which should work.
It will start the bot again if Red exits with anything but 0 as its exitcode.

I hope this helps someone. :)

Create e.g. /etc/systemd/system/red-discord.service

Paste in the following, modify to fit your own environment.

[Unit]
Description=Red Discord bot
After=network.target

[Service]
User=discord
Group=discord
Type=simple
WorkingDirectory=/home/discord/Red-DiscordBot
ExecStart=/usr/bin/python3.5 /home/discord/Red-DiscordBot/red.py --no-prompt
Restart=on-failure

[Install]
WantedBy=multi-user.target

Reload systemd:

systemctl daemon-reload

Start the bot

systemctl start red-discord

@phantium there is also supervisor support, which can be found in Kowlin's guide: https://gist.github.com/Kowlin/2c7116ead68a344e5a33#file-gistfile1-txt-L15

When would you need the bot to restart itself? There may be a better way. For example if you want to restart the bot because you changed some settings, perhaps a config reload command would be better.

I was using the code below to allow me to log out proper and exit out of the loop.bat for my win tray GUI

Helper: pid.py

import subprocess
import os

if os.name == "nt":
    try:
        p=subprocess.Popen(["startRedLoop.bat"])
        pid_bat = str(p.pid)
        pid_red = str(os.getpid())
        if p.pid > 0:
           print ("Process created with PID: ", pid_bat)
           print("Python PID: ", pid_red)
        f = open("red.pid","w")
        f.write(pid_bat)
        f.close()
        exit()
    except Exception as e:
        print(e)

startRedTray.bat

@Echo off
chcp 65001 >nul
python pid.py

Code to kill

def kill_red(bot):
    try:
        f = open("red.pid","r")
        bat_pid = f.readline()
        print("startRedLoop.bat: ", bat_pid)    
        print("active red: ", str(os.getpid()))

        try:
            if sys.platform == "linux" or sys.platform == "linux2":
                # linux
                """
                    start on runlevel [2345]
                    stop on runlevel [016]

                    respawn
                    chdir /home/username/Red-DiscordBot
                    setuid username
                    setgid username
                    exec python3.5 red.py --no-prompt

                    post-start script
                    PID=`status app_name | egrep -oi '([0-9]+)$' | head -n1`
                        echo $PID > /home/username/Red-DiscordBot/red.pid
                    end script

                    post-stop script
                        rm -f /home/username/Red-DiscordBot/red.pid
                    end script  
                    ---------------------------------------------
                    #http://stackoverflow.com/questions/9972023/ubuntu-upstart-and-creating-a-pid-for-monitoring
                    #http://stackoverflow.com/questions/17856928/how-to-terminate-process-from-python-using-pid
                    #!upstart
                    description "Redis Server"

                    env USER=redis

                    start on startup
                    stop on shutdown

                    respawn

                    exec sudo -u $USER sh -c "/usr/local/bin/redis-server /etc/redis/redis.conf 2>&1 >> /var/log/redis/redis.log"

                    post-start script
                        PID=`status app_name | egrep -oi '([0-9]+)$' | head -n1`
                        echo $PID > /var/run/app_name.pid
                    end script

                    post-stop script
                    rm -f /var/run/app_name.pid
                    end script                         
                """
                bot.logout()
                os.popen('kill -SIGTERM '+str(bat_pid))
            elif sys.platform == "darwin":
                # OS X
                bot.logout()
            elif sys.platform == "win32":
                # Windows... 
                bot.logout()
                # Kill the proces using pywin32 and pid
                import win32api
                PROCESS_TERMINATE = 1
                handle = win32api.OpenProcess(PROCESS_TERMINATE, False, int(bat_pid))
                win32api.TerminateProcess(handle, -1)
                win32api.CloseHandle(handle)
                exit()
        except Exception as e:
            print("Kill PID error")
            print (e)
            return False
    except Exception as e:
        print("Read PID error")
        print (e)
        #bot.logout()
        return False

how do I run bot when my pc is off?

@SunDwarf -- How do I launch my web browser if my PC is off? Hint: I don't. 馃槈

You have to host the bot on an external server if you don't want to leave your own PC on 24/7.

@xnaas Pretty sure that @SunDwarf was being sarcastic lol

Was this page helpful?
0 / 5 - 0 ratings

Related issues

irdumbs picture irdumbs  路  4Comments

Fozar picture Fozar  路  4Comments

Kowlin picture Kowlin  路  4Comments

lifehome picture lifehome  路  4Comments

LGACode picture LGACode  路  4Comments