監控Linux進程
原文 http://huoding.com/2015/02/11/419
有時候,進程突然終止服務,可能是沒有資源了,也可能是意外,比如說:因為 OOM 被殺;或者由于 BUG 導致崩潰;亦或者誤操作等等,此時,我們需要重新啟動進程。
實際上,Linux 本身的初始化系統能實現簡單的功能,無論是老牌的 SysVinit,還是新潮的 Upstart 或者 Systemd 均可,但它們并不適合處理一些復雜的情況,比如說:CPU 占用超過多少就重啟;或者同時管理 100 個 PHP 實現的 Worker 進程等等,如果你有類似的需求,那么可以考慮試試 Monit 和 Supervisor ,相信會有不一樣的感受。
讓我們看看 Monit 的用法,假設我們要監控 Nginx 進程,一旦其 CPU 使用率連續 5 次超過 80% 的話,就重啟進程,此時就可以按照如下方式設置:
check process nginx with pidfile /var/run/nginx.pid start program = "/etc/init.d/nginx start" stop program = "/etc/init.d/nginx stop" if cpu is greater than 80% for 5 cycles then restart
Monit 根據 pidfile 輪詢對應的進程是否健在,滿足條件就執行 start/stop 等操作。如果進程本身不存在 pidfile,那么也可以使用 matching 語法來匹配進程。
再讓我們看看 Supervisor 的用法,假設我們要監控 100 個 PHP 實現的 Worker 進程,用來提供 Gearman 之類的服務,由于 PHP 本身運行模式的緣故,為了避免嚴重的內存泄漏問題,我們設定 PHP 進程服務一定次數或一段時間后就自動退出,這時候我們需要啟動新的 Worker 進程,以便總數維持不變,此時就可以按照如下方式設置:
[program:worker] command=/usr/bin/php /path/to/worker.php process_name=%(program_name)s_%(process_num)02d numprocs=100 autostart=true autorestart=true
如果說 Supervisor 有什么缺點的話,那么首當其沖的是對使用者而言它不夠透明:很多進程都是后臺運行的,但 Supervisor 卻要求必須改成前臺運行。好在多數服務都提供了對應的配置選項,如果沒有的話,我們也可以使用一些變通的方法:
- How can I supervise a daemon that puts itself into the background?
- Managing daemons with supervisor: no foreground mode available.
不管用什么來監控進程,如果監控者本身掛了,那么被監控者無疑就失控了。此時需要考慮如何監控監控者本身,這似乎是一個遞歸問題,不過文章開頭我們說過,Linux 本身的初始化系統就能實現簡單的監控功能,以 SysVinit 為例,編輯 /etc/inittab 文件:
SU:2345:respawn:/usr/bin/supervisord -c /etc/supervisord.conf
改好后運行「init q」命令讓其生效,然后 kill 掉 supervisor 進程看看會不會發生奇跡。
注意:記得事先我們要配置 Supervisor 為 nodaemon=true 噢。