即使在 /etc/rc.local 中出现无限循环也能正常启动

即使在 /etc/rc.local 中出现无限循环也能正常启动

我放入了一个无限循环的 python 脚本,/etc/rc.local但机器成功启动,这让我很困惑。

内容/etc/rc.local

#!/bin/sh -e
#
# rc.local
#
# This script is executed at the end of each multiuser runlevel.
# Make sure that the script will "exit 0" on success or any other
# value on error.
#
# In order to enable or disable this script just change the execution
# bits.
#
# By default this script does nothing.

# Print the IP address
_IP=$(hostname -I) || true
if [ "$_IP" ]; then
  printf "My IP address is %s\n" "$_IP"
fi

/home/pi/py/startsignal.py &
/home/pi/py/fan.py
touch /home/pi/thisisrun
exit 0

启动信号.py

#!/usr/bin/python
import RPi.GPIO as GPIO

GPIO.setmode(GPIO.BCM)
GPIO.setup(18, GPIO.OUT)

GPIO.output(18, 1)

粉丝.py

#!/usr/bin/python
# coding: utf8
import RPi.GPIO as gpio

gpio.setmode(gpio.BCM)
upper_temp = 55
lower_temp = 45
# minutes
check_interval = 2

def get_temp():
    with open('/sys/class/thermal/thermal_zone0/temp', 'r') as f:
        temp = float(f.read()) / 1000
    return temp

def check_temp():
    if get_temp() > upper_temp:
        gpio.setup(23, gpio.OUT)
    elif get_temp() < lower_temp:
        gpio.setup(23, gpio.IN)

if __name__ == '__main__':
    # check every 2 minutes
    try:
        while True:
            check_temp()
            sleep(check_interval * 60)
    finally:
        gpio.cleanup()

所有相关代码都在上面。我在谷歌搜索后想到了这一点。

  1. 表示#!/bin/sh -e一旦发生错误,脚本就会退出。
  2. /home/pi/thisisrun文件没有创建,所以这一行上面一定有错误
  3. 启动进入系统后我可以看到它fan.py正在运行。所以我猜这个错误是在执行过程中发生的fan.py。但其中fan.py有一个无限循环!

python脚本如何产生错误但仍然正常运行?

当永远不会返回时如何/bin/sh检测错误fan.py

操作系统:raspbian 拉伸

答案1

假设 Raspbian Stretchsystemd默认情况下像常规 Debian Stretch 一样使用,/etc/rc.local启动方式为/lib/systemd/system/rc-local.service

#  This file is part of systemd.
#
#  systemd is free software; you can redistribute it and/or modify it
#  under the terms of the GNU Lesser General Public License as published by
#  the Free Software Foundation; either version 2.1 of the License, or
#  (at your option) any later version.

# This unit gets pulled automatically into multi-user.target by
# systemd-rc-local-generator if /etc/rc.local is executable.
[Unit]
Description=/etc/rc.local Compatibility
ConditionFileIsExecutable=/etc/rc.local
After=network.target

[Service]
Type=forking
ExecStart=/etc/rc.local start
TimeoutSec=0
RemainAfterExit=yes
GuessMainPID=no

正如它所指定的Type=forking,TimeoutSec=0RemainAfterExit=yes,我理解 systemd 基本上启动它并且不关心它是否退出。这就解释了为什么系统即使/etc/rc.local仍在运行也能成功完成启动。

您的rc.local脚本首先startsignal.py在后台运行(= 带有&):这意味着只有启动脚本失败才会导致rc.local此时脚本出现错误。如果startsignal.py成功启动但随后返回错误,rc.local则必须使用wait <process or job ID>从进程中读取传入的错误startsignal.py。但你的过程显然不关心检查这一点。

然后你的rc.local开始fan.py。由于它是在没有 的情况下启动的&,因此 shell 会启动另一个进程来运行fan.py并等待它退出...但由于fan.py有一个无限循环,因此它不会退出,直到系统关闭、fan.py出现错误或进程正在运行fan.py被杀了。只有退出touch /home/pi/thisisrun后才会执行。fan.py

我认为开始更有意义startsignal.py 没有&fan.py 它,而不是相反。

相关内容