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

lmq*_*305 7 io systemd

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

Jos*_*ris 12

我可以想到多种方法来做到这一点。当然,每个人都有自己的警告。

  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
    
    Run Code Online (Sandbox Code Playgroud)

    以下选项适用于上述简单服务:

    1. conspy对文本模式虚拟控制台进行(远程)控制。这可能是您最好的选择(使用上述 tty 服务)。它可以通过大多数扩展包存储库获得,并且易于使用,如下所示:

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

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

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

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

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

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

       reptyr $(systemctl status systemd-interactive-simple-tty.service | grep Main\ PID | awk '{print $3}') # or just reptyr <pid>
      
      Run Code Online (Sandbox Code Playgroud)
  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
    
    Run Code Online (Sandbox Code Playgroud)

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

    与上述相比的主要优势是不错的 termcap 支持(虽然不如 tmux 的好)。这只是意味着您的退格键、箭头等将比使用conspy或更好reptyrscreen可以通过大多数基础包存储库获得,并且可以像这样使用:

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

    事实上,我现在正在 Neovim 窗格中编写此内容tmux。但是,我仍然使用screen了更长的时间。根据我的经验和观点,tmux对于这样的事情来说太过分了。当然tmux是更新的,具有更多的功能,并且是一个比screen但是更好的外壳多路复用器......它甚至更复杂。伴随着额外的复杂性而来的是一些额外的不稳定性。

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

  4. 取决于你的程序;命名管道...... systemd 服务也支持它们!IE

    StandardInput=/path/to/named/pipe|
    
    Run Code Online (Sandbox Code Playgroud)

... 和更多。