Ecrire à stdin du processus d'arrière-plan

25

Je suis sur une boîte Ubuntu 10.04 et j'ai démarré un serveur en arrière-plan (myserver &) sur ssh. Cela fonctionne bien, mais j'ai besoin d'un moyen pour accéder au stdin du serveur, car la seule façon de contrôler le serveur est par cette méthode.

Existe-t-il un moyen d'accéder à la stdin d'un processus déjà en cours afin que je puisse y écrire (et, espérons-le, lire sa sortie standard)? Évidemment, si j'allais faire ça maintenant, je commencerais par une redirection FIFO vers stdin, mais malheureusement c'est un peu tard pour ça maintenant.

Des idées?

tajmorton
la source
Ne pourriez-vous pas simplement le ramener au premier plan? ('jobs' listera votre processus d'arrière-plan actuel, 'fg $ X' ramènera le travail au premier plan, ctrl + b mettra le travail en pause et vous ramènera à votre shell, tandis que 'bg' poursuivra le processus suspendu dans le background)
symcbean

Réponses:

10

Vous pouvez essayer d'écrire dans son répertoire pid / proc. Supposons que le pid de votre démon soit 2000, essayez d'écrire dans / proc / 2000 / fd / 0

Katriel
la source
Merci ... J'ai trouvé ça juste après avoir posté ça (après une journée de recherche - typique). Cela semble fonctionner (en ce qui concerne l'envoi de données au programme). Malheureusement, le programme n'accepte pas les commandes. Je l'ai testé en exécutant le serveur sur mon ordinateur local, et bien sûr, je vois les données apparaître, mais le programme ne reconnaît pas les commandes. Je dois appuyer manuellement sur Entrée sur le terminal du serveur, puis il indique simplement une commande non reconnue. Peut-être un peu de bizarrerie java? Je suis coincé ...
tajmorton
1
que diriez-vous d'écho -e "quelque chose \ n"> / proc / 2000 / fd / 0?
katriel
En fait, cela ne fonctionne pas toujours car / proc / <pid> / fd / 0 pointe vers / dev / pts <un certain nombre> sur au moins certains systèmes ...
bk138
La première réponse à serverfault.com/questions/178457/… note que cette approche ne fonctionne pas réellement.
barrycarter
2
Cela ne fonctionne pas vraiment. Votre shell normalement (quand aucun canal ou redirection n'est utilisé) démarre une commande avec des descripteurs de fichier 0via 2le même fichier, qui est normalement un terminal virtuel (quelque chose comme /dev/pty/...). La commande lit alors depuis FD 0et écrit dans FD 1et 2pour communiquer avec le terminal virtuel (par exemple via SSH ou directement avec votre émulateur de terminal). Si un autre processus accède à ce fichier (par exemple via /proc), exactement la même chose se produit, c'est- à- dire que l' écriture sur celui-ci écrit sur le terminal et non sur la commande.
Feuermurmel
29

Vous pouvez démarrer votre serveur avec un canal nommé (fifo) comme entrée:

mkfifo /tmp/srv-input
cat > /tmp/srv-input &
echo $! > /tmp/srv-input-cat-pid
cat /tmp/srv-input | myserver &

Il cat > /tmp/srv-input &est important d'éviter que votre serveur ne reçoive un EOF. Au moins un processus doit avoir le fifo ouvert par écrit afin que votre serveur ne reçoive pas d'EOF. Le PID de cette commande est enregistré dans le /tmp/srv-input-cat-pidfichier pour ce dernier kill.

Dans le cas où vous avez déjà démarré votre serveur, vous devez utiliser un débogueur tel que gdbpour le joindre à votre processus pour le rediriger stdinvers le fifo:

gdb -p PID
call close(0)
call open(0, "/tmp/srv-input", 0600)

Et puis faites quelque chose comme ci-dessous pour envoyer des entrées à votre serveur (dans une autre fenêtre de terminal si nécessaire):

echo "command" > /tmp/srv-input

Pour envoyer un EOF à votre serveur, vous devez tuer le cat > /tmp/srv-inputprocessus dont le PID a été enregistré dans le /tmp/srv-input-cat-pid file.

Dans le cas de GDB, il suffit de quitter GDB et EOF sera envoyé.

jfg956
la source
1
il s'agit d'une approche beaucoup plus portable que celle de @katriel car / proc / 2000 / fd / 0 n'est pas standard sur tous les systèmes.
Prior99
L'astuce avec "cat> / tmp / srv-input &" m'a sauvé quelques maux de tête. Merci!
Prior99
Et alors mkfifo /tmp/srv-input; tail -f /tmp/srv-input | myserver &? Cela gardera le tuyau ouvert aussi ...
bk138
@ bk138: il me semble que la queue devrait fonctionner, mais il n'y a qu'une seule façon de savoir avec certitude: tester.
jfg956
tailne fonctionne pas, mais a ajouté ceci pour terminer le travail: cat /tmp/srv-input | myserver; kill -9 cat / tmp / srv-input-cat-pid` && rm / tmp / srv-input-cat * `
Thiago Macedo
4

Comme ci-dessus, mais «chat» ne fonctionnait pas pour moi. Le fichier a obtenu l'EOF et s'est terminé après l'envoi d'une commande.

Cela a fonctionné pour moi:

#!/bin/bash

mkfifo /tmp/srv-input
tail -f /tmp/srv-input | myserver &
Tamir
la source