I have some python daemons for raspberry pi applications running on startup with init-scripts.
The init script runs fine from the console, starts and ends the background process correctly.
The script was made autostart with sudo insserv GartenwasserUI
It starts on startup, which is proof by having the LCD backlight on, but is not in the process list after logon. A manual start with sudo service GartenwasserUI start works immediately.
What could be wrong?
Here the script
#!/bin/sh
### BEGIN INIT INFO
# Provides: GartenwasserUI
# Required-Start: $remote_fs $syslog
# Required-Stop: $remote_fs $syslog
# Default-Start: 2 3 4 5
# Default-Stop: 0 1 6
# Short-Description: GartenwasserUI acts as a mqtt client for LCD displaying and switching gpio through mqtt
# Description: Put a long description of the service here
### END INIT INFO
# Change the next 3 lines to suit where you install your script and what you want to call it
DIR=/usr/local/bin/Gartenwasser
DAEMON=$DIR/GartenwasserUI.py
DAEMON_NAME=GartenwasserUI
# Add any command line options for your daemon here
DAEMON_OPTS=""
# This next line determines what user the script runs as.
# Root generally not recommended but necessary if you are using the Raspberry Pi GPIO from Python.
DAEMON_USER=root
# The process ID of the script when it runs is stored here:
PIDFILE=/var/run/$DAEMON_NAME.pid
. /lib/lsb/init-functions
do_start () {
log_daemon_msg "Starting system $DAEMON_NAME daemon"
cd $DIR
#python ./$DAEMON_NAME.py &
start-stop-daemon --start --background --pidfile $PIDFILE --make-pidfile --user $DAEMON_USER --chuid $DAEMON_USER --startas $DAEMON -- $DAEMON_OPTS --verbose -stdout /var/log/GartenwasserUI.log
log_end_msg $?
}
do_stop () {
log_daemon_msg "Stopping system $DAEMON_NAME daemon"
start-stop-daemon --stop --pidfile $PIDFILE --retry 10
log_end_msg $?
}
case "$1" in
start|stop)
do_${1}
;;
restart|reload|force-reload)
do_stop
do_start
;;
status)
status_of_proc "$DAEMON_NAME" "$DAEMON" && exit 0 || exit $?
;;
*)
echo "Usage: /etc/init.d/$DAEMON_NAME {start|stop|restart|status}"
exit 1
;;
esac
exit 0
And the script itself:
#!/usr/bin/env python
__author__ = "Bernd Gewehr"
# import python libraries
import os
import signal
import sys
import time
# import libraries
import lib_mqtt as MQTT
from Adafruit_CharLCDPlate import Adafruit_CharLCDPlate
#DEBUG = False
DEBUG = True
MQTT_TOPIC_IN = "/Gartenwasser/#"
MQTT_TOPIC = "/Gartenwasser"
MQTT_QOS = 0
VALVE_STATE = [0, 0, 0, 0, 0]
def on_message(mosq, obj, msg):
"""
Handle incoming messages
"""
topicparts = msg.topic.split("/")
if DEBUG:
print msg.topic
print topicparts
for i in range(0,len(topicparts)):
print i, topicparts[i]
print msg.payload
pin = int('0' + topicparts[len(topicparts) - 1])
value = int(msg.payload)
if topicparts[2] == "in":
if pin == 29:
VALVE_STATE[0] = value
if pin == 31:
VALVE_STATE[1] = value
if pin == 33:
VALVE_STATE[2] = value
if pin == 35:
VALVE_STATE[3] = value
Message = 'V1: ' + str(VALVE_STATE[0]) + ' V2: ' + str(VALVE_STATE[1]) + '\nV3: ' + str(VALVE_STATE[2]) + ' V4: ' + str(VALVE_STATE[3])
lcd.clear()
lcd.message(Message)
# End of MQTT callbacks
def cleanup(signum, frame):
"""
Signal handler to ensure we disconnect cleanly
in the event of a SIGTERM or SIGINT.
"""
# Cleanup modules
MQTT.cleanup()
lcd.stop()
# Exit from application
sys.exit(signum)
def loop():
"""
The main loop in which we mow the lawn.
"""
while True:
time.sleep(0.08)
buttonState = lcd.buttons()
for b in btn:
if (buttonState & (1 << b[0])) != 0:
if DEBUG: print 'Button pressed for GPIO ' + str(b[1])
if b[1] > 0: MQTT.mqttc.publish(MQTT_TOPIC + '/in/' + str(b[1]), abs(VALVE_STATE[b[2]]-1), qos=0, retain=True)
time.sleep(.5)
break
# Use the signal module to handle signals
for sig in [signal.SIGTERM, signal.SIGINT, signal.SIGHUP, signal.SIGQUIT]:
signal.signal(sig, cleanup)
# Initialise our libraries
lcd = Adafruit_CharLCDPlate()
lcd.backlight(True)
MQTT.init()
MQTT.mqttc.on_message = on_message
MQTT.mqttc.subscribe(MQTT_TOPIC_IN, qos=MQTT_QOS)
# Clear display and show greeting, pause 1 sec
lcd.clear()
lcd.message("Gartenwasser\nstartet...")
time.sleep(1)
Message = 'V1: ' + str(VALVE_STATE[0]) + ' V2: ' + str(VALVE_STATE[1]) + '\nV3: ' + str(VALVE_STATE[2]) + ' V4: ' + str(VALVE_STATE[3])
lcd.clear()
lcd.message(Message)
# Cycle through backlight colors
#col = (lcd.RED, lcd.YELLOW, lcd.GREEN, lcd.TEAL,
# lcd.BLUE, lcd.VIOLET, lcd.WHITE, lcd.OFF)
#for c in col:
# lcd.ledRGB(c)
# sleep(.5)
# assign GPIO & Status index of VALVA_STATUS
btn = ((lcd.LEFT, 29, 0),
(lcd.UP, 31, 1),
(lcd.DOWN, 33, 2),
(lcd.RIGHT, 35, 3),
(lcd.SELECT, 0, 4))
# start main procedure
loop()
I found the solution: When the machine starts up, the mosquitto service starts withs S02. Since the python daemons init scripts had no info that they depend on mosquitto, they were started as S02 also.
The change that solved the problem:
Set the dependencies in the LSB header of the init script:
# Required-Start: $remote_fs $syslog mosquitto
After that, both python daemons were executed correctly as S03.