最近产品上有用到一个叫 supervisord 的开源软件。
https://github.com/ochinchina/supervisordsupervisord 是一个进程管理软件,golang 写的, 3.5k star。
我们的产品上有多个服务程序要在后台长期运行,所以使用 supervisord 来守护并管理这些进程。
supervisord 非常适合嵌入式 linux 平台。
一方面,supervisord 可以帮我们在开机时后台启动多个服务程序,另一方面,当有服务异常退出时,supervisord 也能帮我们重新将服务拉起来,从而保证产品能长期正常工作。
supervisord 的代码非常值得我们阅读学习,不过今天不研究它。
我们来研究另外一个核心功能跟它类似,但是代码更加简单的开源软件:pman。
https://github.com/matsune/pmanpman 也是一个进程管理软件,不过它是 c++ 写的,代码仅 1420 行,麻雀虽小,五脏俱全,功能上也完全满足我们产品的需求。
pman 的用法举个例子:
$ cat /etc/pman.conf[pman]pidfile=/tmp/pman.pid ; pman daemon's pidfilelogfile=/tmp/pman.log ; pman daemon's logfileport=127.0.0.1:50010 ; grpc server portdirectory=/tmp ; default is current dir[program:ls]command=/bin/ls ; program commandstdout=/tmp/sample_stdout.log ; program stdout logfile (default: /tmp/${program name}_stdout.log)stderr=/tmp/sample_stderr.log ; program stderr logfile (default: /tmp/${program name}_stderr.log)autorestart=true ; automatically restart if exited unexpectedlyautostart=true ; start program on daemon's startup这个配置文件指定了一个需要运行的程序:ls,并且指定了它的标准输出输出,以及是否要自动重启等属性。
运行效果:
$ ./pman status -c pman.conf [sleep] running pid: 15283 uptime: 00:00:04$ ./pman stop sleep -c pman.conf [sleep] stopping$ ./pman status -c pman.conf [sleep] stopping$ ./pman start sleep -c pman.conf [sleep] running pid: 15370 uptime: 00:00:00内部实现
pman 源码一共才 1420 行,非常适合我们用来学习进程管理类工具的实现原理。
$ wc -l * 222 cmd_parser.cpp 45 cmd_parser.hpp 32 conf.cpp 47 conf.hpp 80 conf_parser.cpp 23 conf_parser.hpp 222 daemon.cpp 41 daemon.hpp 29 defines.h 126 main.cpp 56 pid_file.cpp 15 pid_file.hpp 88 pman_client.cpp 21 pman_client.hpp 188 pman_service_impl.cpp 39 pman_service_impl.hpp 35 program.cpp 27 program.hpp 21 task.hpp 54 util.cpp 9 util.hpp 1420 total简单过一下源码,抓主干:
int main(){ [...] if (cmdparser.command() == daemon) { // 守护模式,并启动 server return runserver(confparser.pmanconf(), confparser.programconfs()); } else if (cmdparser.command() == kill) { return killserver(confparser.pmanconf(); } else { // client 模式,会去访问 server return runclient(confparser.pmanconf().port(), cmdparser.command(), cmdparser.program()); }}pman 自己本身就是一个守护服务,当没有传递 status、stop、start 等参数时,pman 会以守护进程的方式运行:
int runserver(...){ // 将自己编程守护进程 daemon daemon(pmanconf, programconfs); daemon.setup(); // 创建 server 线程 thread(rungrpcserver, pmanconf.port(), ref(daemon)).detach(); // 启动配置文件中指定的所有程序 return daemon.runloop();}server 线程会建立一个 rpcserver,使用到了 google 的 grpc 组件:
https://github.com/grpc/grpc简单来说,就是为了实现 status/stop/start 等命令以 rpc client 的方式去调用到 pman 守护进程内的函数 api,这里就不详细展开了。
接着看 runloop()
int daemon::runloop(){ // 启动所有的用户程序 for (auto program = this->programs_.begin(); program != this->programs_.end(); ++program) { if (program->autostart()) startprogram(*program); } // 循环处理用户的命令行 的操作 while (!abrt_status) { // 取出用户指令 while (!tasks_.empty()) { task task = tasks_.front(); // start / stop 程序 } }}上面的代码只是 pman 的主逻辑,其他很多功能,例如命令行参数的解析、配置文件的解析、程序的管理等功能,都被良好地封装起来了,所以我们看起来才会这么清晰明了。
总结对于嵌入式 linux 的产品,如果需要长期守护住应用程序的运行,可以考虑部署 supervisord 或者 pman 等进程管理工具。
建议优先考虑考虑 go 版本 supervisord,一方面是因为 go 应用部署非常简单,只要拷贝一个可执行文件即可,另一方面也是因为 supervisord 的用户更多、活跃度更高,功能更完善。
如果你开发的产品上没有 go 环境,性能也有限,类似路由器 openwrt 系统,那就考虑采用 pman,对其加以定制以满足最终的需求。
最后,这两个开源工具的代码可读性都非常的好,很适合用来锻炼和提升 go / c++ 的编程能力,喜欢研究技术的小伙伴们,可以品读一下源码,肯定会有所收获。
线路板是怎样制作的
美企推出四分之一晶片,可连接带有图像采集卡的主机PC
中国移动全家WiFi发布,实现进一步改善移动用户家庭网络质量
超声波清洗机功率越大,清洗效果越好么?
“机器行为学” 这门跨越多个研究领域的新兴学科正式诞生
什么是pman?
PCB线路板过孔对信号传输有什么影响
赛睿APEXPRO机械键盘高清图集
英特尔发布第11代酷睿处理器,助推多种应用场景实现数字化转型
关于固体环网柜的应用,它的核心技术是什么
Linux socket底层的相关实现
苹果笔记本有望为iPhone无线充电
电容传感器产品设计要点:漂移补偿+寄生电容
宝马正式推出第八代iDrive操作系统,未来该系将率先搭载于宝马iX
玩转双11,CANON EOS M100缤纷微单任你选!
保密!麦捷科技回复为华为P40系列提供SAW滤波器
在医疗领域掘金的人工智能企业,必须要有身为拓荒者心理准备
数字视频驱动通用基础设施的开放标准
虫情测报灯与物联网技术的结合提升了工作效率
华为助力中国电信实现全球首个5G音视频通话