Comment écrire sur stdin d'un service

Sep 30 2020

J'ai un service en cours d'exécution qui a un CLI connecté à stdin. Quand je suis sshdans la machine, j'aimerais pouvoir envoyer des commandes au stdin de ce service.

systemd.exec dit que StandardInput=file:/path/to/filec'est une chose et prend en charge les FIFO. Cela ressemble à la méthode la plus simple.

J'ai essayé ça dans mon ~/.config/systemd/user/foo.service

[Service]
ExecStartPre=mkfifo %t/foo.stdin
ExecStart=cat -
StandardInput=file:%t/foo.stdin
ExecStopPost=rm -f %t/foo.stdin

Dans cet exemple, je m'attends à ce que lorsque j'exécute ce qui suit, je vois la sortie en écho dans le journal.

echo "hello" > /run/user/1000/foo.stdin

J'ai deux problèmes avec ceci:

  1. foo.service: Failed to set up standard input: No such file or directory . Il semble que cela StandardInput=doit exister avant ExecStartPre=. Dois-je créer un tuyau permanent dans un endroit statique pendant l'installation ou y a-t-il une solution de contournement? Si je crée le fichier manuellement et que je supprime ExecStartPre/ ExecStopPost, les choses fonctionnent.
  2. Le premier echo "command"est traité correctement, mais envoie un EOFmessage et stdin se ferme. Je voulais que le stdin reste ouvert. La réponse ( exec 3> stdin, ..., exec 3>&-) semble être d'utiliser la redirection bash FD, mais cela n'est pas disponible dans systemd.

Réponses

3 user3840170 Sep 30 2020 at 09:51

Vous pouvez créer une prise pour votre FIFO:

  • foo.socket:

    [Socket]
    ListenFIFO=%t/foo.stdin
    Service=foo.service
    
  • foo.service:

    [Service]
    ExecStart=/bin/cat -
    Sockets=foo.socket
    StandardInput=socket
    StandardOutput=journal
    StandardError=journal
    

Démarrez-le comme suit:

systemctl --user start foo.socket

Le service lui-même démarre dès que le FIFO est écrit dans. Si vous voulez qu'il démarre immédiatement, lancez-le plutôt comme ceci:

systemctl --user start foo.service