轉載自:https://www.jianshu.com/p/acd2ccb5ea8d
編寫一個openwrt package程序,使用procd方式編寫/etc/init.d/xxx 自啟動腳本,就能擁有程序的監控,異常退出重新拉起功能
示例
root@xxx:~# cat /etc/init.d/testpro #!/bin/sh /etc/rc.common # Copyright (C) 2006-2011 OpenWrt.org START=18 USE_PROCD=1 PROG=/usr/sbin/testpro start_service() { procd_open_instance procd_set_param command "$PROG" procd_set_param respawn 0 procd_close_instance } stop_service(){ service_stop "$PROG" }
其中,procd_set_param respawn 0,respawn設置進程掛掉自動重啟
通常的嵌入式系統均有一個守護進程,該守護進程監控系統進程的狀態,如果某些系統進程異常退出,將再次啟動這些進程。procd 就是這樣一個進程,它是使用C語言編寫的,一個新的 OpenWrt 進程管理服務。它通過init腳本來將進程信息加入到 procd 的數據庫中來管理進程啟動,這是通過ubus總線調用來實現,可以防止進程的重復啟動調用。
procd 的進程管理功能主要包含 3 個部分。
- reload_config,檢查配置文件是否發生變化,如果有變化則通知 procd 進程。
- procd,守護進程,接收使用者的請求,增加或刪除所管理的進程,並監控進程的狀態,如果發現進程退出,則再次啟動進程。
- procd.sh,提供函數封裝procd提供系統總線方法,調用者可以非常便利的使用procd 提供的方法。
root@zihome:/etc/init.d# cat /var/run/config.md5 b9f0f9179b5b407ff85430da41877ba3 /var/run/config.check/dhcp ce8e9fffa77a896c43cdeb2b83dede88 /var/run/config.check/dropbear 92a19521dd5c8cacd08e64e2785d94b1 /var/run/config.check/firewall 736bccfcc298fcdac1016da5f58518e1 /var/run/config.check/fstab 751c2e2ff80f2952b4c866fbc1d52f7d /var/run/config.check/guide b9111c52e6db67b7bf550d5701a44e5f /var/run/config.check/htpdate bad4e7384734245500ed9c081e0009f5 /var/run/config.check/igmpproxy 645f0a3cbfd1cf565b920dfd897af0c5 /var/run/config.check/network 3165f4af5f45e3209f9e20e28a78a76a /var/run/config.check/rpcd 87701d34b6de4ec46e6cb5edf1ac5f74 /var/run/config.check/system 6ec4ee52ca677ac87ff2469607a8cf9f /var/run/config.check/uhttpd 0ba26b28318a2a2d879fdad87f8e8c56 /var/run/config.check/upnpd 775e2ac3058da3ea2e973b3747233b92 /var/run/config.check/webpage 009ba5a3f9130b74662822d36d3ecd37 /var/run/config.check/wifidev 741a39d373e3c6f2dbeff47ca145606b /var/run/config.check/wireless af357fab720926629ad9ab2ff4f465e1 /var/run/config.check/zihome e2e3d1e8532386200a708f0c6837830c /var/run/config.check/zqos
如果在自己的啟動腳本中定義了 USE_PROCD 那就調用這些函數。在 rc.common 中重
新定義了 start 函數,相當於重載了這些函數。
函 數 | 含 義 |
---|---|
start_service | 向 procd 注冊並啟動服務,是將在 services 所管理對象里面增加了一項 |
stop_service | 讓 procd 解除注冊,並關閉服務, 是將在 services 中的管理對象刪除 |
service_triggers | 配置文件或網絡接口改變之后觸發服務重新讀取配置 |
service_running | 查詢服務的狀態 |
reload_service | 重啟服務,如果定義了該函數,在 reload 時將調用該函數,否則再次調用 start 函數 |
service_started | 用於判斷進程是否啟動成功 |
舉例:
通常有兩行內容是固定的,第一
行表示使用“/etc/rc.common”來解釋腳本。
第二行內容設置 USE_PROCD 變量為 1,表示使
用 procd 來管理進程
(1)pprocd_open_instance 開始增加一個服務實例。
(2)procd_set_param 設置服務實例的參數值,通常會有以下幾種類型的參數。
- command: 服務的啟動命令行。
- respawn: 進程意外退出的重啟機制及策略,它需要有 3 個設置值。第一個設置為判斷異常失敗邊界值(threshold),默認為3600秒,如果小於這個時間退出,則會累加重新啟動次數,如果大於這個臨界值,則將重啟次數置 0。第二個設置為重啟延遲時間(timeout),將在多少秒后啟動進程,默認為5秒。第三個設置是總的失敗重啟次數(retry),是進程永久退出之前的重新啟動次數,超過這個次數進程退出之后將不會再啟動。默認為 5 次。也可以不帶任何設置,那這些設置都是默認值。
- env:進程的環境變量。
- file:配置文件名,比較其文件內容是否改變。
- netdev:綁定的網絡設備(探測 ifindex 更改)。
- limits:進程資源限制。
每次只能使用一種類型參數,其后是這個類型參數的值。
(3)procd_close_instance 完成進程實例的增加。
vim /etc/init.d/zdetect
#!/bin/sh /etc/rc.common
USE_PROCD=1
START=88
STOP=92
start_service() {
procd_open_instance
procd_set_param command /usr/bin/zdetect
procd_set_param respawn
[ -e /proc/sys/kernel/core_pattern ] && {
procd_set_param limits core="unlimited"
}
procd_close_instance
}
vim /etc/init.d/zboard
#!/bin/sh /etc/rc.common
USE_PROCD=1
START=18
STOP=82
start_service() {
procd_open_instance
local wan_port=$(uci -q get zihome.system.wanport)
local wan_status=0
[ -z "$wan_port" ] && {
wan_port=0
}
if [ -f /tmp/status/wan_port_status ]; then
wan_status=$(cat /tmp/status/wan_port_status)
fi
procd_set_param command /usr/bin/zboard -p $wan_port -s $wan_status
procd_set_param respawn
[ -e /proc/sys/kernel/core_pattern ] && {
procd_set_param limits core="unlimited"
}
procd_close_instance
}
stop_service() {
local zboard_pid=""
zboard_pid=`ps -w | grep -w "/usr/bin/zboard" | grep -v grep| awk '{print $1}'`
if [ "${zboard_pid}" != "" ];then
kill -9 ${zboard_pid}
fi
}
(4)procd_add_reload_trigger,增加配置文件觸發器,每次配置文件的修改,如果調用了reload_config時,當前實例都被重啟。有一個可選的參數為配置文件名稱。其實它在內部是調用procd_open_trigger、procd_add_config_trigger和procd_close_trigger這3個函數來增加觸發器。
(5)procd_open_validate,打開一個驗證數組,是和 procd_close_validate 函數一起使用。
(6)procd_close_validate,關閉一個驗證數組。示例 8-9 是軟件包 firewall使用procd來對防火牆配置的觸發器和驗證。
(7)procd_open_service(name, [script]),至少需要一個參數,第一個參數是實例名稱,第二個參數是可選參數為啟動腳本。該函數僅在在rc.common 中調用,用於創建一個新的procd進程服務消息。
(8)procd_close_service,該函數不需要參數,僅在 rc.common 中調用,完成進程管理服務的增加。
(9)procd_kill,殺掉服務實例(或所有的服務實例)。至少需要一個參數,第一個參數是服務名稱,通常為進程名,第二個是可選參數,是進程實例名稱,因為可能有多個進程示例,如果不指定所有的實例將被關閉。該函數在 rc.common 中調用,用戶從命令行調用 stop 函數時會使用該函數殺掉進程。
(10)uci_validate_section,調用 validate_data 命令注冊為驗證服務。在配置發生改變后對配置文件的配置項合法性進行校驗。驗證服務是在進程啟動時通過 ubus 總線注冊到procd進程中。輸入以下命令,可以看到系統所有注冊的驗證服務。