笔者前段时间看到有个用 QT写的进程守护程序,在程序有卡死等问题时就依靠单独的守护程序来做健康检查,重启进程。
说到进程守护问题,那离不开以前写的脚本了,不管时Windows(tasklist 或qprocess)或者Linux(ps配合grep或pgrep)平台上,脚本判断进程是否存在,如果不存在就开启进程,然后将脚本加入到Windows任务计划程序或者Linux的cron定时任务中来定时检查进程是否存在。但是有个问题,进程存在但是进程已经卡死,这种情况普通脚本是无法感知的。那么进程卡死后,从技术上怎么怎么实现呢?
Linux上在使用systemd管理.service时可以设置Restart选项。我们来搜索一下man -k systemd.service ,定位到systemd.service (5) - Service unit configuration ,然后使用man 5 systemd.service来搜索restart。
部分翻译如下:
选项的值可以取 no, on-success, on-failure, on-abnormal, on-watchdog, on-abort, always 之一。 no(默认值) 表示不会被重启。 always 表示会被无条件的重启。 on-success 表示仅在服务进程正常退出时重启, 所谓"正常退出"是指:退出码为"0", 或者进程收到 SIGHUP, SIGINT, SIGTERM, SIGPIPE 信号之一, 并且 退出码符合 SuccessExitStatus= 的设置。 on-failure 表示 仅在服务进程异常退出时重启, 所谓"异常退出" 是指: 退出码不为"0", 或者 进程被强制杀死(包括 "core dump"以及收到 SIGHUP, SIGINT, SIGTERM, SIGPIPE 之外的其他信号), 或者进程由于 看门狗超时 或者 systemd 的操作超时 而被杀死。
那么进程卡死,可以Restart设置Watchdog,可以实现在失败状态下的自动重启该服务。 WatchdogSec可以配置该服务的看门狗(watchdog)的超时时长。但是笔者没有测试过Watchdog,所以不便细说感受。
除了systemd.service的定义外,笔者总结了其他几种方法。
1、在程序界面上直接写上时间,如果时间停止更新,那么就是程序卡死。当然这属于人肉运维,需要定期巡检。
2、通过心跳检测来判断,程序定时发送信息到特定的接口或者直接广播/组播心跳信息,在经过几个周期后杀死进程,Windows的taskkill或者Linux的kill或者pkill 。
那笔者就使用虚拟仪器来测试一番。现在对于LabVIEW可以几个钟搞定一个程序,实在是太方便了。笔者选用数据通信的通知器来实现,与队列操作函数不同,通知器操作函数不缓冲已发送的消息。读者可以想想为啥不缓冲呢,如果缓冲会啥问题呢?
1、需守护的程序
事件结构里面分为手动关闭和超时时定时发送时间字符串,因为对于手动关闭需要另外处理,不需要进程守护做其他操作。
2、进程守护程序
根据通知器接收到的字符串来分别处理。里面具体实现我就不写了,无非就是判断接收到的时间字符串和现在的时间字符串对比,超过设定的值即判断程序卡死。手动关闭程序则不做任何操作。
利用通知器引用相同的通知器名称可以在内存中完成数据通信。而且通知器的原理也适合做进程状态的判断。你可能会有疑问,就不怕进程守护程序卡死吗?看看进程守护程序的内存使用,只要通知器里面没有插入数据,那么进程守护程序就会一直等待,不会消耗资源。只要控制需要守护的程序的插入通知器的频率,那么这么小的进程守护程序有个没啥问题。
网友评论