0

I want to start some python script (with venv) at startup and monitor the status, for auto restart it if something goes wrong.

I've made: - a simple python example prg.py that sleep forever and exit if it receive a sigint signal.

  • a bash script prg.sh that monitor the execution of prg.py. If the process stop, the script restart the program. If the script receive the sigint, it will send a sigint to the prg.py program and exit.

  • A init.d script (prg) for start the bash script (prg.sh). The code of prg is not mine, I've found it on GitHub and modified it. I'm searching the link, When I will found it I will edit the post.

prg.py:

import signal
import time

def signal_handler(sig, frame):
  print('sigint')
  quit(0)

signal.signal(signal.SIGINT, signal_handler)
print ('aaa')
while (1):
  time.sleep(1.5)

prg.sh:

#!/bin/bash

#set -x

DIR="/home/pi"
PRESCRIPT="source venv/bin/activate;python --version"
SCRIPT="python prg.py"

EXITDO=0
PID=-1
trap ctrl_c INT
function ctrl_c() {
  echo 'SIGINT intercepted.'
  EXITDO=1
}

#Main loop
while [ $EXITDO -eq 0 ]; do
  echo 'Starting process…'
  cd "$DIR"
  eval $PRESCRIPT
  $SCRIPT &
  PID=$(echo $!)
  echo "Process started with PID: $PID"
  while $(kill -0 $PID) && [ $EXITDO -eq 0 ]; do
    sleep 1
  done
  if [ $EXITDO -eq 0 ]; then
    echo 'Process terminated. Restart.'
  else
    echo 'Kill service.'
    kill -2 $PID
  fi
done

prg:

#!/bin/sh
### BEGIN INIT INFO
# Provides:          prg
# Required-Start:    $local_fs $network $named $time $syslog
# Required-Stop:     $local_fs $network $named $time $syslog
# Default-Start:     2 3 4 5
# Default-Stop:      0 1 6
# Description:       <DESCRIPTION>
### END INIT INFO
NAME=prg
SCRIPT="/home/pi/prg.sh"

PIDFILE=/var/run/$NAME.pid

start() {
  if [ -f $PIDFILE ] && [ -s $PIDFILE ] && kill -0 $(cat $PIDFILE); then
    echo 'Service already running' >&2
    return 1
  fi
  echo 'Starting service…' >&2
  #local CMD="$SCRIPT &> \"$LOGFILE\" & echo \$!"
  #su -c "$CMD" $RUNAS > "$PIDFILE"
  # Try with this command line instead of above if not workable
  # su -s /bin/sh $RUNAS -c "$CMD" > "$PIDFILE"
  $SCRIPT &
  echo $! > "$PIDFILE"
  PID=$(cat $PIDFILE)
  if kill -0 $(cat $PIDFILE) > /dev/null
  then
    echo "$NAME is now running, the PID is $PID"
  else
    echo ''
    echo "Error! Could not start $NAME!"
  fi
}

stop() {
  if [ ! -f "$PIDFILE" ] || ! kill -0 $(cat "$PIDFILE"); then
    echo 'Service not running' >&2
    return 1
  fi
  echo 'Stopping service…' >&2
  #Kill by pid
  kill -2 $(cat "$PIDFILE")
  #remove .pid file
  sleep 3
  if ! kill -0 $(cat "$PIDFILE"); then
    rm -f "$PIDFILE"
    echo 'Service stopped' >&2
  fi
}

uninstall() {
  echo -n "Are you really sure you want to uninstall this service? That cannot be undone. [yes|No] "
  local SURE
  read SURE
  if [ "$SURE" = "yes" ]; then
    stop
    rm -f "$PIDFILE"
    echo "Notice: log file was not removed: $LOGFILE" >&2
    update-rc.d -f $NAME remove
    rm -fv "$0"
  else
    echo "Abort!"
  fi
}

status() {
    printf "%-50s" "Checking $NAME..."
    if [ -f $PIDFILE ] && [ -s $PIDFILE ]; then
        PID=$(cat $PIDFILE)
            if [ -z "$(ps axf | grep ${PID} | grep -v grep)" ]; then
                printf "%s\n" "The process appears to be dead but pidfile still exists"
            else
                echo "Running, the PID is $PID"
            fi
    else
        printf "%s\n" "Service not running"
    fi
}


case "$1" in
  start)
    start
    ;;
  stop)
    stop
    ;;
  status)
    status
    ;;
  uninstall)
    uninstall
    ;;
  restart)
    stop
    start
    ;;
  *)
    echo "Usage: $0 {start|stop|status|restart|uninstall}"
esac
  • If I start prg.sh the program run as expected.

  • I can kill prg.py and the prg.sh auto restart the prg.py.

  • I can send a sigint to prg.sh and the prg.sh stop the prg.py and close itself.

  • I can start the prg with sudo service prg start command and all works fine.

BUT

  • in this situation the, if I send a sigint to prg.sh, nothing happen.

  • In simple words, service prg stop does not work and I don't understand why.

Thanks in advance.

Katte
  • 101
  • 3
  • You mentioned systemd but what you have here is an init script. You should use a native systemd service unit instead, not only it will be much simpler, it will also be way more reliable, since you'll be starting your Python application in foreground, so it's really easy to monitor it and restart it. For a Python venv on a systemd unit, see this question: https://unix.stackexchange.com/q/409609/281844 – filbranden May 17 '19 at 12:41
  • 2
    I'd be happy to write an answer... Except that *you have not asked a question*, so it's unclear what you want to accomplish here... If you want to run your Python venv as a native systemd unit and need some more help getting there from where you're now, that's a possible approach. In that case, please edit your question and ask about what you'd like to have answered. Thanks! – filbranden May 17 '19 at 12:44
  • Thanks for the hint. I've rewrited the question. I hope the question is clearer now. – Katte May 17 '19 at 20:32

0 Answers0