热门标签 | HotTags
当前位置:  开发笔记 > 编程语言 > 正文

守护进程二三事与Supervisor

守护的梦想有时候我们在运行服务端系统的时候会遇到这样的问题,希望一个进程能常驻,而不是随着会话的结束而结束,常见如Mysql、Apache等web服务都有类似的需求。这种不会随着会话

守护的梦想

有时候我们在运行服务端系统的时候会遇到这样的问题,希望一个进程能常驻,而不是随着会话的结束而结束,常见如Mysql、Apache等web服务都有类似的需求。

这种不会随着会话退出而自己结束的进程,可以叫做守护进程(Daemon),而像Mysql、Apache这类程序,已经很贴心的提供了守护进程的配置,甚至是默认就是已守护进程的形式工作的。

其实守护进程还有更严谨的定义,这里就不展开了

但有时候我们如果需要运行一个自己的程序,或者某个不支持守护进程的程序时,就需要做些额外的动作让这个进程不会随着会话退出而退出

所以经常看到类似mysqld、httpd啥的,这里的d就是Daemon的意思

贴心点的如swoole server,在配置中补上一个daemon配置即可,麻烦点如beego的server,可以用类似这样的命令:

nohup path/XXX &

严格来说,这样启动的并不是守护进程,不过从结果来说,也可以说它已经是“守护进程”了

总所周知,linux系统中有一个很重要的信号机制,进程可以通过一系列信号进行通讯,例如说,经常为了关闭一个进程使用的

kill -TERM <#pid#>

而用户结束当前会话的时候,会向当前会话的子进程发送一个HUP信号,一般情况下,当前会话的子进程收到HUP信号以后就会退出自己。

也就是说对于交互进程,kill -hup <#pid#>也可以起到退出进程的作用。

看到这里,相信nohup的意思就很明确了,“No HUP”,使用了这个命令以后,启动的进程将忽略HUP信号;

nohup之后还可以配合其他命令重定向输出等,这里就不展开啦

也就是说,因为忽略了HUP的信号,当前会话结束以后,该进程不会自动退出,而是被系统主进程收养(pid = 1),也就产生了形如守护进程的效果。

而&表示将当前进程放入后台执行。

利用nohup命令,我们可以很方便的根据自己的需要启动守护进程,以达到我们的目的,例如对外提供web服务。

简单粗暴好用,再好不过了


如果说nohup命令是用户在使用时根据自己需要实现的守护进程,有些时候作为工具的制造者的攻城狮也可以让程序运行时自动蜕变成守护进程的方法

适度的封装是为了降低使用者的门槛

比较传统的守护进程程序实现思路如下:

  1. 创建子进程,父进程退出
  2. 在子进程中创建新会话

beego的graceful实现就是fork出子进程以后,子进程反手就把把父进程关闭了 ———— 总觉得是一出麦克白…

由于父进程是由会话终端启动的,此时父进程就隶属于会话进程,如果此时会话退出,父进程也会由于收到hup信号而退出

其实父进程只是个壳,子进程才是真正处理业务的进程,有点像鲧和禹的传说

但如果父进程主动退出以后,子进程就变成了孤儿进程,而善良的Linux系统进程(pid = 1)就会收养孤儿进程,这个时候子进程就已经从组织上脱离会话进程了

独立成人总是长大的一部分,但童年的经历也是人生的一部分

子进程仍然会继承父进程与会话有关的会话期的信息,此时需要让子进程自己创立自己的会话,并担任会话组的组长

就像成人仪式一样,宣布正式脱离原会话的控制、原进程组的控制、原控制终端的控制

具体实现上,不同的语言有不同的写法,所以这里只简单介绍一下原理咯~

一般来说就是fork和 … 你猜?


守护 ~ 守护进程 ~ 进程

守护进程虽然不会因为会话的退出而退出,却有可能因为各式各样的原因出现异常而崩溃。

一些web服务往往要求有比较高的可用性,服务进程崩溃以后,用户往往看到的就是404了

但大多时候都是稳定的服务,偶发性的崩溃却很难及时的通知到管理员

毕竟很多程序不是自己写的,要在程序内部做点监听啥的还真不容易(也没必要)

而且很多时候,只要重启一下服务即可,如果有一个方法可以监视着服务进程,如果发生了异常的退出则自动重启服务进程,就好了

例如丶运维攻城宅可以7*24小时每隔2秒刷新一下网页,看看有没有404 …

显然这种工具是有的,Supervisor就是其中一个。

Supervisor

Supervisor是一个用Python写的进程管控工具,简单地说,它主要解决了两个问题:

  1. 管:进程的启动和守护进程化。
  2. 控:监控进程是否异常退出,根据需要重启进程。

当然,Supervisor还可以做得更多…

关于Supervisor的安装说明网上很多,这里就不一一细说了,我们还是来聊聊Supervisor可以怎么管及怎么控你需要的进程。

进程配置文件简析

一个简单的Supervisor进程配置文件可能是这样的:

[program:nginx]
command=/usr/sbin/nginx ;the program (relative uses PATH, can take args)

没错,就这么简单,你只需要把启动进程的命令写进去就可以了,剩下的事情,Supervisor会自动帮你搞定。

Sometimes, simple is the best

这个配置文件中有两个关键属性,第一个是第一行中的“nginx”,这个参数表明了对于Supervisor来说,这个进程应该怎么称呼

毕竟每次运行的时候,进程号都是新分配的,用进程号显然极不方便

第二个属性显然是command,这里就跟你在shell中调用一样,把你想启动的程序的命令写进去吧,可以带参数,也可以不带。

同样,更多的配置略

Supervisord和Supervisorctl

安装完Supervisor以后,系统中一般会找到两个工具(程序),一个是supervisord,另一个是supervisorctl,前者是主要的工作程序,后者则是一个管理工具,两者的关系类似apache和apachectl

事实上,ctl的基本工作就是把人比较好理解的命令转译给正在工作的d,就像高级语言,最终会被转成cpu指令执行一样

首先使用superviaord启动supervisor的主进程,然后通过supervisorctl向主进程发送一系列命令,让它听你的命令工作。

木有错,这里的d就是前文说的Daemon的意思

首先,supervisord启动后,其自身就会蜕变成一个守护进程,然后,它会根据用户的配置文件,根据用户启动配置启动用户需要的进程,而用户配置的进程就变成了supervisord的子进程

这里可不需要nohup ~

如果子进程发生了什么意外导致退出,supervisord进程会收到子进程挂掉的消息,然后重新启动子进程

默认情况下,supervisor的意外表示进程的 exit_code != 0 || exit_code != 2

这样就是守护-守护进程-的进程,由supervisor替管理员管理服务进程的生命周期

常用的命令如supervisorctl start|reload|stop|update这里就不细说咯

意外,总是如期而至

事实上,用supervisor启动守护进程,某种程度上有点像nohup的方法,把自身非守护进程的进程当作守护进程再运行,所以如果某个程序本身就是默认以守护进程的方式运行的,就会出问题

还记得前文中介绍的自身守护进程化的方式么?

我们假设用supervisor启动了默认的nginx服务,刚启动的一瞬间,进程的结构可以简单看作是这样的:

systemd pid = 1
    \- supervisord pid = 1234
        \= nginx pid = 5678

但nginx默认是自身守护进程化的,也就是说,这个时候pid=5678的进程是父进程,此时他会根据自己的逻辑fork出子进程(假设pid = 8765)用于处理业务:

systemd pid = 1
    \- supervisord pid = 1234
        \= nginx pid = 5678
            \- nginx pid = 8765

然后,父进程(pid = 5678)退出,子进程(pid = 8765)被主进程(pid = 1)收养:

systemd pid = 1
    |
    \- supervisord pid = 1234
    |
    \- nginx pid = 8765

这时,问题来了,supervisor发现自己的小弟nginx(pid=5678)退出了,真正的业务进程()pid = 8765)并不是组织(super联萌)的人,那么也就是说,nginx本意是为了脱离会话的控制而华为守护进程的行为,也导致了它无法被supervisor守护

毕竟,人是社会性动物,人设计的程序、系统、制度,或多或少都会体现这一点

那么解决的方法是什么呢?也很简单,告诉nginx不要自己蜕变成守护进程即可:

# 编辑nginx的配置文件
daemon off;

此时,nginx就不会主动的守护自身,而是把这个权利让渡给了supervisor,由supervisor守护自己

是不是有点公民权利让渡的味道(^^__^^)

除了supervisor,常用的apahce也有类似的问题,解决方式如下:

;supervisor的apache2配置中
command = PathToApache/apache2ctl -DFOREGROUND;

后记

关于守护进程,从早年在不知情的情况下用apahce、mysql,到在学习swoole的时候第一次知道守护进程的概念,从自己写的process守护,到使用supervisor,一路走来,今天写这篇稿的时候忽然有点唏嘘。

物似人非,事事休

也许成长就是学会接受变化。


推荐阅读
  • Python 伦理黑客技术:深入探讨后门攻击(第三部分)
    在《Python 伦理黑客技术:深入探讨后门攻击(第三部分)》中,作者详细分析了后门攻击中的Socket问题。由于TCP协议基于流,难以确定消息批次的结束点,这给后门攻击的实现带来了挑战。为了解决这一问题,文章提出了一系列有效的技术方案,包括使用特定的分隔符和长度前缀,以确保数据包的准确传输和解析。这些方法不仅提高了攻击的隐蔽性和可靠性,还为安全研究人员提供了宝贵的参考。 ... [详细]
  • 在 Ubuntu 中遇到 Samba 服务器故障时,尝试卸载并重新安装 Samba 发现配置文件未重新生成。本文介绍了解决该问题的方法。 ... [详细]
  • 使用Tkinter构建51Ape无损音乐爬虫UI
    本文介绍了如何使用Python的内置模块Tkinter来构建一个简单的用户界面,用于爬取51Ape网站上的无损音乐百度云链接。虽然Tkinter入门相对简单,但在实际开发过程中由于文档不足可能会带来一些不便。 ... [详细]
  • 本文详细介绍了如何在 Django 项目中使用 Admin 管理后台,包括创建超级用户、启动项目、管理数据模型和修改用户密码等步骤。 ... [详细]
  • 本文将详细介绍如何在Mac上安装Jupyter Notebook,并提供一些常见的问题解决方法。通过这些步骤,您将能够顺利地在Mac上运行Jupyter Notebook。 ... [详细]
  • 在JavaWeb开发中,文件上传是一个常见的需求。无论是通过表单还是其他方式上传文件,都必须使用POST请求。前端部分通常采用HTML表单来实现文件选择和提交功能。后端则利用Apache Commons FileUpload库来处理上传的文件,该库提供了强大的文件解析和存储能力,能够高效地处理各种文件类型。此外,为了提高系统的安全性和稳定性,还需要对上传文件的大小、格式等进行严格的校验和限制。 ... [详细]
  • 如何在Linux服务器上配置MySQL和Tomcat的开机自动启动
    在Linux服务器上部署Web项目时,通常需要确保MySQL和Tomcat服务能够随系统启动而自动运行。本文将详细介绍如何在Linux环境中配置MySQL和Tomcat的开机自启动,以确保服务的稳定性和可靠性。通过合理的配置,可以有效避免因服务未启动而导致的项目故障。 ... [详细]
  • Python错误重试让多少开发者头疼?高效解决方案出炉
    ### 优化后的摘要在处理 Python 开发中的错误重试问题时,许多开发者常常感到困扰。为了应对这一挑战,`tenacity` 库提供了一种高效的解决方案。首先,通过 `pip install tenacity` 安装该库。使用时,可以通过简单的规则配置重试策略。例如,可以设置多个重试条件,使用 `|`(或)和 `&`(与)操作符组合不同的参数,从而实现灵活的错误重试机制。此外,`tenacity` 还支持自定义等待时间、重试次数和异常处理,为开发者提供了强大的工具来提高代码的健壮性和可靠性。 ... [详细]
  • 为了确保iOS应用能够安全地访问网站数据,本文介绍了如何在Nginx服务器上轻松配置CertBot以实现SSL证书的自动化管理。通过这一过程,可以确保应用始终使用HTTPS协议,从而提升数据传输的安全性和可靠性。文章详细阐述了配置步骤和常见问题的解决方法,帮助读者快速上手并成功部署SSL证书。 ... [详细]
  • MATLAB字典学习工具箱SPAMS:稀疏与字典学习的详细介绍、配置及应用实例
    SPAMS(Sparse Modeling Software)是一个强大的开源优化工具箱,专为解决多种稀疏估计问题而设计。该工具箱基于MATLAB,提供了丰富的算法和函数,适用于字典学习、信号处理和机器学习等领域。本文将详细介绍SPAMS的配置方法、核心功能及其在实际应用中的典型案例,帮助用户更好地理解和使用这一工具箱。 ... [详细]
  • Nginx作为前端服务器时,Tomcat与Apache作为后端,War包应部署在何处? ... [详细]
  • PHP自学必备:从零开始的准备工作与工具选择 ... [详细]
  • 在 Kubernetes 中,Pod 的调度通常由集群的自动调度策略决定,这些策略主要关注资源充足性和负载均衡。然而,在某些场景下,用户可能需要更精细地控制 Pod 的调度行为,例如将特定的服务(如 GitLab)部署到特定节点上,以提高性能或满足特定需求。本文深入解析了 Kubernetes 的亲和性调度机制,并探讨了多种优化策略,帮助用户实现更高效、更灵活的资源管理。 ... [详细]
  • FastDFS Nginx 扩展模块的源代码解析与技术剖析
    FastDFS Nginx 扩展模块的源代码解析与技术剖析 ... [详细]
  • 在项目开发过程中,掌握一些关键的Linux命令至关重要。例如,使用 `Ctrl+C` 可以立即终止当前正在执行的命令;通过 `ps -ef | grep ias` 可以查看特定服务的进程信息,包括进程ID(PID)和JVM参数(如内存分配和远程连接端口);而 `netstat -apn | more` 则用于显示网络连接状态,帮助开发者监控和调试网络服务。这些命令不仅提高了开发效率,还能有效解决运行时的各种问题。 ... [详细]
author-avatar
mobiledu2502859223
这个家伙很懒,什么也没留下!
PHP1.CN | 中国最专业的PHP中文社区 | DevBox开发工具箱 | json解析格式化 |PHP资讯 | PHP教程 | 数据库技术 | 服务器技术 | 前端开发技术 | PHP框架 | 开发工具 | 在线工具
Copyright © 1998 - 2020 PHP1.CN. All Rights Reserved | 京公网安备 11010802041100号 | 京ICP备19059560号-4 | PHP1.CN 第一PHP社区 版权所有