【问题标题】:how to start svnserve with systemctl systemd如何使用 systemctl systemd 启动 svnserve
【发布时间】:2016-11-06 22:53:36
【问题描述】:

debian jessie 中的 subversion 包不包含 systemd 服务文件。什么是最简单的自动启动解决方案。我试试

[Unit]
Description=Subversion protocol daemon
After=syslog.target network.target

[Service]
Type=forking
#EnvironmentFile=/etc/conf.d/svnserve
#ExecStart=/usr/bin/svnserve --daemon $SVNSERVE_ARGS
ExecStart=/usr/bin/svnserve -d -r /svnFolder/repositories
ExecReload=/bin/kill -HUP $MAINPID
KillMode=process
Restart=on-failure

[Install]
WantedBy=multi-user.target
Alias=svnserve.service

它是https://bbs.archlinux.org/viewtopic.php?id=190127 的改编版,但我已将 svnserve 的参数直接放在这里。

有什么可以改进的?

【问题讨论】:

  • 我投票决定将此问题作为离题结束,因为它与 SO 无关,因为它与编程没有直接关系。 Unix 和 Linux StackExchange 站点会更合适。
  • systemd 文件在所有基于 systemd 的发行版之间基本相同。您是否从 Arch Linux、Fedora 或 Ubuntu 中查看了相同的文件以获得灵感?
  • 您当前的解决方案有什么问题?它不工作?它会产生什么错误?

标签: svn systemd


【解决方案1】:

这里建议设置svnserve 服务“the-Debian-way” 使用专用的svn 服务帐户运行,并具有正确的日志记录。根据FHS,仓库应该存放在/srv/

mkdir -p /srv/svn/repos; chown svn /srv/svn/repos

一、systemd/etc/systemd/system/svnserve.service的服务配置:

[Unit]
Description=Subversion protocol daemon
After=syslog.target network.target

[Service]
Type=forking
RuntimeDirectory=svnserve
PIDFile=/run/svnserve/svnserve.pid
EnvironmentFile=/etc/default/svnserve
ExecStart=/usr/bin/svnserve $DAEMON_ARGS
User=svn
Group=svn
KillMode=control-group
Restart=on-failure

[Install]
WantedBy=multi-user.target

二、/etc/default/svnserve处的服务启动选项:

# svnserve options
DAEMON_ARGS="--daemon --pid-file /run/svnserve/svnserve.pid --root /srv/svn/repos --log-file /var/log/svnserve/svnserve.log"

要正常工作,日志文件的文件夹也必须以正确的所有权和 pid 文件的运行位置创建:

mkdir /var/log/svnserve; chown svn /var/log/svnserve
mkdir -p /run/svnserve; chown svn /run/svnserve

以日志轮换配置结束/etc/logrotate.d/svnserve

/var/log/svnserve/*.log {
    daily
    missingok
    rotate 14
    compress
    notifempty
    create 640 svn adm
    sharedscripts
    postrotate
            if /bin/systemctl status svnserve > /dev/null ; then \
                /bin/systemctl restart svnserve > /dev/null; \
            fi;
    endscript
}

希望这会有所帮助。

【讨论】:

  • @Yves Martin 感谢您提供此解决方案。我最近使用了这个解决方案的一个变体,并且有几个 cmets。首先,在/etc/default/svnserve 中,日志文件的arg 标志应该是--log-file,而不是--log。此外,虽然只需要创建一次日志目录,但不能保证 /var/run 会持续存在。最好使用RuntimeDirectory= 指令。在 Ubuntu 中,/var/run 是指向/run 的符号链接。
  • @Grexis 非常感谢您的改进。此服务设置现在看起来很棒。我了解了systemd 的另一个功能,并修复了我的 FHS 关于/run 的问题。谢谢
  • 这不会在 logrotation 期间中断未完成的 svn 连接吗?也就是说,如果我正在进行 svn 操作,比如在自动构建器上进行长时间结帐,“重新启动”不会中断并因此中断我的 svn 连接,从而中断我的构建吗?
  • 好问题。据我所知,svnserve 为每个请求分叉并等待孩子在退出之前停止......所以我认为没有机会取消正在进行的操作
  • 我将KillMode 恢复为默认control-group,否则子进程将继续运行。 ExecReload 没有预期的效果,进程被简单地杀死了。
【解决方案2】:

(我会在@Yves Martin's answer 上发表评论,但这是一个新帐户,我不能发表评论。:-P)

对于 SELinux,此解决方案不允许自动启动守护程序。我做了一些改变让它快乐。 svnserve 守护进程在 /var/log 树中没有 open 权限。将日志放在 svn 帐户的域中可以解决安全问题。

在/etc/systemd/system/svnserve.service:

ExecStart=/usr/bin/svnserve --daemon \
  --pid-file /var/run/svnserve/svnserve.pid \
  --root /project/svn/repos \
  --log-file /project/svn/log/svnserve.log

在 /etc/logrotate.d/svnserve:

/project/svn/log/*.log {  # path changed
...
  create 644 svn svn   # corrected group and made world-readable
...

最后,让 svn repos 和 log 目录拥有正确的所有权和安全类型:

sudo mkdir /project/svn
sudo chmod 755 /project/svn
sudo mkdir /project/svn/repos /project/svn/log
sudo chown -R svn:svn /project/svn
sudo semanage fcontext --add --type svnserve_content_t "/project/svn(/.*)?"
sudo restorecon -Rv /project/svn

(显然,将 /project/svn 更改为您决定放置 repo 结构的任何位置。/var/svn 很常见,并且该目录树的规则已经存在,因此上面的最后几行是不必要的。)

【讨论】:

  • semanage add 选项需要两个'-',如:# sudo semanage fcontext --add --type svnserve_content_t "/project/svn(/.*)?"
  • 谢谢@Mac。固定
【解决方案3】:

请考虑替换 xinet -> systemd: (这主要来自http://0pointer.de/blog/projects/inetd.html

您需要创建两个文件:

svnserve.socket

[Unit]
Description=SVN Socket for Per-Connection Servers

[Socket]
ListenStream=3690
Accept=yes

[Install]
WantedBy=sockets.target

和 svnserve@.service

[Unit]
Description=SVN Per-Connection Server

[Service]
User=svn
Group=svn
ExecStart=-/usr/bin/svnserve -i -r /srv/repositories/svn/repositories
StandardInput=socket

将这两个文件复制到 /etc/systemd/system/

然后

systemctl enable svnserve.socket
systemctl start svnserve.socket
systemctl status svnserve.socket

【讨论】:

    【解决方案4】:

    对 Yves Martin 上述出色回答的评论(我还没有代表点可以评论):

    当尝试使服务在启动时启动时,我会收到一个错误:

    $ sudo systemctl enable svnserve.service
    Failed to execute operation: Invalid argument
    

    在做了一些研究后,我发现您显然无法将别名设置为与服务相同的名称。从 svnserve.service 的 [Install] 部分删除 Alias 行解决了这个问题:

    [Unit]
    Description=Subversion protocol daemon
    After=syslog.target network.target
    
    [Service]
    Type=forking
    RuntimeDirectory=svnserve
    PIDFile=/run/svnserve/svnserve.pid
    EnvironmentFile=/etc/default/svnserve
    ExecStart=/usr/bin/svnserve $DAEMON_ARGS
    User=svn
    Group=svn
    KillMode=control-group
    Restart=on-failure
    
    [Install]
    WantedBy=multi-user.target
    

    【讨论】:

    • 我发现在 Ubuntu 20.04 上也是如此。我从启用中得到一个不同的错误:“无法启用单元:文件 /etc/systemd/system/svnserve.service 已经存在。”谢谢!
    【解决方案5】:

    更新:我在下面的回答已经过时了。这些改进和其他改进已纳入Yves Martin's excellent solution

    我有两个改进:一般建议不要运行root之类的东西。为此创建一个用户,例如“svn”。使用分叉时显式指定PID文件也是recommended。我的 svnserve.service 看起来很像你的,只是我添加了以下几行:

    User=svn
    Group=svn
    PIDFile=/usr/local/svn/svnserve.pid
    ExecStart=/usr/bin/svnserve  -d -r /usr/local/svn/repos --pid-file /usr/local/svn/svnserve.pid
    

    【讨论】:

    • PID 文件和单独的用户一样看起来是个好主意。谢谢!
    • 我已将它更改为将 pid 文件放在由 svn 用户而不是 /var/run/svnserve 完全管理的目录中。 /var/run 在我使用的系统上是临时的。也许最好有一个启动脚本创建和权限 /var/run/svnserve 但我选择不处理它。也许其他人可以改进这一点。
    • @EricS 我遇到了同样的问题。 RuntimeDirectory= 指令非常适合此操作,tmpfiles.d 可用于更复杂的操作。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2019-03-17
    • 1970-01-01
    • 2017-04-15
    • 2023-01-28
    • 2016-01-27
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多