上篇文章中,我有写如何收集日志,并对日志服务进行进程守护加固,其中有提到使用群晖作为个人日志采集服务。

但是群晖的系统是定制的,并不能够直接使用 supervisor 之类的工具来管理进程,查阅搜索引擎给出的答案,最接近的一篇是介绍如何在群晖上安装 supervisor,但是这篇文章有两个问题:

  • 一来是文章成文于2015年,不完全适用于现在的 DSM 6.x
  • 二来是并没有给出如何让 supervisor 成为随系统启动的进程,以及如何守护要启动的用户进程

文章地址,有兴趣可以围观(还是很感谢作者的付出)。

当然搜索出的答案,也有人很笨拙的使用群晖自带的计划任务来定时执行脚本,不是不可以,但是同样存在一些问题:

  • 定时任务执行的结果不能被管理或者方便查阅,如果始终以邮件方式通知的话,你是按秒来发送邮件呢,还是按分钟,邮箱垃圾邮件会不会太多
  • 定时任务无法进行重试操作,需要编写脚本来进行操作。
  • 定时任务的执行日志无法归档,前文提过日志是很重要的数据。

说了这么多,言归正传,聊聊在群晖系统上正确进行进程守护的方法。

安装进程管理工具

工欲善其事必先利其器,进程管理,我还是推荐使用 supervisor

一来可以保持和服务端的一致,二来 supervisor 的文档资料比较多,之后解决问题和继续学习都是可持续有保障的。

我们先进行python环境的安装。

还在前往 套件中心 ,选择 Python 3 进行安装,安装完毕之后,可以ssh到机器,执行命令查看是否安装正确。

which python && python --version

执行命令,我们可以看到安装就绪。

/bin/python
Python 2.7.12

群晖系统是没有开源软件包管理工具的,可以使用的软件包安装工具有两个:

  • 官方的软件安装工具
    • 需要编写软件包,忘记是否要对包进行签名了,很麻烦不推荐
  • 开源的ipkg工具
    • 官方社区有人编译了900多个常用软件,可以使用它来进行安装,很像是 osx 系统上的 homebrew,但是我们有更简单的方案,所以也不需要进行配置安装

刚刚安装了python,python其实也有自己的软件分发套件,经常使用开源软件的同学应该使用过这两个命令: easy_install, pip

没错,我们可以使用 easy_install,在群晖终端里执行(以下命令都使用root身份执行):

wget https://bootstrap.pypa.io/ez_setup.py -O - | python

当你看到下面的内容的时候,说明你已经安装完毕:

...
Processing setuptools-33.1.1-py2.7.egg
Copying setuptools-33.1.1-py2.7.egg to /usr/lib/python2.7/site-packages
Adding setuptools 33.1.1 to easy-install.pth file
Installing easy_install script to /usr/bin
Installing easy_install-2.7 script to /usr/bin

Installed /usr/lib/python2.7/site-packages/setuptools-33.1.1-py2.7.egg
Processing dependencies for setuptools==33.1.1
Finished processing dependencies for setuptools==33.1.1

接下来使用 easy_install 安装 supervisor

easy_install supervisor

如果顺利的话,你将会看到下面的内容:

Installed /usr/lib/python2.7/site-packages/meld3-1.0.2-py2.7.egg
Finished processing dependencies for supervisor

配置群晖上的进行管理工具

软件安装完毕,先不用着急启动,因为:

  1. 你还没有创建进程管理工具需要的配置。
  2. 一会还得重载配置,不如先写好了,一发入魂,节能环保(笑)。

执行配置生成命令,获得一个默认配置。

echo_supervisord_conf > /etc/supervisord.conf

使用vi编辑 /etc/supervisord.conf 文件,在文件末添加以下内容:

(你也可以取消配置文件中include指令的注释,把配置切割到子文件中,我这里需要守护的进程不多,就先写默认配置中了)

[program:syslog-frp]
command=/volume1/docker/frp/frpc -c  /volume1/docker/frp/frpc.ini
user=admin
autostart=true
startsecs=3
startretries=100
autorestart=true
stderr_logfile=/volume1/docker/frp/error.log
stderr_logfile_maxbytes=50MB
stderr_logfile_backups=10
stdout_logfile=/volume1/docker/frp/access.log
stdout_logfile_maxbytes=50MB
stdout_logfile_backups=10

上面的配置将会合理的对frp客户端进行进程管理:随机启动、有限次数的失败重试、日志记录。

更多配置信息,可以参阅官方文档

好了,配置编写完毕,启动进程就可以了。

supervisord

顺利的话,你将会看到下面的提示。

/usr/lib/python2.7/site-packages/supervisor-3.3.4-py2.7.egg/supervisor/options.py:461: UserWarning: Supervisord is running as root and it is searching for its configuration file in default locations (including its current working directory); you probably want to specify a "-c" argument specifying an absolute path to a configuration file for improved security.
  'Supervisord is running as root and it is searching '

通过 ps 命令进行进程检查,发现我们要被管理的软件被如期的运行起来了。

root@Lemon:/etc# ps -ef | grep frp
admin    13159 13155  0 19:33 ?        00:00:00 /volume1/docker/frp/frpc -c /volume1/docker/frp/frpc.ini

为了证明它是有守护能力的,我们把这个软件进行关闭,看它是否还能被顺利启动:

root@Lemon:/etc# kill 13159
root@Lemon:/etc# ps -ef | grep frp
admin    13197 13155  0 19:33 ?        00:00:00 /volume1/docker/frp/frpc -c /volume1/docker/frp/frpc.ini

看起来都一切就绪,那么我们进行更彻底的破坏行为,系统重启,看看重启后的系统环境是否还会运行我们的程序:

root@Lemon:/etc# reboot 

Broadcast message from soulteary@Lemon
	(/dev/pts/6) at 19:34 ...

The system is going down for reboot NOW!

重启之后,再次使用 ps 命令进行进程检查,发现一无所获,难道这个群晖上使用 supervisor 进行进程管理要凉凉,还是说要使用文章开头使用的很笨的定时任务的模式来执行它么?

显然不是,我们继续聊。

将软件注册为系统开机启动进程

Linux系统中,我们知道 /etc/init 下存放了我们开机要执行的程序或者脚本。

群晖也是一样,但是别太着急往 /etc/init 目录编写脚本,为什么呢?

执行 ls 命令,发现整个文件是被link过来的,我们需要在原始目录中进行脚本编写:

soulteary@Lemon:/$ ll /etc/init
lrwxrwxrwx 1 root root 15 May 23 17:47 /etc/init -> /usr/share/init

第二,里面的脚本是被群晖的执行器进行解析的特殊脚本,并非标准的 Bash Shell 脚本,所幸官方提供了大量example,通过围观,不难模仿写出一个启动脚本,为了方便大家,我直接提供出群晖系统默认开机启动supervisord的脚本:

author "SOULTEARY"
description	"start supervisord"

start on stopped hostname

oom score -999

respawn
respawn limit 5 10

console log

script

    if [ ! -f /tmp/supervisord.pid ]; then
        exec /bin/supervisord
    fi

    echo "Starting supervisord"
    
end script

将上面的内容保存为 supervisor.conf ,存放到 /usr/share/init中,再次重启系统,观察一下我们是否能够如愿以偿。

soulteary@Lemon:/$ ps -ef | grep -E 'supervisord|frpc'
root      7848     1  0 19:56 ?        00:00:01 /bin/python /bin/supervisord
admin     8925  7848  0 19:56 ?        00:00:01 /volume1/docker/frp/frpc -c /volume1/docker/frp/frpc.ini

一切顺利。

最后

先写到这里,该去打王者上分了,之前文章中提到的内容,不定期继续更新。

如果你对本篇文章的内容有疑问或者想讨论,欢迎联系我,我的联系方式聪明的你应该找的到吧?

–EOF