2016-01-23 70 views
0

我有一些python守護進程,用於啓動時使用init腳本運行的樹莓派應用程序。Python守護進程使用init腳本正確啓動,但在啓動時失敗

初始化腳本在控制檯上正常運行,正確啓動和結束後臺進程。

劇本寫了自動啓動使用sudo insserv時GartenwasserUI

它開始啓動時,它是由具有液晶顯示屏背光證明,但不是在登錄後的進程列表。手動啓動sudo服務GartenwasserUI立即開始工作。

什麼可能是錯的?

這裏腳本

#!/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 

和腳本本身:

#!/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() 
+0

想法:假設你已經檢查過'.log'文件。也許在啓動時設置'sys.stderr = sys.stdout',以防python在退出時打印對stderr有用的東西。最後,我會在'strace'下運行以瞭解它是如何退出的,以及之前發生的事情。 (需要弄清楚如何重定向stderr,因爲'strace'會寫入;'strace/usr/local/bin/python