3

I have a python program named endless.py. I want to restart it whenever it crashes, and write the time that it restarted, to a file named restartlog.txt. Here is my python code so far:

import time, os, subprocess
while True:
        x = os.popen('ps -ef | grep python').read()
        if 'endless.py' not in x:
                print 'Restarted'
                y = open('restartlog.txt', 'a')
                y.seek(0)
                x = time.asctime( time.localtime(time.time()))
                z = '\nRestarted at', x
                z = str(z)
                y.write(z)
                print 'Written!'
                subprocess.call('python endless.py', shell=True)
        time.sleep(1)

This restarts the program, but it also creates a new one called /bin/sh -c /usr/bin/python /home/pi/endless.py. It also doesn't write to the file unless I remove the subprocess.call() (I checked). Is there any way to restart the program cleanly and write it to a file in linux or python?

closed as off-topic by lenik, goldilocks, RPiAwesomeness, Fred, Impulss Apr 9 '14 at 5:32

This question appears to be off-topic. The users who voted to close gave this specific reason:

  • "This question does not appear to be specific to the Raspberry Pi within the scope defined in the help center." – lenik, goldilocks, RPiAwesomeness, Fred, Impulss
If this question can be reworded to fit the rules in the help center, please edit the question.

  • why don't you fix it so it does not crash instead? – lenik Mar 25 '14 at 10:13
  • correct way is to let the operating system manage these kinds of processes as a service or a cronjob. – nurettin Apr 10 at 11:44
3

You can do this very easily with a shell script:

#!/bin/sh

COMMAND=endless.py
LOGFILE=restart.txt

writelog() {
  now=`date`
  echo "$now $*" >> $LOGFILE
}

writelog "Starting"
while true ; do
  $COMMAND
  writelog "Exited with status $?"
  writelog "Restarting"
done

If you really want to use python:

#!/usr/bin/env python

import time, subprocess

COMMAND=['/path/to/endless.py']
LOGFILE='/path/to/restart.txt'

def writelog(message):
    with open(LOGFILE,'a') as f:
        f.write("{0} {1}\n".format(time.asctime( time.localtime(time.time())),
                                   message))

writelog("Starting")
while True:
    rc = subprocess.call(COMMAND)
    if rc >= 0:
        writelog("Exited with {0} status".format(rc))
    else:
        writelog("Exited on signal {0}".format(0-rc))
    writelog("Restarting")
  • Cool, this should work with Java apps aswell? (Can't test at the moment) – Paul Feb 25 '16 at 17:25
0

The problem is that subprocess.call waits for the command to complete.

An alternative would be to use subprocess.Popen instead, for example

import time, subprocess

# Logging function
def AddLog(status):
    # Add line to status log
    logFile = open('restartlog.txt', 'a')
    timeString = time.asctime(time.localtime(time.time()))
    logFile.write('%s %s\n' % (timeString, status))
    # Force the log to be written out
    logFile.flush()
    logFile.close()

# Start the process first time
process = subprocess.Popen(['python', 'endless.py'])
AddLog('Started')

while True:
    # Check the state of the process
    status = process.poll()

    if status != None:
        # Terminated, restart process
        process = subprocess.Popen(['python', 'endless.py'])
        print 'Termination code %d, restarted' % (status)
        AddLog('Restarted')
    else:
        # Still running
        time.sleep(1)

This has the added advantage of avoiding the ps command as well as not waiting for the command to finish.

I have to agree with Lenik though, it is really better to ensure the script does not fail, is there a problem there which you require help with?

Finally I am a little confused why you are opening the log file in append mode but immediately moving the write position to the start of the file, did you want an appending log or a single last message log?

Not the answer you're looking for? Browse other questions tagged or ask your own question.