本文来自依云's Blog,转载请注明。
这几天闲下来的时间多了,于是趁机折腾 systemd,也读了不少 systemd 的文档。
当 Arch 官方宣布 sysvinit 不再被支持的时候,我是有些不喜欢的,因为我还没来得及弄明白 systemd 这完全不同的一套东西。现在看了不少 systemd 的文档,反倒是喜欢上 systemd 了 :-)
关于 systemd,我有两个没想到。其一,systemd 是兼容 sysvinit 服务的,一如 upstart。只是 Arch 一向比较激进,所以根本没用到这兼容性。其二,systemd 这个名字是个双关语,它不仅表示「system daemon」,还与「System V」遥相呼应,因为它是「System D」 :-)
本文不是教程,因此没什么意思的服务启动停止之类的就不写了。本文写点有意思的:让 systemd 监听套接字,在有连接时再启动服务。这不是什么新鲜东西,inetd 就是干这个的,但是我从来没用过,也没感觉有多大的需求。然而整理我的用户级服务时却发现这东西挺好的。
首先来最简单的,使用 sshd.socket 代替 sshd.service。
[Unit] Conflicts=sshd.service Wants=sshdgenkeys.service [Socket] ListenStream=22 Accept=yes [Install] WantedBy=sockets.target
其实用起来很简单,systemctl start sshd.socket
就启动它了。因为写了Conflicts=sshd.service
,所以已经启动的 sshd 服务会自动停止。但是,我还没告诉 systemd 要监听 2 号端口而不是 22 呢!
直接改这个sshd.socket
显然不行,下次更新修改就没了。把文件从/usr/lib/systemd/system
复制到/etc/systemd/system
下再修改?以前我是这么做的,但是其实还有更好的做法:
在/etc/systemd/system
下建立目录sshd.socket.d
,然后建立个.conf
文件写入需要的修改:
[Socket] ListenStream= ListenStream=2
这里有两个ListenStream
指示。第一个值为空,是重置该选项的值,之前的设置全部作废。systemd 单元文件中有很多选项都接受多个值,写多遍的话就是多项相加,除非写空值来重置前边设置过的值。一开始看到这种设计我还没明白为什么要这样做,后来看到对.d
目录的支持才恍然大悟。
于是乎,自己要的修改完全和系统自带的配置分离开了,既不需要手动合并上游的新配置,也不需要担心自己复制过来修改的配置文件陈旧了。
除了sshd.socket
文件外,还有一个与之配套的sshd@.service
文件,说明服务该如何启动。当然像 acpid 这种Accept=false
(默认)的套接字配置,有连接时只要启动一个进程来处理就可以了,所以对应的 .service 文件不是模板(文件名中没有@
)。
下面我自己来给 socat 写个类似的配置。这个极其简单的服务是我为在远程主机中 fcitx.vim 来控制本地 fcitx用的。
首先是.socket
文件:
[Socket] ListenStream=@fcitx-remote Accept=yes [Install] WantedBy=sockets.target
ListenStream
第一个字符是@
,表示「抽象套接字」,是 Linux 特有的一种在文件系统和网络之外的套接字,好处是不用在监听前先删除相应的套接字文件。socat 和 sshd 一样,也是一个连接对应一个进程,所以Accept=true
,让 systemd 接受连接之后把连接的套接字传过来。
然后是对应的.service
文件:
[Unit] Description=Fcitx Socket Forwarder [Service] SyslogIdentifier=fcitx-socat SyslogFacility=local0 ExecStart=/usr/bin/socat stdin tcp:10.7.0.6:8989 StandardInput=socket StandardError=syslog
StandardInput=socket
指定 socat 进程的标准输入是 systemd 接收的套接字,所以 socat 命令变成了这样子:
/usr/bin/socat stdin tcp:10.7.0.6:8989
这样子,原先跑在 tmux 里的命令
socat abstract-listen:fcitx-remote,fork tcp:10.7.0.6:8989
就变成由 systemd 监听,在需要时再启动 socat 来处理啦 =w=
关于这个 .service 文件中那两个 Syslog 开头的指令,以及这两个手写的配置要如何给 systemd 用,请看下篇:玩转 systemd 之用户级服务管理。
Feb 05, 2014 04:30:51 PM
我发现我到现在还是懒得弄明白 systemd :(