web-dev-qa-db-ja.com

systemdはサービスの開始後にstdin / stdoutに接続します

コンソールアプリケーションであるsystemdサービスがあります。つまり、コマンドをそのstdinに送信することによって制御され、情報をsdoutに出力します。どのようにすれば、systemdサービスをセットアップして、そのstdinに接続し、任意の時点でそれにコマンドを与え、これから切り離して、必要に応じて繰り返すことができますか?

3
lmq_305

これを行う方法はいくつか考えられます。もちろん、それぞれに独自の警告があります。

  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. conspy は、テキストモードの仮想コンソールを(リモートで)制御します。これはおそらく(上記のttyサービスで)最善の策です。ほとんどの拡張パッケージリポジトリから利用でき、次のように簡単に使用できます。

      _ conspy 20 # hit ESC+ESC+ESC (3 times quickly, to exit)
      _
    2. chvtconspyと同様に機能しますが、/ dev/ttyNをフォアグラウンド(ローカル)端末にします。これは kbd コレクションの一部であり、ほぼすべての最新のLinuxディストリビューションにデフォルトでインストールされます。それが私が言及する価値があると思った理由です。 chvtの主な注意点は、接続されているキーボードを使用する必要があることです。上記のサービスの例では、chvtは次のように使用できます。

      _ chvt 20 # ALT+F1 to return to /dev/tty1
      _
    3. reptyr は、ptrace(2)システムコールを使用して、リモートプログラムに(PIDを介して)接続します。これはconspychvtとはまったく異なるアプローチですが、上記のサービス定義でも機能します。

      reptyr自体は、実際には「切り離し」をサポートしていないことに注意してください。 termcapのサポートもあまり堅牢ではありません。通常、reptyrscreentmux と組み合わせて使用​​されます。これは、よりシームレスに「切り離す」方法を提供するためです。 reptyrは、既存のPIDをscreenセッションまたはtmuxウィンドウまたはペインに移動するための優れたニッチツールです。

      それは言った; reptyrまたはscreenなしでtmuxを使用することはまだ可能であるため、このオプションを最後に配置しました。主な注意点は、(別のシェルを介して)別のtty/ptyに(再度)反復するのではなく、プロセス(例えば^ C)を中断する場合です。プロセスにブレークを送信すると、プロセスが中止される可能性があります。残りを知っていると思います。

      特にプロセスが重要ではなく、上で示したようにsystemdサービスが_Restart=always_に設定されている場合は特に問題ないでしょう。プロセスが「壊れた」場合、systemdは自動的に再起動します(systemdのもう1つの優れた機能です)。 Restartにも異なる値があります。 YMMV。

      reptyrは、ほとんどの拡張パッケージリポジトリから入手でき、次のように使用できます。

      _ reptyr $(systemctl status systemd-interactive-simple-tty.service | grep Main\ PID | awk '{print $3}') # or just reptyr <pid>
      _
  2. 別の(より複雑な[失敗する可能性があることを意味する])アプローチは、次のように画面を使用してフォークサービスを作成することです。

    _# /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
    _

    screen は、複数のプロセス間で物理端末を多重化するフルスクリーンウィンドウマネージャーです。これは、最初の単純なオプションにリストされているものよりもかなり複雑です。個人的に、私は画面を長い間使用しており、ほとんどのもので信頼できるほど快適に感じています。それは非常に貴重なツールです。

    上記に対する主な利点は、適切なtermcapサポートです(ただし、tmuxの場合ほどではありません)。これは、バックスペースキー、矢印などがconspyまたはreptyrよりもうまく機能することを意味します。 screenは、ほとんどのbaseパッケージリポジトリから利用でき、次のように使用できます。

    _screen -r systemd-interactive # CTRL-A+D to detach
    _
  3. 画面をフォークする同様の方法は、tmuxをフォークすることです。 tmuxのsystemdサービスは、screenのsystemdサービスとほとんど同じです。しかし、これは詳しく説明するつもりはありません。まあ、それは遅く、私は疲れているからです。はい、私はtmuxscreen(最近)より多く使用します

    実際、私はこれを現在tmuxのneovimペインで書いています。しかし、私はscreenをまだずっと長く使用しています。私の経験と意見では、tmuxはこのようなものには過剰です。確かにtmuxscreenよりも新しく、より多くの機能を備えており、はるかに優れたシェルマルチプレクサですが...より複雑です。その余分な複雑さに加えて、いくつかの追加の不安定さが伴います。

    少なくとも私にとってより重要なのは、tmuxが画面よりも頻繁にクラッシュすることです。 screenを#2と表示したのは、それが私である場合、そのような場合には、おそらくconspyで#1を使用するだけだからです。

  4. プログラムによって異なります。名前付きパイプ... systemdサービスもそれらをサポートします!つまり.

    _StandardInput=/path/to/named/pipe|
    _

... もっと。

5
Joseph Tingiris