CentOS7安装daemontools与supervise的使用总结
一. 工具介绍
daemontools 工具官网介绍 http://cr.yp.to/daemontools.html。
daemontools 工具需要root权限,所以直接切换到root用户进行安装。daemontools是svscanboot,svscan,supervise,svc,svok,svstat等一系列工具的合集。其中,supervise 是其中的核心工具。
二. 工具安装
- 下载解压
sudo su -
mkdir -p /opt/package
chmod 1755 /opt/package
cd /opt/package
wget http://cr.yp.to/daemontools/daemontools-0.76.tar.gz
tar -zxf daemontools-0.76.tar.gz
cd admin/daemontools-0.76/
- 还不能直接编译,需要修改代码文件
vim src/conf-cc
# 在gcc 一行末尾增加
-include /usr/include/errno.h
# 更改后
gcc -O2 -Wimplicit -Wunused -Wcomment -Wchar-subscripts -Wuninitialized -Wshadow -Wcast-qual -Wcast-align -Wwrite-strings -include /usr/include/errno.h
- 编译安装
cd /opt/package/admin/daemontools-0.76/
./package/install
...
Copying commands into ./command...
Creating symlink daemontools -> daemontools-0.76...
Making command links in /command...
Making compatibility links in /usr/local/bin...
Creating /service...
Adding svscanboot to inittab...
init should start svscan now.
# 安装完成之后,会创建 /service和 /command两个目录
[root@node1 daemontools-0.76]# ll /service/
total 0
[root@node1 daemontools-0.76]#
[root@node1 daemontools-0.76]#
[root@node1 daemontools-0.76]# ll /command
total 0
lrwxrwxrwx 1 root root 45 May 20 12:11 envdir -> /opt/package/admin/daemontools/command/envdir
lrwxrwxrwx 1 root root 48 May 20 12:11 envuidgid -> /opt/package/admin/daemontools/command/envuidgid
lrwxrwxrwx 1 root root 45 May 20 12:11 fghack -> /opt/package/admin/daemontools/command/fghack
lrwxrwxrwx 1 root root 47 May 20 12:11 multilog -> /opt/package/admin/daemontools/command/multilog
lrwxrwxrwx 1 root root 47 May 20 12:11 pgrphack -> /opt/package/admin/daemontools/command/pgrphack
lrwxrwxrwx 1 root root 52 May 20 12:11 readproctitle -> /opt/package/admin/daemontools/command/readproctitle
lrwxrwxrwx 1 root root 46 May 20 12:11 setlock -> /opt/package/admin/daemontools/command/setlock
lrwxrwxrwx 1 root root 48 May 20 12:11 setuidgid -> /opt/package/admin/daemontools/command/setuidgid
lrwxrwxrwx 1 root root 48 May 20 12:11 softlimit -> /opt/package/admin/daemontools/command/softlimit
lrwxrwxrwx 1 root root 48 May 20 12:11 supervise -> /opt/package/admin/daemontools/command/supervise
lrwxrwxrwx 1 root root 42 May 20 12:11 svc -> /opt/package/admin/daemontools/command/svc
lrwxrwxrwx 1 root root 43 May 20 12:11 svok -> /opt/package/admin/daemontools/command/svok
lrwxrwxrwx 1 root root 45 May 20 12:11 svscan -> /opt/package/admin/daemontools/command/svscan
lrwxrwxrwx 1 root root 49 May 20 12:11 svscanboot -> /opt/package/admin/daemontools/command/svscanboot
lrwxrwxrwx 1 root root 45 May 20 12:11 svstat -> /opt/package/admin/daemontools/command/svstat
lrwxrwxrwx 1 root root 45 May 20 12:11 tai64n -> /opt/package/admin/daemontools/command/tai64n
lrwxrwxrwx 1 root root 50 May 20 12:11 tai64nlocal -> /opt/package/admin/daemontools/command/tai64nlocal
# 查看是否加入自启动,在最后一行会看到启动svscanboot的配置
cat /etc/inittab
SV:123456:respawn:/command/svscanboot
- 启动 svscanboot, svscanboot是自动加入了自启动脚本了的,所以只需要手动启动一次即可。svscanboot会随系统启动而启动,svscanboot 会启动 svscan 监视 /service 目录,svscan 则为 /service 的每个进程都启动一个 supervise 服务(也就是后面提到的的
supervise testprogram
)。
/command/svscanboot &
ps aux | grep svs
root 93653 0.0 0.0 113184 1420 pts/1 S 12:28 0:00 /bin/sh /command/svscanboot
root 93655 0.0 0.0 4396 468 pts/1 S 12:28 0:00 svscan /service
三. 使用示例
下面使用普通用户 yzy 启动服务,需要提前设置 yzy 用户 sudo 免密。
- 1、创建主程序目录
/home/yzy/testprogram
,编写主程序/home/yzy/testprogram/testprogram.py
,内容如下
import time
while True:
print("running..",time.time())
time.sleep(10)
- 2、创建启动脚本,并给出执行权限
vim /home/yzy/testprogram/run
,chmod +x /home/yzy/testprogram/run
,脚本内容如下
#!/bin/bash
cd /home/yzy/testprogram/
exec python -u testprogram.py >> /tmp/logs 2>&1
- 3、启动程序。也就是创建一个软连接,这样启动的程序是以root权限启动的。
sudo ln -s /home/yzy/testprogram /service
ps aux | grep testprogram
root 3323 0.0 0.0 4224 436 ? S 17:10 0:00 supervise testprogram
root 4038 0.0 0.0 23972 4632 ? S 17:54 0:00 python -u testprogram.py
yzy 4050 0.0 0.0 112712 968 pts/0 R+ 17:54 0:00 grep --color=auto testprogram
- 4、确保普通用户也能使用svc svstat等命令,切换到root用户修改 sudoers 配置
sudo su -
visudo
# 确保 /usr/local/bin 在里面
Defaults secure_path = /sbin:/bin:/usr/sbin:/usr/bin:/usr/local/bin
四. 常用命令
由于这个服务是root用户启动的,所以需要使用 sudo 或者切换到 root 才能执行相关命令。如果 cd
到程序目录/home/yzy/testprogram
,那么 /service/testprogram
可以替换成 .
也就说不用写绝对路径。
sudo svc -u /service/testprogram # 启动服务
sudo svc -d /service/testprogram # 停止服务
sudo svc -o /service/testprogram # 只启动一次服务
sudo svc -k /service/testprogram # 杀掉服务,杀掉后会立即被启动
svstat /service/testprogram # 查看服务状态
五. 普通用户权限启动服务
前面我们创建服务(创建软连接)的时候使用了sudo,也就是root权限启动服务的,有些服务时不允许root服务启动的,所以来看看怎么使用普通用户权限启动服务。
只需要在 exec
后面加上 /usr/local/bin/setuidgid yzy
即可指定用户启动程序了。下面是指定 yzy
用户启动程序的示例
#!/bin/bash
cd /home/yzy/testprogram/
exec /usr/local/bin/setuidgid yzy python -u testprogram.py >> /tmp/logs 2>&1
六. 启动前、停止后分别执行脚本
有时为了监控命令的执行是否停止,是否启动,想在启动脚本的前后分别发送消息。如果只是简单的在 exec 这一行的前面、后面分别加入执行脚本,你会发现后面的脚步不能执行了。如果你去掉exec,你会发现正常了,但是使用 svc -d
不能停止服务了。
原因是 exec
命令会让新的命令替换掉当前的shell脚本,所以一旦执行了 exec ,后面的内容就不会执行了,详情见exec的详细用法:https://yuchaoshui.com/731c133/
- 错误示例 run 脚本:后面的脚本不会执行
#!/bin/bash
cd /home/yzy/testprogram/
./send_ding.py starting_program
exec /usr/local/bin/setuidgid yzy python -u testprogram.py >> /tmp/logs 2>&1
./send_ding.py stopping_program
- 正确示例 run 脚本:下面是部署 rembg 服务的示例,由于运行 rembg 会启动新的shell,即新的 pid,supervise 监控的是 run 脚本的 pid ,所以当 run 被通知退出时,要手动把 rembg 的 pid 杀掉。
#!/bin/bash
cd /opt/rembg
./venv/bin/python ding_alarm.py starting_rembg
./venv/bin/rembg s -t 5 -p 5000 >>./logs/logs_`date '+%Y%m%d%H'` 2>&1 &
REMBG_PID=$!
trap "./venv/bin/python ding_alarm.py rembg_stopped; kill $REMBG_PID" EXIT
wait $REMBG_PID
七. 日志切换
前面的示例中,如果不重启程序,日志永远都打印在一个文件中,daemontools提供了 multilog
来自动切换日志。看下面示例:
#!/bin/bash
cd /home/yzy/testprogram/
exec python -u testprogram.py 2>&1 | multilog t n10 s1000 ./logs
上面 的示例中:
- 程序 testprogram.py 的所有输出(标准错误、标准输出)都输入到 multilog,有multilog来统一处理日志
- t 表示在每一行日志前面加上时间戳,比如@4000000065b24d5605e27a34,转换为可读时间字符串方法:
echo @4000000065b24cdf0fd440f4.s | tai64nlocal
- n10 表示保留最新的10个日志文件
- s1000 表示每个日志文件最大存放1000字节
- ./logs 用于存放日志文件,不能自定义文件名的前缀,文件名以时间戳命名
ll logs/
total 40
-rwxr--r-- 1 root root 2114 Jan 25 19:56 @4000000065b24c60321138fc.s
-rwxr--r-- 1 root root 2122 Jan 25 19:56 @4000000065b24c7234d4c9b4.s
-rwxr--r-- 1 root root 2121 Jan 25 19:56 @4000000065b24c8437843244.s
-rwxr--r-- 1 root root 2118 Jan 25 19:57 @4000000065b24c963a9c2c5c.s
-rwxr--r-- 1 root root 2117 Jan 25 19:57 @4000000065b24ca903aa8f7c.s
-rwxr--r-- 1 root root 2119 Jan 25 19:57 @4000000065b24cbb084f53b4.s
-rwxr--r-- 1 root root 2120 Jan 25 19:57 @4000000065b24ccd0b760b3c.s
-rwxr--r-- 1 root root 2118 Jan 25 19:58 @4000000065b24cdf0fd440f4.s
-rwxr--r-- 1 root root 2121 Jan 25 19:58 @4000000065b24cf11456331c.s
-rw-r--r-- 1 root root 1768 Jan 25 19:58 current
-rw------- 1 root root 0 Jan 25 18:44 lock
-rw-r--r-- 1 root root 0 Jan 25 18:44 state
# 时间戳转换为可读时间戳方法
echo @4000000065b24cdf0fd440f4.s | tai64nlocal
2024-01-25 19:58:13.265568500.s
注意:这样写有一个缺点,由于使用了管道,启动程序的pid不在是原本的主程序,所以此时 svc -d 来停止程序是不行的。