我是老吴,一个爱学习的,嵌入式 Linux 驱动工程师。关注我,一起变得更加优秀吧!
哈喽,我是老吴。
【资料图】
最近产品上有用到一个叫supervisord的开源软件。
https://github.com/ochinchina/supervisord
supervisord是一个进程管理软件,golang写的,3.5Kstar。
我们的产品上有多个服务程序要在后台长期运行,所以使用 supervisord 来守护并管理这些进程。
supervisord 非常适合嵌入式 Linux 平台。
一方面,supervisord 可以帮我们在开机时后台启动多个服务程序,另一方面,当有服务异常退出时,supervisord 也能帮我们重新将服务拉起来,从而保证产品能长期正常工作。
supervisord 的代码非常值得我们阅读学习,不过今天不研究它。
我们来研究另外一个核心功能跟它类似,但是代码更加简单的开源软件:pman。
https://github.com/matsune/pman
pman 也是一个进程管理软件,不过它是 C++ 写的,代码仅 1420 行,麻雀虽小,五脏俱全,功能上也完全满足我们产品的需求。
举个例子:
$cat/etc/pman.conf[pman]pidfile=/tmp/pman.pid;pmandaemon"spidfilelogfile=/tmp/pman.log;pmandaemon"slogfileport=127.0.0.1:50010;gRPCserverportdirectory=/tmp;defaultiscurrentdir[program:ls]command=/bin/ls;programcommandstdout=/tmp/sample_stdout.log;programstdoutlogfile(default:/tmp/${programname}_stdout.log)stderr=/tmp/sample_stderr.log;programstderrlogfile(default:/tmp/${programname}_stderr.log)autorestart=true;automaticallyrestartifexitedunexpectedlyautostart=true;startprogramondaemon"sstartup
这个配置文件指定了一个需要运行的程序:ls,并且指定了它的标准输出输出,以及是否要自动重启等属性。
运行效果:
$./pmanstatus-cpman.conf[sleep]RUNNINGpid:15283uptime:00:00:04$./pmanstopsleep-cpman.conf[sleep]STOPPING$./pmanstatus-cpman.conf[sleep]STOPPING$./pmanstartsleep-cpman.conf[sleep]RUNNINGpid:15370uptime:00:00:00
pman源码一共才1420行,非常适合我们用来学习进程管理类工具的实现原理。
$wc-l*222cmd_parser.cpp45cmd_parser.hpp32conf.cpp47conf.hpp80conf_parser.cpp23conf_parser.hpp222daemon.cpp41daemon.hpp29defines.h126main.cpp56pid_file.cpp15pid_file.hpp88pman_client.cpp21pman_client.hpp188pman_service_impl.cpp39pman_service_impl.hpp35program.cpp27program.hpp21task.hpp54util.cpp9util.hpp1420total
简单过一下源码,抓主干:
intmain(){[...]if(cmdParser.command()==DAEMON){//守护模式,并启动serverreturnrunServer(confParser.pmanConf(),confParser.programConfs());}elseif(cmdParser.command()==KILL){returnkillServer(confParser.pmanConf();}else{//client模式,会去访问serverreturnrunClient(confParser.pmanConf().port(),cmdParser.command(),cmdParser.program());}}
pman 自己本身就是一个守护服务,当没有传递 status、stop、start 等参数时,pman 会以守护进程的方式运行:
intrunServer(...){//将自己编程守护进程Daemondaemon(pmanConf,programConfs);daemon.setup();//创建server线程thread(rungRPCServer,pmanConf.port(),ref(daemon)).detach();//启动配置文件中指定的所有程序returndaemon.runLoop();}
server 线程会建立一个 RPCServer,使用到了 Google 的 gRPC 组件:
https://github.com/grpc/grpc
简单来说,就是为了实现 status/stop/start 等命令以 RPC client 的方式去调用到 pman 守护进程内的函数 API,这里就不详细展开了。
接着看 runLoop()
intDaemon::runLoop(){//启动所有的用户程序for(autoprogram=this->programs_.begin();program!=this->programs_.end();++program){if(program->autostart())startProgram(*program);}//循环处理用户的命令行的操作while(!abrt_status){//取出用户指令while(!tasks_.empty()){Tasktask=tasks_.front();//Start/Stop程序}}}
上面的代码只是 pman 的主逻辑,其他很多功能,例如命令行参数的解析、配置文件的解析、程序的管理等功能,都被良好地封装起来了,所以我们看起来才会这么清晰明了。
总结
对于嵌入式Linux的产品,如果需要长期守护住应用程序的运行,可以考虑部署supervisord或者pman等进程管理工具。
建议优先考虑考虑 Go 版本 supervisord,一方面是因为 Go 应用部署非常简单,只要拷贝一个可执行文件即可,另一方面也是因为 supervisord 的用户更多、活跃度更高,功能更完善。
如果你开发的产品上没有 Go 环境,性能也有限,类似路由器 openwrt 系统,那就考虑采用 pman,对其加以定制以满足最终的需求。
最后,这两个开源工具的代码可读性都非常的好,很适合用来锻炼和提升Go/C++的编程能力,喜欢研究技术的小伙伴们,可以品读一下源码,肯定会有所收获。
标签:
我是老吴,一个爱学习的,嵌入式Linux驱动工程师。关注我,一起变得更加优秀吧!哈喽,我是老吴。最近产品
1、qūqūwānwānㄑㄩㄑㄩㄨㄢㄨㄢ2、曲曲湾湾(曲曲湾湾)3、词语释义4、(1) 形容很弯曲。《霓裳续谱·杂曲·情
NBA季后赛,尼克斯主场101-108不敌热火。赛后,布伦森接受了采访。谈到自己的表现时,布伦森表示:“今天我
狄龙:不后悔跟詹姆斯喷垃圾话我们只是被一支更好的球队击败了,狄龙,湖人,垃圾话,脚伤势,美国篮球,勒布朗詹
苏尼特右旗气象台2023年05月01日06时47分发布大风蓝色预警信号:24小时内苏尼特右旗将受大风影响,平均风力