文章程式碼顯示

2018年7月7日 星期六

一起學 Python 104 : Raspberry pi 開機自動運行 Python 程式碼

(方法1) 更改 /etc/rc.local (可參考)

1. sudo su

2. sudo nano /etc/rc.local

3. 在 exit0 上一行加入  sudo python /xx/xx/xx.py

實測 : 失敗 20181018成功(原因如下綠字部分)

就算我依 一起學 Python 102 修正預設的 python 版本後,

使用 sudo /etc/rc.local

還是會出現沒有 import module 的問題。但如果直接輸入 python /xx/xx/xx.py 是可以的,原因不明

20181018 更新

我找到一個簡單的方法。在參考連結中有人提出一樣的問題,其下的回答大致上的意思是說"因為在安裝外部 module 的時候我們只有將其安裝到 "pi" 使用者上,而使用  /etc/rc.local  此方法開機自啟動時,使用的是 "root" 使用者(而我們平常在終端機操作 Rpi 時執行文件等等的都是使用 "pi" 使用者",所以才會發生找不到 module 的情況。

遇到這情形可使用

sudo -u pi python /xx/xx/xx.py

改以 "pi" 使用者執行 python 檔

P.S. :  此方法有個需要注意的點,如果你的 python 檔具有 blocking 的特性。例如說你總共要開啟五個檔案,但你的第一個檔案(python)程式內容會有迴圈讓程式卡在裡面的,則你必須使用 "&" 後綴在指令後面解決這個問題,也就是說告知系統以一個子進程的方式開啟檔案,如

sudo -u pi python /xx/xx/xx.py &


(方法2) /home/pi/.config 中新增 *.desktop 腳本 (可參考)

/home/pi/.config 下找到名為 autostart 的文件夾,如果沒有就新創建一個。

在該文件夾下創建一個 xxx.desktop 文件,文件名自擬,後綴必須是 desktop

xxx.desktop 的內文為

[Desktop Entry]
Type=Application
Name=test
Comment=Python Program
Exec=sudo -H -u pi python /home/pi/test.py

實測 : 成功

(方法3) /etc/init.d 中新增腳本 (可參考)

1. sudo su
2. sudo nano /etc/init.d/TEST

... (後續請參考參考連結)


實測 : 失敗(原因我懶得查了,這方法有點麻煩)

(方法4) 在  /home/pi/.config/lxsession/LXDE-pi/autostart 加入路徑 (可參考)

此方法最簡易,且可以打開終端機,從電腦上顯示出 print 的那些字

步驟如下
1. sudo su
2. sudo nano /home/pi/.config/lxsession/LXDE-pi/autostart
3. 在最後面加入 @lxterminal -e python /full/path/to/your/script




我使用此法後,有一天莫名發現我桌面的 "工具欄" 消失了

解決辦法請看 一起學 Python 108 : Raspberry pi 桌面的工具列消失 解決辦法

實測 : 成功又簡單


(方法5) 使用 service 的方法開機自啟動

假設要開機自啟動的 python 文件以及名稱為以下

/home/pi/python_program/PiTurnON_v1.0.0.py

執行步驟

1. 進入 /lib/systemd/system/ 目錄底下

cd /lib/systemd/system/

2. 開起一個 service 編譯檔

sudo nano PiTurnON.service

3. 於該 service 編譯檔中鍵入以下內容

[Unit]
Description=EqNotifyMQTT
After=multi-user.target

[Service]
Type=simple
User = pi
ExecStart=/usr/bin/python -u /home/pi/python_program/EqNotifyMQTT_v2.3.6.py
Restart=on-abort

[Install]
WantedBy=multi-user.target

4. 對該 service 編譯檔設定權限( 777 代表所有使用者皆可以 讀/寫/執行 該檔案)
相關可參考此連結

sudo chmod 777 /lib/systemd/system/PiTurnON.service

5. 對 python 檔設定權限( a=rwx 亦代表所有使用者皆可以 讀/寫/執行 該檔案)
相關可參考此連結

chmod a=rwx /home/pi/python_program/PiTurnON_v1.0.0.py

6. Reload systemd manager configuration, scanning for new or changed units

sudo systemctl daemon-reload

7. Enable a service to be started on bootup and Start immediately

sudo systemctl enable PiTurnON.service

8. Start service

sudo systemctl start PiTurnON.service

更多與 systemctl 相關的指令如下(用來查看或重啟 service 的狀態)

# Check status
sudo systemctl status EqLineNotify.service

# Stop service
sudo systemctl stop PiTurnON.service

# Restart service
sudo systemctl restart EqLineNotify.service

# Check service's log
sudo journalctl -f -u EqLineNotify.service

補充(20181108) :

我在某個 python 應用中有使用 apscheduler 的  BackgroundScheduler
企圖讓這個 python 程式碼在某個時間點執行某一段程式碼
原本的程式碼中我將這段程式碼 add_job 以及 start 後就沒有後續的程式碼了

但我發現如果這樣子的話,當排定到開機啟動的 service 後
沒多久這個 service 就會死掉 (status : dead)

我在 Restart 中是設定 on-abort 的
這個設定會讓程式碼遇到"錯誤"的時候自動重啟
但或許沒有包含這種 "長時間待命不幹事" 而被 service 關閉的情形
他並沒有幫我自動重啟

故我在程式碼的最後隨意寫了一個 while 迴圈,搭配 time.sleep 以及 print 讓他幹點事
這問題就解決了

HOW TO RUN A SCRIPT AS A SERVICE IN RASPBERRY PI - RASPBIAN JESSIE

↓↓↓ 連結到部落格方針與索引 ↓↓↓

Blog 使用方針與索引