You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

树莓派Python脚本无法通过rc.local/crontab/systemd启动求助

Let's dig into this startup issue step by step. First, let's recap what's happening: your Python script runs perfectly when executed manually (either as the pi user or via sh /etc/rc.local), but none of the three startup methods (rc.local, crontab @reboot, systemd) get it running on boot. Even the IP logging in rc.local fails on reboot but works when you run it manually—this tells us the problem is likely related to the execution environment or timing during boot, not the script itself.


Your Python Script (for reference)

#!/usr/bin/python
#required libraries
import sys
import ssl
import paho.mqtt.client as mqtt
import json
from pprint import pprint
import Adafruit_CharLCD as LCD
from textwrap import fill

#Configuration
rootCAPath = "/home/pi/Cigar-Box/certs/rootCA.pem"
certFilePath = "/home/pi/Cigar-Box/certs/xxxxxxxxxx-certificate.pem.crt"
keyFilePath = "/home/pi/Cigar-Box/certs/xxxxxxxxxx-private.pem.key"
iotThing = "Zorua"
clientID = "Zorua"

#Device JSON initialization
device = {'state': {'reported': {'HP':100} } }
device['state']['reported']['color'] = {'r':0, 'g':0, 'b':0}

#Create LCD
lcd = LCD.Adafruit_CharLCDPlate()

#LCD wrapper
def set_lcd_color(R,G,B):
    global lcd
    device['state']['reported']['color']['r'] = R
    device['state']['reported']['color']['g'] = G
    device['state']['reported']['color']['b'] = B
    lcd.set_color(R, G, B)

def set_lcd_message(message):
    global lcd
    device['state']['reported']['msg'] = message
    lcd.clear()
    #Word wrap to fit 16-char wide display and add capitalization
    lcd_message = fill(message.capitalize(),16)
    lcd.message(lcd_message)

# Initialize the LCD using the pins
set_lcd_message('Initializing...')
set_lcd_color(0, 0, 1)

#called while client tries to establish connection with the server
def on_connect(mqttc, obj, flags, rc):
    print "Connecting..."
    if rc==0:
        print ("Subscriber Connection status code: "+str(rc)+" | Connectionstatus: successful")
        #We only want to be notified about things we need to change to stay in sync with AWS
        mqttc.subscribe("$aws/things/" + iotThing + "/shadow/update/delta", qos=1)
    elif rc==1:
        print ("Subscriber Connection status code: "+str(rc)+" | Connection status: Connection refused")
    print ("Subscriber Connection status code: "+str(rc))

#called when a topic is successfully subscribed to
def on_subscribe(mqttc, obj, mid, granted_qos):
    print("Subscribed: "+str(mid)+" "+str(granted_qos)+"data"+str(obj))
    set_lcd_color(0,1,0)
    set_lcd_message('Connected!\nReady for input')
    #Let AWS know about the current state of the plate so we can tell us what's out of sync
    mqttc.publish("$aws/things/" + iotThing + "/shadow/update", json.dumps(device))

#called when a message is received by a topic
#Messages are formatted in JSON
#When working with /update, we might not find all keys all the time, so we need to handle that
def on_message(mqttc, obj, msg):
    try:
        data = json.loads(msg.payload)
        update = data['state']
    except:
        return
    #Look for a message in the update. If it's there, we need to update the display
    if 'msg' in update.keys():
        try:
            set_lcd_message(update['msg'])
        except:
            print("Could not enact message from topic: "+msg.topic+" | QoS: "+str(msg.qos)+" | Data Received: "+str(msg.payload))
    #Look to see if the status of R, G, or B has changed for the display
    if 'color' in update.keys():
        try:
            lcd_r = update['color']['r']
        except:
            lcd_r = device['state']['reported']['color']['r']
        try:
            lcd_g = update['color']['g']
        except:
            lcd_g = device['state']['reported']['color']['g']
        try:
            lcd_b = update['color']['b']
        except:
            lcd_b = device['state']['reported']['color']['b']
        set_lcd_color(lcd_r, lcd_g, lcd_b)
    #Let AWS know we've updated the display
    mqttc.publish("$aws/things/Zorua/shadow/update", json.dumps(device))

#creating a client with client-id=Zorua
mqttc = mqtt.Client(client_id=clientID)
mqttc.on_connect = on_connect
mqttc.on_reconnect = on_connect
mqttc.on_subscribe = on_subscribe
mqttc.on_message = on_message

#Configure network encryption and authentication options. Enables SSL/TLS support.
#adding client-side certificates and enabling tlsv1.2 support as required by aws-iot service
mqttc.tls_set(rootCAPath, certfile=certFilePath, keyfile=keyFilePath, tls_version=ssl.PROTOCOL_TLSv1_2, ciphers=None)

#connecting to aws-account-specific-iot-endpoint
print ("About to connect")
mqttc.connect("lettersandnumbers.iot.us-west-2.amazonaws.com", port=8883) #AWS IoT service hostname and portno

#automatically handles reconnecting
mqttc.loop_forever()

Your /etc/rc.local & Test Results

# Default code located inside /etc/rc.local
# Print the IP address
_IP=$(hostname -I) || true
if [ "$_IP" ]; then
  printf "My IP address is %s\n" "$_IP" > /home/pi/cigarbox.log
fi
exit 0

Test Behavior:

  • After reboot: /home/pi/cigarbox.log is empty
  • When running sh /etc/rc.local manually: Log file correctly shows My IP address is 192.168.0.21

1. Fix /etc/rc.local First

The empty log after reboot tells us rc.local is either running too early (before network is ready) or missing critical configuration. Here's how to fix it:

Step 1: Add a Shebang & Execution Permission

rc.local needs a proper shebang to run correctly. Add this to the very top of the file:

#!/bin/bash

Then set execution permissions:

sudo chmod +x /etc/rc.local

Step 2: Delay Execution for Network Readiness

hostname -I returns empty on reboot because the network hasn't finished initializing yet. Add a sleep to wait for it:

#!/bin/bash
# Wait 10 seconds for network to come up
sleep 10

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

# Add your Python script startup (use absolute paths!)
/usr/bin/python /home/pi/Cigar-Box/your_script_name.py > /home/pi/cigarbox_script.log 2>&1 &

exit 0
  • The 2>&1 & redirects all output (including errors) to a log file and runs the script in the background.
  • Use absolute paths for Python and your script—boot environments don't have the same PATH as your pi user.

Step 3: Verify rc-local Service Status

After reboot, check if the service ran correctly:

systemctl status rc-local.service

If there are errors, they'll show up here to help debug.


2. Fix Crontab @reboot

Crontab runs with a minimal environment, so we need to mimic your pi user's setup and add a delay:

Step 1: Edit Pi User's Crontab

Run this as the pi user:

crontab -e

Step 2: Add the Reboot Command

Add this line at the end:

@reboot sleep 15 && /usr/bin/python /home/pi/Cigar-Box/your_script_name.py > /home/pi/cigarbox_cron.log 2>&1
  • sleep 15 gives more time for network and dependencies to load.
  • The log file will capture any errors that occur during boot.

Step 3: Verify Cron Service

Make sure cron is running:

systemctl status cron.service

Systemd is the modern way to manage services on Linux—it's more stable, handles restarts automatically, and provides clear logging. This is the best long-term solution.

Step 1: Create a Systemd Service File

sudo nano /etc/systemd/system/cigarbox.service

Step 2: Paste This Configuration

[Unit]
Description=Cigar Box MQTT LCD Service
After=network.target
Wants=network.target

[Service]
User=pi
WorkingDirectory=/home/pi/Cigar-Box
ExecStart=/usr/bin/python /home/pi/Cigar-Box/your_script_name.py
Restart=always
RestartSec=5
StandardOutput=append:/home/pi/cigarbox_systemd.log
StandardError=append:/home/pi/cigarbox_systemd.log

[Install]
WantedBy=multi-user.target
  • User=pi: Runs the script as your pi user, matching the environment where it works manually.
  • After=network.target: Ensures the service starts only after the network is ready.
  • Restart=always: Automatically restarts the script if it crashes.
  • Logs are appended to a file for easy debugging.

Step 3: Enable & Start the Service

sudo systemctl daemon-reload
sudo systemctl enable cigarbox.service
sudo systemctl start cigarbox.service

Step 4: Check Service Status

sudo systemctl status cigarbox.service

If it fails, check the log file /home/pi/cigarbox_systemd.log for specific errors (like missing libraries or permission issues).


Common Debugging Tips

  • Missing Libraries: If you see ImportError in logs, install the library as the pi user (since systemd runs as pi):
    pip install Adafruit-CharLCD paho-mqtt
    
  • Permission Issues: Ensure your certificate files in /home/pi/Cigar-Box/certs/ are readable by the pi user:
    chmod 644 /home/pi/Cigar-Box/certs/*.pem /home/pi/Cigar-Box/certs/*.crt
    
  • Log Files: Always check the log files you set up—they'll tell you exactly why the script isn't starting.

内容的提问来源于stack exchange,提问作者electronical

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.05.28 10:05:57