使用 systemd 部署 Twisted¶
简介¶
在本教程中,您将学习如何使用 systemd
启动 Twisted 服务。您还将学习如何使用 socket activation
启动服务。
注意
本教程中的示例演示了如何启动 Twisted Web 服务器,但相同的技术适用于任何 Twisted 服务。
先决条件¶
Twisted
本教程的套接字激活部分需要 Twisted 版本 >= 12.2。
本教程是在 Fedora 18 Linux 操作系统上编写的,该操作系统具有系统范围的 Twisted 和 Twisted Web 安装。
如果您在本地安装了 Twisted,例如在您的主目录或 virtualenv 中,则需要修改以下示例中的一些路径。
通过以下命令在 TCP 端口 8080 上启动
twistd web
服务器来测试您的 Twisted 安装$ twistd --nodaemon web --listen tcp:8080 --path /srv/www/www.example.com/static 2013-01-28 13:21:35+0000 [-] Log opened. 2013-01-28 13:21:35+0000 [-] twistd 12.3.0 (/usr/bin/python 2.7.3) starting up. 2013-01-28 13:21:35+0000 [-] reactor class: twisted.internet.epollreactor.EPollReactor. 2013-01-28 13:21:35+0000 [-] Site starting on 8080 2013-01-28 13:21:35+0000 [-] Starting factory <twisted.web.server.Site instance at 0x7f57eb66efc8>假设您在以下目录结构中具有以下静态网页
# tree /srv/ /srv/ └── www └── www.example.com └── static └── index.html<!doctype html> <html lang=en> <head> <meta charset=utf-8> <title>Example Site</title> </head> <body> <h1>Example Site</h1> </body> </html>现在尝试在您的 Web 浏览器中连接到 http://localhost:8080。
如果您没有看到您的网页,或者
twistd
没有启动,您应该调查并解决问题,然后再继续。
基本的 Systemd 服务配置¶
systemd
服务的基本配置文件是 服务文件。
在本教程的后面,您将了解其他类型的配置文件,这些文件用于控制服务何时以及如何启动。
但我们将从配置 systemd
开始,以便在系统启动时立即启动 Twisted Web 服务器。
创建 systemd 服务文件¶
在 /etc/systemd/system/www.example.com.service
创建 服务文件,内容如下
/etc/systemd/system/www.example.com.service
[Unit]
Description=Example Web Server
[Service]
ExecStart=/usr/bin/twistd \
--nodaemon \
--pidfile= \
web --listen tcp:8080 --path .
WorkingDirectory=/srv/www/www.example.com/static
User=nobody
Group=nobody
Restart=always
[Install]
WantedBy=multi-user.target
此配置文件包含以下值得注意的指令
ExecStart
始终包含
twistd
的完整路径,以防您安装了多个版本。
--nodaemon
标志使twistd
在前台运行。Systemd 最适合在前景中保持的子进程。
--pidfile=
标志阻止twistd
编写 pidfile。当 Twisted 作为前台进程运行时,pidfile 不是必需的。
--path
标志指定网站文件的位置。在本例中,我们使用“.”,这使得twistd
从其当前工作目录提供服务(见下文)。
WorkingDirectory
Systemd 可以配置其子进程的工作环境。
在本例中,
twistd
的工作目录设置为静态网站的工作目录。
用户/组
Systemd 还可以控制其子进程的有效用户和组。
本例使用非特权用户“nobody”和非特权组“nobody”。
这是一项重要的安全措施,它确保 Twisted 子进程无法访问文件系统的受限区域。
重启
如果子进程意外退出或崩溃,Systemd 可以自动重启子进程。
在本例中,
Restart
选项设置为always
,这确保了twistd
将在任何情况下都重新启动。
WantedBy
systemd
服务依赖关系由配置文件的[Install]
部分中的WantedBy
和RequiredBy
指令控制。在本例中,使用特殊的 multi-user.target,以便在
systemd
达到引导序列的多用户阶段时启动twistd web
服务。
还有许多其他服务指令,这些指令在systemd.directives 手册页中有所记录。
重新加载 systemd
¶
$ sudo systemctl daemon-reload
这将强制 systemd
读取新的配置文件。
更改任何 systemd
配置文件后,始终运行 systemctl daemon-reload
。
启动服务¶
$ sudo systemctl start www.example.com
twistd
现在应该正在运行并监听 TCP 端口 8080。您可以使用 systemctl status
命令验证这一点。例如
$ systemctl status www.example.com.service
www.example.com.service - Example Web Server
Loaded: loaded (/etc/systemd/system/www.example.com.service; enabled)
Active: active (running) since Mon 2013-01-28 16:16:26 GMT; 1s ago
Main PID: 10695 (twistd)
CGroup: name=systemd:/system/www.example.com.service
└─10695 /usr/bin/python /usr/bin/twistd --nodaemon --pidfile= web --listen tcp:8080 --path .
Jan 28 16:16:26 zorin.lan systemd[1]: Starting Example Web Server...
Jan 28 16:16:26 zorin.lan systemd[1]: Started Example Web Server.
Jan 28 16:16:26 zorin.lan twistd[10695]: 2013-01-28 16:16:26+0000 [-] Log opened.
Jan 28 16:16:26 zorin.lan twistd[10695]: 2013-01-28 16:16:26+0000 [-] twistd 12.1.0 (/usr/bin/python 2.7.3) starting up.
Jan 28 16:16:26 zorin.lan twistd[10695]: 2013-01-28 16:16:26+0000 [-] reactor class: twisted.internet.epollreactor.EPollReactor.
Jan 28 16:16:26 zorin.lan twistd[10695]: 2013-01-28 16:16:26+0000 [-] Site starting on 8080
Jan 28 16:16:26 zorin.lan twistd[10695]: 2013-01-28 16:16:26+0000 [-] Starting factory <twisted.web.server.Site instance at 0x159b758>
systemctl status
命令很方便,因为它同时显示了服务的当前状态和服务输出的简短日志。
这对于调试和诊断服务启动问题特别有用。
twistd
子进程将日志消息记录到 stderr
,而 systemd
将这些消息记录到 syslog。您可以通过监控 syslog 消息或使用 Fedora 中的新 journalctl
工具来验证这一点。
有关其他 systemctl
命令行选项的详细信息,请参阅systemctl 手册页。
启用服务¶
我们已经了解了如何手动启动服务,但现在我们需要“启用”它,以便它在启动时自动启动。
使用以下命令启用服务
$ sudo systemctl enable www.example.com.service
ln -s '/etc/systemd/system/www.example.com.service' '/etc/systemd/system/multi-user.target.wants/www.example.com.service'
这将在 multi-user.target.wants
目录中创建一个指向服务文件的符号链接。
Twisted Web 服务器现在将在启动时自动启动。
multi-user.target
是 “特殊” systemd 单位 的一个示例。在本教程的后面,您将学习如何使用另一个特殊单位 - sockets.target
。
测试服务是否自动重启¶
www.example.com.service
文件中的 Restart=always
选项确保 systemd
将在 twistd
进程意外退出时重启该进程。
您可以在systemd.service 手册页中阅读有关其他 Restart
选项的信息。
尝试杀死 twistd
进程,然后再次检查其状态
$ sudo kill 12543
$ systemctl status www.example.com.service
www.example.com.service - Example Web Server
Loaded: loaded (/etc/systemd/system/www.example.com.service; disabled)
Active: active (running) since Mon 2013-01-28 17:47:37 GMT; 1s ago
Main PID: 12611 (twistd)
“Active” 时间戳显示 twistd
进程在 1 秒内重启。
现在在继续下一节之前停止服务。
$ sudo systemctl stop www.example.com.service
$ systemctl status www.example.com.service
www.example.com.service - Example Web Server
Loaded: loaded (/etc/systemd/system/www.example.com.service; enabled)
Active: inactive (dead) since Mon 2013-01-28 16:51:12 GMT; 1s ago
Process: 10695 ExecStart=/usr/bin/twistd --nodaemon --pidfile= web --port 8080 --path . (code=exited, status=0/SUCCESS)
套接字激活¶
首先,您需要了解“套接字激活”是什么。以下摘录来自systemd daemon 手册页,它清楚地解释了这一点。
在基于套接字的激活方案中,创建和绑定监听套接字作为守护进程与本地(有时也包括远程)客户端的主要通信通道,这一操作从守护进程代码中移到了 init 系统中。
根据每个守护进程的配置,init 系统会安装套接字,然后在相应的守护进程即将启动时将其传递给生成的进程。
可以选择延迟服务的激活,直到第一个入站流量到达套接字,以实现守护进程的按需激活。
但是,这种方案的主要优势在于,一旦所有套接字都建立起来,所有提供者和所有消费者都可以并行启动。
除此之外,守护进程可以在重启时只丢失最少的客户端事务,甚至不丢失任何客户端请求(对于无状态协议,例如 DNS 或 syslog,尤其如此),因为套接字在重启期间保持绑定和可访问,并且所有请求都在守护进程无法处理它们时排队。
套接字激活的另一个好处是,systemd
可以监听特权端口,并以已删除的特权启动 Twisted。这允许非 root 用户配置和重启 Twisted 服务。
Twisted(从 12.2 版本开始)包含一个systemd 端点 API 和相应的字符串端口语法,它允许 Twisted 服务从 systemd
继承监听套接字。
以下示例基于前面的示例,演示了如何为简单的 Twisted Web 服务器启用套接字激活。
注意
在继续之前,使用以下命令停止前面的示例服务
$ sudo systemctl stop www.example.com.service
创建 systemd.socket 文件¶
在 /etc/systemd/system/www.example.com.socket
处创建 systemd.socket 文件,内容如下
/etc/systemd/system/www.example.com.socket
[Socket]
ListenStream=0.0.0.0:80
FileDescriptorName=my-web-port
[Install]
WantedBy=sockets.target
此配置文件包含以下重要指令
ListenStream=0.0.0.0:80
此选项配置
systemd
创建一个监听 TCP 套接字,该套接字绑定到端口 80 上的所有本地 IPv4 地址。
WantedBy=sockets.target
这是一个由所有套接字激活服务使用的特殊目标。
systemd
将在启动时自动绑定到所有此类套接字激活端口。
FileDescriptorName=my-web-port
此选项命名套接字的文件描述符。该名称允许从一组继承的描述符中可靠地选择特定的继承描述符。
您还需要修改 www.example.com.service
文件,如下所示
/etc/systemd/system/www.example.com.service
[Unit]
Description=Example Web Server
Requires=www.example.com.socket
[Service]
ExecStart=/usr/bin/twistd \
--nodaemon \
--pidfile= \
web --listen systemd:domain=INET:name=my-web-port --path .
WorkingDirectory=/srv/www/www.example.com/static
User=nobody
Group=nobody
Restart=always
请注意以下重要指令和更改
ExecStart
domain=INET
端点参数使twistd
将继承的文件描述符视为 IPv4 套接字。
name=my-web-port
端点参数使twistd
采用从名为my-web-port
的systemd
继承的文件描述符。套接字激活在技术上也可能与其他套接字族和类型一起使用,但 Twisted 目前只接受 IPv4 和 IPv6 TCP 套接字。请参阅下面的限制和已知问题。
需要
服务不再知道如何为自己绑定监听端口。必须启动相应的套接字单元,以便它可以将监听端口传递给
twistd
进程。
[Install]
在此示例中,
[Install]
部分已移至套接字配置文件。
重新加载 systemd
,以便它读取更新的配置文件。
$ sudo systemctl daemon-reload
启动并启用套接字¶
您现在可以使用以下命令启动 systemd
在套接字上监听
$ sudo systemctl start www.example.com.socket
此命令专门引用套接字配置文件,而不是服务文件。
systemd
现在应该在端口 80 上监听
$ systemctl status www.example.com.socket
www.example.com.socket
Loaded: loaded (/etc/systemd/system/www.example.com.socket; disabled)
Active: active (listening) since Tue 2013-01-29 14:53:17 GMT; 7s ago
Jan 29 14:53:17 zorin.lan systemd[1]: Listening on www.example.com.socket.
但 twistd
应该还没有启动。您可以使用 systemctl
命令验证这一点。例如
$ systemctl status www.example.com.service
www.example.com.service - Example Web Server
Loaded: loaded (/etc/systemd/system/www.example.com.service; static)
Active: inactive (dead) since Tue 2013-01-29 14:48:42 GMT; 6min ago
启用套接字,以便它在启动时与其他套接字激活服务一起自动启动。
$ sudo systemctl enable www.example.com.socket
ln -s '/etc/systemd/system/www.example.com.socket' '/etc/systemd/system/sockets.target.wants/www.example.com.socket'
激活端口以启动服务¶
现在尝试连接到http://localhost:80(在您的 Web 浏览器中)。
systemd
将接受连接并启动 twistd
,并将监听套接字传递给它。您可以使用 systemctl 报告服务的状况来验证这一点。例如
$ systemctl status www.example.com.service
www.example.com.service - Example Web Server
Loaded: loaded (/etc/systemd/system/www.example.com.service; static)
Active: active (running) since Tue 2013-01-29 15:02:20 GMT; 3s ago
Main PID: 25605 (twistd)
CGroup: name=systemd:/system/www.example.com.service
└─25605 /usr/bin/python /usr/bin/twistd --nodaemon --pidfile= web --port systemd:domain=INET:name=my-web-port --path .
Jan 29 15:02:20 zorin.lan systemd[1]: Started Example Web Server.
Jan 29 15:02:20 zorin.lan twistd[25605]: 2013-01-29 15:02:20+0000 [-] Log opened.
Jan 29 15:02:20 zorin.lan twistd[25605]: 2013-01-29 15:02:20+0000 [-] twistd 12.1.0 (/usr/bin/python 2.7.3) starting up.
Jan 29 15:02:20 zorin.lan twistd[25605]: 2013-01-29 15:02:20+0000 [-] reactor class: twisted.internet.epollreactor.EPollReactor.
Jan 29 15:02:20 zorin.lan twistd[25605]: 2013-01-29 15:02:20+0000 [-] Site starting on 80
Jan 29 15:02:20 zorin.lan twistd[25605]: 2013-01-29 15:02:20+0000 [-] Starting factory <twisted.web.server.Site instance at 0x24be758>
结论¶
在本教程中,您学习了如何使用 systemd
部署 Twisted 服务。您还了解了如何使用套接字激活按需启动服务。
限制和已知问题¶
Twisted 无法从
systemd
接受数据报套接字。Twisted 不支持监听从
systemd
继承的套接字上的 SSL 连接。