服务启动后 systemd 连接到 stdin/stdout

服务启动后 systemd 连接到 stdin/stdout

我有一个 systemd 服务,它是一个控制台应用程序,这意味着它是通过向其 stdin 发送命令来控制的,并将信息输出到 sdout。如何设置 systemd 服务,以便我可以连接到其标准输入并随时向其发出命令,然后与之分离,并在必要时重复?

答案1

我可以想出多种方法来做到这一点。当然,每个都有其自己的注意事项。

  1. 最直接的方法可能是创建一个带有专用 tty 的简单服务,类似于:

    # /etc/systemd/system/systemd-interactive-simple-tty.service
    
    [Unit]
    Description=Example systemd interactive simple tty service
    After=getty.service
    
    [Service]
    # https://www.freedesktop.org/software/systemd/man/systemd.exec.html
    ExecStart=/usr/local/sbin/systemd-interactive.bash
    StandardInput=tty-force
    TTYVHangup=yes
    TTYPath=/dev/tty20
    TTYReset=yes
    # https://www.freedesktop.org/software/systemd/man/systemd.service.html
    Type=simple
    RemainAfterExit=false
    Restart=always
    RestartSec=5s
    
    [Install]
    WantedBy=default.target
    

    以下选项将与上述简单服务一起使用:

    1. 密谋(远程)控制文本模式虚拟控制台。这可能是你最好的选择(使用上面的 tty 服务)。它可以通过大多数扩展包存储库获得,并且使用起来很简单,如下所示:

       conspy 20 # hit ESC+ESC+ESC (3 times quickly, to exit)
      
    2. 奇夫特工作方式与 /dev/ttyN 类似,conspy但使 /dev/ttyN 成为前台(本地)终端。它是的一部分知识库集合,并且默认安装在几乎每个现代 Linux 发行版上。这就是为什么我认为值得一提。主要的警告chvt是它要求您使用附带的键盘,这可能不是您想要的。对于上面的服务示例,chvt可以这样使用:

       chvt 20 # ALT+F1 to return to /dev/tty1
      
    3. 雷普特尔使用ptrace(2)系统调用附加到远程程序(通过它的 PID)。这是与conspy&完全不同的方法chvt,但也适用于上述服务定义。

      请记住reptyr,它本身并不真正支持“分离”。它的 termcap 支持也不是很强大。通常,reptyr屏幕和/或多路复用器因为它们提供了一种更无缝的“分离”方式;我发现reptyr这是一个很棒的利基工具,可以将现有的 PID 移动到screen会话、tmux窗口或窗格中。

      也就是说;我把这个选项放在这里,尽管是最后,因为它仍然可以在reptyr没有screenor 的情况下使用tmux。主要的警告是,如果您中断该进程(例如 ^C),而不是将其(再次)重新复制到另一个 tty/pty(通过另一个 shell)。向进程发送中断可能会导致其中止,我相信您知道其余的事情。

      也许这没关系,特别是如果该进程不重要并且 systemd 服务配置为Restart=always如我上面所示。如果进程“中断”,那么 systemd 将自动重新启动它(systemd 的另一个很酷的功能!)。也有不同的值Restart。 YMMV。

      reptyr可通过大多数扩展包存储库获得并可以使用,如下所示:

       reptyr $(systemctl status systemd-interactive-simple-tty.service | grep Main\ PID | awk '{print $3}') # or just reptyr <pid>
      
  2. 另一种(更复杂[意味着有更多可能失败])方法是使用 screen 创建分叉服务,类似于:

    # /etc/systemd/system/systemd-interactive-forking-screen.service
    
    [Unit]
    Description=Example systemd interactive forking screen service
    
    [Service]
    # https://www.freedesktop.org/software/systemd/man/systemd.exec.html
    ExecStartPre=-/usr/bin/screen -X -S ${SCREEN_TITLE} kill # [optional] prevent multiple screens with the same name
    ExecStart=/usr/bin/screen -dmS ${SCREEN_TITLE} -O -l /usr/bin/bash -c /usr/local/sbin/systemd-interactive.bash
    # https://www.freedesktop.org/software/systemd/man/systemd.service.html
    Type=forking
    Environment=SCREEN_TITLE=systemd-interactive
    RemainAfterExit=false
    Restart=always
    RestartSec=5s
    SuccessExitStatus=1
    
    [Install]
    WantedBy=default.target
    

    屏幕是一个全屏窗口管理器,它在多个进程之间复用一个物理终端。它比第一个简单选项中列出的任何内容都要复杂得多。就我个人而言,我已经使用屏幕很长时间了,并且感觉足够舒服,可以信任它来处理大多数事情。这是一个非常宝贵的工具。

    与上述相比,主要优点是良好的 termcap 支持(尽管不如 tmux)。这只是意味着您的退格键、箭头等将比使用conspy或更好地工作reptyrscreen可以通过大多数根据包存储库,并且可以像这样使用:

    screen -r systemd-interactive # CTRL-A+D to detach
    
  3. 与分叉屏幕类似的方法是 fork tmux。的 systemd 服务tmux与 的 systemd 服务几乎相同screen。但是,我不会详细说明这一点,因为,已经很晚了而且我累了。是的,我用tmux 很多超过screen(这些天)。

    事实上,我tmux现在正在 neovim 窗格中写这篇文章。但是,我仍然使用了screen很长时间。根据我的经验和观点,tmux对于这样的事情来说有点矫枉过正。 Suretmux更新,具有更多功能,并且是一个更好的 shell 多路复用器,screen但是……它甚至更复杂。伴随着额外的复杂性而来的是一些额外的不稳定。

    更重要的是,至少对我来说,tmux崩溃比屏幕更频繁。我将 screen 列为 #2,因为如果是我,对于类似的事情,我可能只会将 #1 与conspy.

  4. 取决于您的计划;命名管道...systemd 服务也支持它们! IE

    StandardInput=/path/to/named/pipe|
    

... 和更多。

答案2

对我来说更简单的屏幕解决方案:

地点:

/home/someUser/.config/systemd/user/some.service

内容:

[Unit]
Description=someServer

Wants=network.target
After=network.target

[Service]
ExecStart=screen -S screenName -D -m /home/someUser/startServer.sh

[Install]
WantedBy=default.target

相关内容