2012-12-19 41 views
3

我有一个python脚本,我想在启动时在后台运行。这是脚本:守护debian中的python脚本

#!/usr/bin/python 
from Adafruit_CharLCD import Adafruit_CharLCD 
from subprocess import * 
from time import sleep, strftime 
from datetime import datetime 
from datetime import timedelta 
from os import system 
from os import getloadavg 
from glob import glob 

#Variables 
lcd = Adafruit_CharLCD() #Stores LCD object 
cmdIP = "ip addr show eth0 | grep inet | awk '{print $2}' | cut -d/ -f1" #Current IP 
cmdHD = "df -h/| awk '{print $5}'" # Available hd space 
cmdSD = "df -h /dev/sda1 | awk '{print $5}'" # Available sd space 
cmdRam = "free -h" 
temp = 0 

#Run shell command 
def run_cmd(cmd): 
    p = Popen(cmd, shell=True, stdout=PIPE) 
    output = p.communicate()[0] 
    return output 

#Initalises temp device  
def initialise_temp(): 
    #Initialise 
    system("sudo modprobe w1-gpio") 
    system("sudo modprobe w1-therm") 
    #Find device 
    devicedir = glob("/sys/bus/w1/devices/28-*") 
    device = devicedir[0]+"/w1_slave" 
    return device 

#Gets temp 
def get_temp(device): 
    f = open (device, 'r') 
    sensor = f.readlines() 
    f.close() 

    #parse results from the file 
    crc=sensor[0].split()[-1] 
    temp=float(sensor[1].split()[-1].strip('t=')) 
    temp_C=(temp/1000.000) 
    temp_F = (temp_C * 9.0/5.0) + 32 

    #output 
    return temp_C 

#Gets time 
def get_time(): 
    return datetime.now().strftime('%b %d %H:%M:%S\n') 

#Gets uptime 
def get_uptime(): 
    with open('/proc/uptime', 'r') as f: 
     seconds = float(f.readline().split()[0]) 
     array = str(timedelta(seconds = seconds)).split('.') 
     string = array[0].split(' ') 
     totalString = string[0] + ":" + string[2] 
    return totalString 

#Gets average load 
def get_load(): 
    array = getloadavg() 
    average = 0 
    for i in array: 
     average += i 
    average = average/3 
    average = average * 100 
    average = "%.2f" % average 
    return str(average + "%") 

#def get_ram(): 
def get_ram(): 
    ram = run_cmd(cmdRam) 
    strippedRam = ram.replace("\n"," "); 
    splitRam = strippedRam.split(' ') 
    totalRam = int(splitRam[52].rstrip("M")) 
    usedRam = int(splitRam[59].rstrip("M")) 
    percentage = "%.2f" % ((float(usedRam)/float(totalRam)) * 100) 
    return percentage + "%" 

#Gets the SD usage 
def get_sd(): 
    sd = run_cmd(cmdSD) 
    strippedSD = sd.lstrip("Use%\n") 
    return strippedSD 

#Gets the HD usage 
def get_hd(): 
    hd = run_cmd(cmdSD) 
    strippedHD = hd.lstrip("Use%\n") 
    return strippedHD 

def scroll(): 
    while(1): 
     lcd.scrollDisplayLeft() 
     sleep(0.5) 

#Uptime and IP 
def screen1(): 
    uptime = get_uptime() 
    lcd.message('Uptime %s\n' % (uptime)) 
    ipaddr = run_cmd(cmdIP) 
    lcd.message('IP %s' % (ipaddr)) 

#Ram and load 
def screen2(): 
    ram = get_ram() 
    lcd.message('Ram Used %s\n' % (ram)) 
    load = get_load() 
    lcd.message('Avg Load %s' % (load)) 

#Temp and time 
def screen3(): 
    time = get_time(); 
    lcd.message('%s\n' % (time)) 
    lcd.message('Temp %s' % (temp)) 

#HD and SD usage 
def screen4(): 
    sd = get_sd() 
    lcd.message('SD Used %s\n' % (sd)) 
    hd = get_hd() 
    lcd.message('HD Used %s' % (hd)) 

#Pause and clear 
def screenPause(time): 
    sleep(time) 
    #In here to reduce lag 
    global temp 
    temp = str(get_temp(device)); 
    lcd.clear() 
########################################################################################################### 

#Initialise 
lcd.begin(16,2) 
device = initialise_temp() 
lcd.clear() 

#Testing 

#Main loop 
while(1): 
    screen1() 
    screenPause(5) 
    screen2() 
    screenPause(5) 
    screen3() 
    screenPause(5) 
    screen4() 
    screenPause(5) 

我知道我可能havnt做事情的写作方式,但它的第一次尝试。 我的启动脚本是在/etc/init.d这是脚本:

#! /bin/sh 
### BEGIN INIT INFO 
# Provides:   LCD looping 
# Required-Start: $remote_fs $syslog 
# Required-Stop:  $remote_fs $syslog 
# Default-Start:  2 3 4 5 
# Default-Stop:  0 1 6 
# Short-Description: LCD daemon 
# Description:  This file should be used to construct scripts to be 
#     placed in /etc/init.d. 
### END INIT INFO 

# Author: Foo Bar <[email protected]> 
# 
# Please remove the "Author" lines above and replace them 
# with your own name if you copy and modify this script. 

# Do NOT "set -e" 

# PATH should only include /usr/* if it runs after the mountnfs.sh script 
PATH=/sbin:/usr/sbin:/bin:/usr/bin 
DESC="Loops the LCD screen through LCD.py" 
NAME=startup.py 
DAEMON=/home/pi/Programming/LCD/startup.py 
DAEMON_ARGS="" 
PIDFILE=/var/run/daemonLCD.pid 
SCRIPTNAME=/etc/init.d/daemonLCD 

# Exit if the package is not installed 
[ -x "$DAEMON" ] || exit 0 

# Read configuration variable file if it is present 
[ -r /etc/default/daemonLCD ] && . /etc/default/daemonLCD 

# Load the VERBOSE setting and other rcS variables 
. /lib/init/vars.sh 

# Define LSB log_* functions. 
# Depend on lsb-base (>= 3.2-14) to ensure that this file is present 
# and status_of_proc is working. 
. /lib/lsb/init-functions 

# 
# Function that starts the daemon/service 
# 
do_start() 
{ 
     # Return 
     # 0 if daemon has been started 
     # 1 if daemon was already running 
     # 2 if daemon could not be started 
     start-stop-daemon --start --quiet --pidfile $PIDFILE --exec $DAEMON --test > /dev/null \ 
       || return 1 
     start-stop-daemon --start --quiet --pidfile $PIDFILE --exec $DAEMON -- \ 
       $DAEMON_ARGS \ 
       || return 2 
     # Add code here, if necessary, that waits for the process to be ready 
     # to handle requests from services started subsequently which depend 
     # on this one. As a last resort, sleep for some time. 
} 

# 
# Function that stops the daemon/service 
# 
do_stop() 
{ 
     # Return 
     # 0 if daemon has been stopped 
     # 1 if daemon was already stopped 
     # 2 if daemon could not be stopped 
     # other if a failure occurred 
     start-stop-daemon --stop --quiet --retry=TERM/30/KILL/5 --pidfile $PIDFILE --name $NAME 
     RETVAL="$?" 
     [ "$RETVAL" = 2 ] && return 2 
     # Wait for children to finish too if this is a daemon that forks 
     # and if the daemon is only ever run from this initscript. 
     # If the above conditions are not satisfied then add some other code 
     # that waits for the process to drop all resources that could be 
     # needed by services started subsequently. A last resort is to 
     # sleep for some time. 
     start-stop-daemon --stop --quiet --oknodo --retry=0/30/KILL/5 --exec $DAEMON 
     [ "$?" = 2 ] && return 2 
     # Many daemons don't delete their pidfiles when they exit. 
     rm -f $PIDFILE 
     return "$RETVAL" 
# 
# Function that sends a SIGHUP to the daemon/service 
# 
do_reload() { 
     # 
     # If the daemon can reload its configuration without 
     # restarting (for example, when it is sent a SIGHUP), 
     # then implement that here. 
     # 
     start-stop-daemon --stop --signal 1 --quiet --pidfile $PIDFILE --name $NAME 
     return 0 
} 

case "$1" in 
    start) 
     [ "$VERBOSE" != no ] && log_daemon_msg "Starting $DESC" "$NAME" 
     do_start 
     case "$?" in 
       0|1) [ "$VERBOSE" != no ] && log_end_msg 0 ;; 
       2) [ "$VERBOSE" != no ] && log_end_msg 1 ;; 
     esac 
     ;; 
    stop) 
     [ "$VERBOSE" != no ] && log_daemon_msg "Stopping $DESC" "$NAME" 
     do_stop 
     case "$?" in 
       0|1) [ "$VERBOSE" != no ] && log_end_msg 0 ;; 
       2) [ "$VERBOSE" != no ] && log_end_msg 1 ;; 
     esac 
     ;; 
    status) 
     status_of_proc "$DAEMON" "$NAME" && exit 0 || exit $? 
     ;; 
    #reload|force-reload) 
     # 
     # If do_reload() is not implemented then leave this commented out 
     # and leave 'force-reload' as an alias for 'restart'. 
     # 
     #log_daemon_msg "Reloading $DESC" "$NAME" 
     #do_reload 
     #log_end_msg $? 
     #;; 

    restart|force-reload) 
     # 
     # If the "reload" option is implemented then remove the 
     # 'force-reload' alias 
     # 
     log_daemon_msg "Restarting $DESC" "$NAME" 
     do_stop 
     case "$?" in 
      0|1) 
       do_start 
       case "$?" in 
         0) log_end_msg 0 ;; 
         1) log_end_msg 1 ;; # Old process is still running 
         *) log_end_msg 1 ;; # Failed to start 
       esac 
       ;; 
      *) 
       # Failed to stop 
       log_end_msg 1 
       ;; 
     esac 
     ;; 
    *) 
     #echo "Usage: $SCRIPTNAME {start|stop|restart|reload|force-reload}" >&2 
     echo "Usage: $SCRIPTNAME {start|stop|status|restart|force-reload}" >&2 
     exit 3 
     ;; 
esac 

: 

林想我已经错过了一些东西,当我键入daemonLCD启动它说没有找到命令。 任何输入都会很棒。

感谢

+0

你确定这就是它说的。它更可能是':命令未找到'或某些这样的...什么是foo? – SingleNegationElimination

+0

pi @ raspberrypi /etc/init.d $ daemonLCD start -bash:daemonLCD:command not found –

+0

'hostname -i'会更容易得到你当前的ip – tehmisvh

回答

9

假设你可能要管理的未来不止一个守护进程,让我推荐Supervisord。这比编写和管理你自己的init.d脚本简单得多。

例如,启动脚本会为包括这在conf一样容易:

[program:myscript] 
command=/usr/bin/python /path/to/myscript.py 

我使用的init.d脚本available here。它重命名为supervisord并将它复制到你的/etc/init.d/目录,然后运行:

sudo update-rc.d supervisord defaults 

我相信,初始化脚本supervisord运行的根为默认值。如果你愿意的话,你可以让它作为另一个用户运行。我不是如果孩子以根的方式运行,虽然我不认为。继续检查,但如果他们不这样做,你可以在supervisord.conf中的python命令之前粘上一个sudo,并在其中调用脚本。

它不运行,(或者如果你想supervisord作为非root用户运行,但仍然希望你的脚本以root身份运行),你可以允许任何人(或一组用户)运行python脚本作为根(尽管你应该确信这个脚本不能被root以外的任何人编辑)。

USERS ALL=(ALL) NOPASSWD: /path/to/myscript.py 

然后确保你在你的Python脚本的开头有一个家当并更改命令忽略蟒蛇:

你的sudoers文件与“命令visudo命令”文件,并添加以下到最后编辑呼叫,即:

[program:myscript] 
command=sudo /path/to/myscript.py 
+0

嗨,我一直在玩supervisord。我需要以root身份启动我的python脚本。我将如何做到这一点?我试图把用户= root放在[program:myscript]中,但它没有改变。 谢谢 –

+0

你还设置supervisord使用update-rc.d在启动时运行吗?如果是这样,我的意思是将我的supervisord文件从usr/local/bin移动到/etc/init.d?再次感谢 –

+0

让我知道如果更新的配置/根源的东西解决。 – sarwar

0

这是一个经典的错误新的Unix/Linux用户。 /etc/init.d不在你的路径中,这就是为什么你不能只运行daemonLCD。尝试使用完整路径(/etc/init.d/daemonLCD start)或预先考虑./(./daemonLCD start)。

该脚本需要是可执行的以上任何一个工作。

1

使用daemontools从DJB。这比提供的其他答案容易得多。对于初学者,您可以使用apt-get安装守护进程工具,因此您不必担心从主要内容抓取未知脚本,并且可以像通常一样通过debian获取更新。守护进程还负责在服务死亡并重新提供日志记录时重新启动服务。还有的daemontools和Debian的描述在这里:

http://blog.rtwilson.com/how-to-set-up-a-simple-service-to-run-in-the-background-on-a-linux-machine-using-daemontools/

DJB的页面AOUT daemontools

http://cr.yp.to/daemontools.html

0

感谢上面的代码。我一直在使用它来了解如何在Linux机器上设置守护进程。

随着一些调整,我可以让它工作得很好。

但是让我困惑的是。那是通过检查/var/run/myfile.pid的存在来检查进程是否正在运行。

这只是pidfile - 不是进程,对不对?

看看/lib/lsb/init-functions.status_of_proc

status_of_proc() { 
local pidfile daemon name status OPTIND 

pidfile= 
OPTIND=1 
while getopts p: opt ; do 
    case "$opt" in 
     p) pidfile="$OPTARG";; 
    esac 
done 
shift $(($OPTIND - 1)) 

if [ -n "$pidfile" ]; then 
    pidfile="-p $pidfile" 
fi 
daemon="$1" 
name="$2" 

status="0" 
pidofproc $pidfile $daemon >/dev/null || status="$?" 
if [ "$status" = 0 ]; then 
    log_success_msg "$name is running" 
    return 0 
elif [ "$status" = 4 ]; then 
    log_failure_msg "could not access PID file for $name" 
    return $status 
else 
    log_failure_msg "$name is not running" 
    return $status 
fi 
} 

,这只是处理访问PID文件的成功或失败。

现在,我正在构建这个守护进程去一个小设备。我发现它使用了BusyBox,我没有初始化函数:-( 但我有的pidof。

所以我添加

 log_success_msg "pidof $NAME is $(pidof -x $NAME)" >> $LOGFILE 
     log_success_msg "PIDFILE of $NAME is" >> $LOGFILE 
     sed -n '1p' < $PIDFILE >> $LOGFILE 

,并检查$日志文件,然后你瞧号码是不同的。

我做pstree -s -p在数字和

中的pidof数吐出了一个很短的树,所以它的根级进程

,但$ PIDFILE数字在分支后出现分支,所以我不认为pstree可以找到该进程。

是的,Joseph Baldwin Roberts的代码中的do_stop会杀死这两个进程。但是如果该过程以另一种方式被杀死,例如kill -9 12345,$ PIDFILE仍然存在。所以,这个守护进程会错误地认为这个进程已经开始拒绝了。

+0

两个进程编号差异的解决方案是在调用start-stop-daemon之前将PID编号写入$ pidfile(例如printf“$(pidof -x $ name)”>> $ pidfile) do_start。 – mycowan