树莓派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.logis empty - When running
sh /etc/rc.localmanually: Log file correctly showsMy 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
PATHas yourpiuser.
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 15gives 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
3. Systemd Service (Recommended for Reliability)
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 yourpiuser, 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
ImportErrorin logs, install the library as thepiuser (since systemd runs aspi):pip install Adafruit-CharLCD paho-mqtt - Permission Issues: Ensure your certificate files in
/home/pi/Cigar-Box/certs/are readable by thepiuser: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

