我希望systemd管理tup监视器,所以我写了一个服务单元:
[Unit]
Description=Monitor source files for changes
[Service]
Type=simple
ExecStart=/usr/bin/tup monitor -f
ExecStop=/usr/bin/tup stop
WorkingDirectory=/some/dir
StandardOutput=journal+console
StandardError=journal+console
[Install]
WantedBy=multi-user.target
虽然手动启动监视器,但尝试使用systemd失败时会出现以下错误:
setpgid: Operation not permitted
tup error: Unable to set process group for tup's subprocesses.
错误源于this file,似乎是由于systemd没有为进程提供所需的功能,所以我更进一步:
[Unit]
Description=Monitor source files for changes
[Service]
Type=simple
ExecStart=/usr/bin/tup monitor -f
ExecStop=/usr/bin/tup stop
CapabilityBoundingSet=CAP_SETUID CAP_SETGID
AmbientCapabilities=CAP_SETUID CAP_SETGID
WorkingDirectory=/some/dir
StandardOutput=journal+console
StandardError=journal+console
[Install]
WantedBy=multi-user.target
尽管如此,它还不起作用。
如何告诉systemd保留tup所需的权限?
答案 0 :(得分:1)
systemd默认情况下不限制对服务的任何权限,因此我认为这不是问题。 setpgid(2)
联机帮助页中提到了EPERM
的三个可能条件,
试图将进程移至另一个会话中的进程组,或更改调用进程的子进程之一的进程组ID,并且该子进程位于另一个会话中,或更改进程会话主持人的组ID(
setpgid()
,setpgrp()
)。
我认为第三个是最可能导致错误的原因:tup
可能期望从shell运行,在这种情况下,shell将是会话领导者,并且tup
试图建立自己的进程组,但是systemd将每个服务放置在自己的会话中,这是为该服务设置干净执行环境的一部分(另请参见daemon(7)
),因此该步骤将失败。
除非您可以通过某种方式禁用tup
中的该步骤(也不必fork
,或者执行systemd不必要的其他操作),否则我认为唯一的解决方法是成为丑陋的骇客:
ExecStart=/bin/sh -c '/usr/bin/tup monitor -f'
有了这个,会话领导者将成为外壳程序,而不是tup
,因此setpgid
应该可以再次工作。
答案 1 :(得分:0)
试试这个
[Unit]
Description=Monitor source files for changes
After=network.target
[Service]
Type=simple
ExecStart=/usr/bin/tup monitor -f
ExecStop=/usr/bin/tup stop
CapabilityBoundingSet=CAP_SETUID CAP_SETGID
AmbientCapabilities=CAP_SETUID CAP_SETGID
WorkingDirectory=/some/dir
StandardOutput=journal+console
StandardError=journal+console
[Install]
WantedBy=multi-user.target
我已添加After=network.target
,这将确保在网络完全活动后启动TUP服务,并避免因网络问题导致服务失败