systemctl使用reload及踩坑

systemctl使用reload及踩坑1 demo service 文件 Unit Description demo demoserverDo http git demo com demoAfter network targetremote fs targetnss lookup target Service Type sampleUser rootPIDFile run demo

systemctl使用reload及踩坑

1.demo.service文件

[Unit] Description=demo - demo server Documentation=http://git.demo.com/demo After=network.target remote-fs.target nss-lookup.target [Service] Type=sample User=root PIDFile=/run/demo.pid ExecStart=/home/codes/test/src/demo/demo/demo ExecReload=/bin/kill -s HUP $MAINPID ExecStop=/bin/kill -s QUIT $MAINPID Restart=0 LimitNOFILE=65536 [Install] WantedBy=multi-user.target 

[Unit]主要是描述和规定启动前后的顺序依赖关系

[Service]主要是核心的控制语句

[Install]主要是定义服务启动相关

2.程序代码

这里使用go做一个简单的信号量的捕获,

func main() { 
    go signalHandle() // 信号量处理函数 http.ListenAndServe("localhost:8080", nil) // 用于将进程挂起,避免退出 } func signalHandle() { 
    ch := make(chan os.Signal) signal.Notify(ch, syscall.SIGHUP) sig := <-ch for { 
    fmt.Printf("Signal received: %v", sig) if sig == syscall.SIGHUP { 
    fmt.Println("syscall.SIGHUP") writeFile("syscall.SIGHUP received") return } } } func writeFile(wiriteString string) { 
    var filename = "/home/codes/test/src/demo/demo/output.txt" var f *os.File f, err := os.Create(filename) if err != nil { 
    fmt.Println(err) return } l, err := f.WriteString(wiriteString) if err != nil { 
    fmt.Println(err) f.Close() return } fmt.Println(l, "bytes written successfully") err = f.Close() if err != nil { 
    fmt.Println(err) return } } 

3.测试

情况一:

实验步骤:

[root@bogon demo]# cat output.txt  [root@bogon demo]# systemctl start demo.service  [root@bogon demo]# ps -ef|grep demo root 41159 1 0 14:30 ? 00:00:00 /home/codes/test/src/demo/demo/demo root 41168 37883 0 14:30 pts/3 00:00:00 grep --color=auto demo [root@bogon demo]# systemctl reload demo.service  [root@bogon demo]# cat output.txt  syscall.SIGHUP received[root@bogon demo]#  

systemctl start可以启动,进程存在,执行reload,进程可以捕获到SIGHUP信号量,执行了写文件操作,文件中输出syscall.SIGHUP received。

情况二:

有时候进程在启动时去读取配置文件,然后初始化log配置,及log输出路径后才会实现日志记录,在此之前或者有些没有打印日志的位置,怕程序跑飞,往往会用重定向来记录控制台日志,例如go的fmt。

service文件中ExecStart、ExecReload、ExecStop是不支持> 、>>等重定向符号的,这里可以用/bin/sh -c来实现。例如:

ExecStart=/bin/sh -c '/home/codes/test/src/demo/demo/demo >>/home/codes/test/src/demo/demo/reload.log 2>&1' 

实验步骤:

[root@bogon system]# systemctl daemon-reload  [root@bogon system]# systemctl start demo.service  [root@bogon system]# systemctl reload demo.service  Job for demo.service failed because the control process exited with error code. See "systemctl status demo.service" and "journalctl -xe" for details. [root@bogon system]# systemctl status demo.service ● demo.service - demo - demo server Loaded: loaded (/usr/lib/systemd/system/demo.service; disabled; vendor preset: disabled) Active: failed (Result: exit-code) since Thu 2019-07-11 14:42:33 CST; 1min 13s ago Docs: http://git.jd.com/database/jdcloud-rds Process: 41395 ExecStop=/bin/kill -s QUIT $MAINPID (code=exited, status=1/FAILURE) Process: 41394 ExecReload=/bin/kill -s HUP $MAINPID (code=exited, status=0/SUCCESS) Process: 41372 ExecStart=/bin/sh -c /home/codes/test/src/demo/demo/demo >>/home/codes/test/src/demo/demo/reload.log 2>&1 (code=killed, signal=HUP) Main PID: 41372 (code=killed, signal=HUP) Jul 11 14:42:33 bogon kill[41395]: -p, --pid print pids without signaling them Jul 11 14:42:33 bogon kill[41395]: -l, --list [=<signal>] list signal names, or convert one to a name Jul 11 14:42:33 bogon kill[41395]: -L, --table list signal names and numbers Jul 11 14:42:33 bogon kill[41395]: -h, --help display this help and exit Jul 11 14:42:33 bogon kill[41395]: -V, --version output version information and exit Jul 11 14:42:33 bogon kill[41395]: For more details see kill(1). Jul 11 14:42:33 bogon systemd[1]: demo.service: control process exited, code=exited status=1 Jul 11 14:42:33 bogon systemd[1]: Reload failed for demo - demo server. Jul 11 14:42:33 bogon systemd[1]: Unit demo.service entered failed state. Jul 11 14:42:33 bogon systemd[1]: demo.service failed. 

发现reload是报错的,查看status,发现ExecStop=/bin/kill -s QUIT $MAINPID (code=exited, status=1/FAILURE)失败。此时进程已经被杀掉了,执行systemctl strat将服务启动:

[root@bogon system]# ps -ef|grep demo root 41435 1 0 14:45 ? 00:00:00 /bin/sh -c /home/codes/test/src/demo/demo/demo >>/home/codes/test/src/demo/demo/reload.log 2>&1 root 41436 41435 0 14:45 ? 00:00:00 /home/codes/test/src/demo/demo/demo root 41444 37883 0 14:45 pts/3 00:00:00 grep --color=auto demo 

可以看到,这次/bin/sh -c命令循环fork出了两个子进程,41435是该进程组的首进程,负责与终端tty交互,41436才是真正的demo进程,当执行reload时,实际上执行了ExecReload=/bin/kill -s HUP M A I N P I D , 这 个 MAINPID,这个 MAINPIDMAINPID其实是41435,此时的reload信号量是发给了首进程(41435),进程如果没做信号量的捕获,默认是执行中断操作,与此同时会给子进程发送SIGTREM信号杀掉子进程,所以systemctl命令报了错误。

如果在这种情况下还想实现reload,可以换一种实现方法,就是查到demo进程的真实pid,修改如下:

ExecReload=/bin/sh -c '/bin/kill -HUP $(pidof /home/codes/test/src/demo/demo/demo)' 

通过pidof /home/codes/test/src/demo/demo/demo获取进程的pid,执行kill -HUP。

[root@bogon system]# systemctl start demo.service  [root@bogon system]# ps -ef|grep demo root 42728 1 0 15:26 ? 00:00:00 /bin/sh -c /home/codes/test/src/demo/demo/demo >/home/codes/test/src/demo/demo/reload.log 2>&1 root 42729 42728 0 15:26 ? 00:00:00 /home/codes/test/src/demo/demo/demo root 42736 37883 0 15:26 pts/3 00:00:00 grep --color=auto demo [root@bogon system]# systemctl reload demo.service  [root@bogon system]# cat /home/codes/test/src/demo/demo/reload.log  Signal received: hangupsyscall.SIGHUP 23 bytes written successfully 

这次可以看到reload没有报错,进程成功进到HUP信号量,cat reload.log 文件可以看到成功写入文件。

补充:为什么加入重定向就会循环fork出两个进程?

/bin/sh -c的原理就是fork+exec来产生一个进程,次进程是无法与tty(控制台)交互的后台进程,重定向需要与tty(控制台)交互,所以先fork出来一个重定向进程,再fork出一个真正的demo进程。

版权声明:本文内容由互联网用户自发贡献,该文观点仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请联系我们举报,一经查实,本站将立刻删除。

发布者:全栈程序员-站长,转载请注明出处:https://javaforall.net/232412.html原文链接:https://javaforall.net

(0)
上一篇 2025年10月13日 上午8:01
下一篇 2025年10月13日 上午8:22


相关推荐

  • 黑客开始利用云计算暴力激活成功教程密码

    黑客开始利用云计算暴力激活成功教程密码本文讲的是黑客开始利用云计算暴力激活成功教程密码【IT168云计算频道】使用云计算服务来替代在公司里设立维护大量服务器,显然对节省企业的成本有利。不过现在看来从云计算服务中受惠最大的恐怕是黑客等群体,黑客们开始利用亚马逊EC2等云计算服务来暴力激活成功教程并窃取用户信用卡密码。不过据安全专家DavidCampbell的计算,即便用户不使用安全专家建议的大小写字母混合…

    2022年8月22日
    8
  • Docker 网络

    Docker 网络文章目录 Docker 网络 Docker0 原理小结 link 自定义网络 Docker 网络 Docker0 清空所有环境测试三个网络问题 docker 如何处理容器网络访问 root localhost dockerrun d Pnametomcat0 查看容器内部网络地址 ipaddr 容器启动的时候会得到 eth0 if96ip 地址 docker 分配的 root localhost dockerexec ittomc

    2026年3月18日
    3
  • 一切都不是为了营销手段的目的都是耍流氓

    一切都不是为了营销手段的目的都是耍流氓

    2022年1月12日
    45
  • 大数据建模与分析挖掘相关了解「建议收藏」

    大数据建模与分析挖掘相关了解「建议收藏」一.大数据总体架构与规划二.各类数据的采集三.相关名词的了解MP:MapReduce是一种编程模型,用于大规模数据集(大于1TB)的并行运算。概念”Map(映射)“和”Reduce(归约)”,是它们的主要思想,都是从函数式编程语言里借来的,还有从矢量编程语言里借来的特性。它极大地方便了编程人员在不会分布式并行编程的情况下,将自己的程序运行在分布式系统上。当前的软件实现是指定一个Ma…

    2022年6月7日
    30
  • ntko execl操作[通俗易懂]

    ntko execl操作[通俗易懂]

    2025年5月28日
    7
  • Jenkins安装_Noam Jenkins

    Jenkins安装_Noam Jenkins前言jenkins的环境搭建方法有很多,本篇使用docker快速搭建一个jenkins环境。环境准备:mac/Linuxdockerdocker拉去jenkins镜像先下载jenkins镜

    2022年7月30日
    11

发表回复

您的邮箱地址不会被公开。 必填项已用 * 标注

关注全栈程序员社区公众号