0

Starting with the following code , my objective was to create a restart command for my python bot.

result = {
    #cmds here
    prfx and 'restart':lambda _: call('./restart.sh', shell=True),
    }[cmd](_)

    room.message(result)

I have a lot of commands in this dictionary so I summarized the format.
The command calls the shell script (restart.sh) , and is supposed to kill the bot process (bot.py) , and then reference to another shell script that then starts the bot process again.

[restart.sh]

pgrep -f bot.py #  pid
pkill -9 -f bot.py # kills the matching pid

sh ./start.sh #run start.sh
exit 0

[start.sh]

python bot.py

When running the restart command , the bot process is ended and does not continue the rest of the script.
[example : Bash]

Connecting to MySQL database...
connection established.
Connection closed.
ONLINE
[chatroom] Bot: ONLINE!: [ip]
[chatroom] user: >restart: [ip]
168747
169448

It will just show the two processes and terminate.

6
  • You're using this mechanism to have the bot restart itself? You can't do that. pkill will kill your parent. Use execve() to replace the old copy of the bot with the new one in memory directly. You don't need any pkill at all. Commented Sep 28, 2017 at 16:16
  • Also, why do you use pgrep if you're being run from the PID you want to replace? You can just look at your parent PID -- much less volatile and risky than string-matching on names. Commented Sep 28, 2017 at 16:20
  • (Also, don't use kill -9 unless you really, really need to; it prevents processes from doing housekeeping, like flushing their write buffers on exit, so you can lose log messages or have datastores left in an unclean state). Commented Sep 28, 2017 at 16:20
  • execve() rewrites the process without you having to manually kill the process? Commented Sep 28, 2017 at 16:22
  • It literally replaces the current process-table entry with a different program. Commented Sep 28, 2017 at 16:23

1 Answer 1

1

To restart yourself (that is to say, the current process), don't use call() (which I'm assuming is subprocess.call()) at all.

Instead, if this code is being run from bot.py itself (and that script is executable with a valid shebang):

os.execl(os.path.abspath(__file__), '_')

The _ is a placeholder passed as argv[0]. You could put other command-line arguments after it, if you wished.

This replaces the running instance of bot.py with a new one inheriting the exact same PID.

Sign up to request clarification or add additional context in comments.

5 Comments

Strangely doesn't seem to run, but os.path,abspathfile(file) prints out the location when tested
It has a shebang and the executable bit set? Do you get an error?
Using os.execl(sys.executable, 'python', file, *sys.argv[1:]) the program restarts, but there are two instances of my bot in the chatroom
How many threads or processes are associated with each instance of the bot?
(so, there are a few possibilities. One is that the CLOEXEC flag isn't set on your network connections, so the file descriptor stays open through the exec call; the other is that you have a different forked-off subprocess that's keeping the connection open).

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.