这个问题也许与我在这里问的问题有关。
这是在以下背景下https://github.com/bstarynk/helpcovid/(适用于 Linux 的 GPLv3+ 软件,目前于 2020 年 4 月发布积极的开发,这是一个专门用于 Linux 的 C++ 多线程 Web 应用程序,所以工作正在进行中2020 年 4 月 8 日)
b-star-y.tech
我正在运行 Linux/Debian/Buster 的主机上租用 VPS 。
我和别人一起发展帮助科维德,一个用 C++17 为 Linux 编码的多线程 GPLv3+ Web 应用程序软件。
我不熟悉systemd
,由该主机上的 Debian/Buster 使用,或者与docker
我想实施下面的无限循环在git clone
d 文件树中。
git pull
make
- 运行
./helpcovid -D -T2
时 stderr 和 stdout 都重定向到某个文件。 sleep 5
和无限重复。
我很想用定时任务工作,或者也许atd
与batch
有更好的方法吗systemd
?
您可以给我发电子邮件至[email protected]
答案1
大约四分之一个世纪以来,我们已经拥有允许非特权用户临时运行随机数服务的工具集。 Daniel J. Bernstein 的守护进程工具是最早的之一。一个没有有设置扫描目录和其他基础设施。人们可以在下面运行一个程序supervise
直接地。 M. Bernstein 的 UCSPI-TCP 工具集此外,它是我们在类似时间长度内使用的几个工具集的一个示例,这些工具集处理需要接受 TCP 连接并执行操作的服务。
还有其他工具集可以做同样的事情,不需要 systemd,当然使用 systemd 也可以还设置专门的每用户服务。
现在已经是 2020 年了。没有充分的理由去编写使用摇摇欲坠且危险的 PID 文件机制的新程序。不需要您编写的任何 PID 文件代码。
同样,编写一个 TCP 服务器也是一个好主意,这样它就可以继承它的监听套接字,作为一个已经打开的文件描述符。事实上就是这样全系统由 inted 运营的服务自 20 世纪 80 年代以来一直按惯例运营。它也可以通过每用户服务来完成。 s6 和 nosh 工具集,甚至还有 systemd,都提供了为服务提供侦听套接字的方法。没有必要任何您编写的随机数 URL 解析代码的一部分,与许多即兴解析器一样,它不能处理 URL 可以采用的所有形式。
不幸的是,正如我所说,您的cpp-httplib
库没有可以使用的构造函数或函数成员给定监听套接字的文件描述符。鉴于继承套接字文件描述符已经成为三十年多来的正常做法,这是该库设计中的一个重大疏忽。
某物以外系统
两个都我的小吃工具集和Laurent Bercot 的 s6 工具集提供将随机数程序作为临时每用户服务运行的方法。
在 nosh 工具集下,会有一个helpcovid
子目录,service
其下的子目录包含用于处理服务的各种程序。
helpcovid/service/start
并且helpcovid/service/stop
相当小:
#!/bin/nosh
#Start file generated from ./helpcovid.socketand ./helpcovid.service
true
#!/bin/nosh
#Stop file generated from ./helpcovid.socketand ./helpcovid.service
true
肉在helpcovid/service/run
和 中helpcovid/service/service
:
#!/bin/nosh
#Run file generated from ./helpcovid.socketand ./helpcovid.service
#Starynkevitch helpcovid listening socket
tcp-socket-listen --systemd-compatibility ::0 50002
envdir env
setenv LC_ALL fr_FR.UTF-8
chdir /home/basile/dev/helpcovid/test
./service
#!/bin/nosh
#Service file generated from ./helpcovid.service
#Starynkevitch helpcovid service
sh -c 'exec /home/basile/dev/helpcovid/work/helpcovid ${flags}'
并helpcovid/service/restart
控制重启逻辑:
#!/bin/sh
#Restart file generated from ./helpcovid.service
sleep 5
exec true # ignore script arguments
该实例将通过将其提供给每个用户的service-manager
.该工具集在套接字上进行绑定和侦听,从 envdir 读取环境变量配置,并使用协议将打开的文件描述符传递给最终程序LISTEN_FDS
,并将工作目录更改为测试webroot/
目录所在的位置。
s6 采用类似的结构,尽管工具名称不同(例如s6-tcpserver6-socketbinder
而不是tcp-socket-listen
)并且重启逻辑的处理方式不同。 s6 不需要服务管理器。就像原来的 daemontools 一样,只需运行s6-supervise
手动调用服务:
s6-监督./helpcovid/service/
我不打算讨论太多细节,因为主要的一点是,没有 systemd 并不是糟糕的守护进程设计的借口(事实上,良好的守护进程设计原则起源于更古老的非 systemd 机制),并且为侦听套接字传递打开文件描述符的机制不仅适用于 systemd,而且可以与其他系统一起使用。
系统
上述程序实际上是从systemd转换而来的插座单元和服务单位我很快就把它们拼凑在一起。他们展示了如何在 systemd 上设置每用户服务,文件位于~/.config/systemd/user/
:
# helpcovid.socket
[Unit]
Description=Starynkevitch helpcovid listening socket
[Socket]
ListenStream=50002
Accept=No
[Install]
Wanted-By=default.target
# helpcovid.service
[Unit]
Description=Starynkevitch helpcovid service
[Service]
Environment=LC_ALL=fr_FR.UTF-8
Restart=always
RestartSec=5
ExecStart=/home/basile/dev/helpcovid/work/helpcovid ${flags}
WorkingDirectory=/home/basile/dev/helpcovid/test
#This has no meaning for systemd.
EnvironmentDirectory=env
这是通过类似的来控制的systemctl --user start helpcovid.socket
。
在 systemd 的世界里,这些是配置文件。用户想要更改 TCP 端口号?用户更改ListenStream=
设置。不需要多余的额外环境变量来设置区域设置。用户只需LC_ALL
按所示方式设置实际(或其他)变量即可。
记录
日志记录也由服务管理处理。 nosh 工具集和 s6 方式是通过管道将标准输出和标准错误提供给正在运行的辅助服务cyclog
,s6-log
或者其他服务。 systemd 将日志输出填充到集中式 systemd 日志的用户部分,供您journalctl --user
阅读。
你的程序
您的程序需要登录std::clog
(即标准错误),调用setlocale()
withNULL
来读取标准环境变量,并具有处理该LISTEN_FDS
机制的代码。最后有很多选择,从 systemd 附带的不可移植的辅助函数库到其他人更可移植的类似函数库。
与所有 TCP 端口号解析代码、摇摇欲坠且危险的 PID 文件代码以及可以通过这种方式取出的代码相比,输入的代码肯定要少HELPCOVID_LOCALE
得多--locale
。 ☺
进一步阅读
- 乔纳森·德博因·波拉德 (2001)。 设计 Unix 守护程序时要避免的错误。常见答案。
- https://github.com/jdebp/nosh/blob/ddb422c9e6db11aee1c22a171bcc729edc7fe1c3/source/listen.cpp#L1
- 问题: