Frage Kann ich einen Text an den STDIN eines aktiven Prozesses senden, der in einer Bildschirmsitzung ausgeführt wird?


Ich habe einen Serverprozess mit langer Laufzeit in einer Bildschirmsitzung auf meinem Linux-Server. Es ist ein wenig instabil (und leider nicht meine Software, also kann ich das nicht beheben!), Also möchte ich einen nächtlichen Neustart des Prozesses skripten, um die Stabilität zu unterstützen. Die einzige Möglichkeit, das System ordnungsgemäß herunterzufahren, besteht darin, zum Bildschirmprozess zu wechseln, zu dem Fenster zu wechseln, in dem es ausgeführt wird, und auf seiner Steuerkonsole die Zeichenfolge "stop" einzugeben.

Gibt es irgendwelche intelligenten Umleitungsverzerrungen, die ich machen kann, damit ein Cronjob diesen Stopbefehl jeden Tag zu einer bestimmten Zeit sendet?


61
2017-09-06 11:42


Ursprung




Antworten:


Diese Antwort löst das Problem nicht, aber es ist hier gelassen, weil 30+ Leute es nützlich fandensonst hätte ich es vor langer Zeit gelöscht.

Schreiben Sie an /proc/*pid of the program*/fd/0. Das fd Unterverzeichnis enthält die Deskriptoren aller geöffneten Dateien und Dateideskriptoren 0 ist die Standardeingabe (1 ist stdout und 2 ist stderr).

Sie können dies verwenden, um Nachrichten auf dem tty auszugeben, auf dem ein Programm läuft, obwohl Sie nicht in das Programm selbst schreiben können.

Beispiel

Terminal 1:

[ciupicri@hermes ~]$ cat
shows on the tty but bypasses cat

Terminal 2:

[ciupicri@hermes ~]$ pidof cat
7417
[ciupicri@hermes ~]$ echo "shows on the tty but bypasses cat" > /proc/7417/fd/0

78
2017-09-06 12:06



@ James Lawrie: dann schau dir das an proc (5) und proc.txt. - Cristian Ciupitu
+2 Egal wie viel du denkst du weißt, es gibt immer mehr zu lernen :) glatt. - troyengel
Beachten Sie jedoch, dass der proc fd nur zu dem weiterleitet, was als Quelle für stdin verwendet wird. In Ihrem Beispiel, wenn Sie etwas in Terminal 1 eingeben, wird es erneut ausgedruckt (es wird an die Katze gesendet, stdin und cat druckt es), was dazu führt, dass Sie es zweimal sehen. Auf der anderen Seite, wenn Sie etwas an fd / 0 senden, wird es an die Konsole gesendet, aber nicht an cat, und wird daher nur einmal angezeigt. Da cat in diesem Beispiel einfach die Eingabe erneut ausgibt, können Sie nicht wirklich sehen, ob Ihre Eingabe oder Ausgabe gedruckt wird, also dieses Missverständnis. / fd / 0 zeigt auf die Konsole / Punkte; sehen ls -l /proc/7417/fd/0. - Kissaki
Beispiel aus der Praxis: Ich habe gphoto2 --get-all-files gestartet und 100 Mal nach einer Bestätigung gefragt. Wenn ich "y"> / proc / PID / fd / 0 ausspreche, geht gphoto2 nicht weiter, jedoch wird "y" im Terminal gedruckt. - Thorsten Staerk
@ThorstenStaerk, ich weiß, deshalb habe ich diese Notiz hinzugefügt. Sie schreiben nur in die Gerätedatei, die dem Terminal entspricht, auf dem gphoto2 ausgeführt wird (z. /dev/pts/19), das y Charakter erreicht nicht die Anwendung selbst. Es ist ähnlich wie bei der Verwendung von schreibe (1) Befehl. Wie auch immer, versuche entweder meine andere Antwort oder ein grafisches Automatisierungswerkzeug wie xdotool. - Cristian Ciupitu


Bildschirmbasierte Lösung

Starten Sie den Server wie folgt:

# screen -d -m -S ServerFault tr a-z A-Z # replace with your server

Bildschirm Wird im getrennten Modus gestartet. Wenn Sie also sehen möchten, was läuft, führen Sie Folgendes aus:

# screen -r ServerFault

Kontrolliere den Server so:

# screen -S ServerFault -p 0 -X stuff "stop^M"
# screen -S ServerFault -p 0 -X stuff "start^M"
# screen -S ServerFault -p 0 -X stuff "^D" # send EOF

(Diese Antwort basiert auf Senden von Texteingabe an einen abgelösten Bildschirm von dem Unix und Linux Geschwisterstelle)

Erläuterung der Parameter:

-d -m
   Start screen in "detached" mode. This creates a new session but doesn't
   attach to it.  This is useful for system startup scripts.
-S sessionname
   When creating a new session, this option can be used to specify a meaningful
   name for the session.
-r [pid.tty.host]
-r sessionowner/[pid.tty.host]
   resumes a detached screen session.
-p number_or_name|-|=|+
   Preselect a window. This is useful when you want to reattach to a specific
   window or you want to send a command via the "-X" option to a specific
   window.
-X
   Send the specified command to a running screen session e.g. stuff.

Zeug [Zeichenfolge]

   Stuff the string string in the input  buffer of the current window.
   This is like the "paste" command but with much less overhead.  Without
   a parameter, screen will prompt for a string to stuff.

tmux basierte Lösung

Starten Sie den Server wie folgt:

# tmux new-session -d -s ServerFault 'tr a-z A-Z' # replace with your server

tmux Wird im getrennten Modus gestartet. Wenn Sie also sehen möchten, was läuft, führen Sie Folgendes aus:

# tmux attach-session -t ServerFault

Kontrolliere den Server so:

# tmux send-keys -t ServerFault -l stop
# tmux send-keys -t ServerFault Enter
# tmux send-keys -t ServerFault -l start
# tmux send-keys -t ServerFault Enter
# tmux send-keys -t ServerFault C-d # send EOF

Erläuterung der Parameter:

 new-session [-AdDP] [-c start-directory] [-F format] [-n window-name] [-s
         session-name] [-t target-session] [-x width] [-y height]
         [shell-command]
         Create a new session with name session-name.

         The new session is attached to the current terminal unless -d is
         given.  window-name and shell-command are the name of and shell
         command to execute in the initial window.  If -d is used, -x and
         -y specify the size of the initial window (80 by 24 if not
         given).

 send-keys [-lR] [-t target-pane] key ...
               (alias: send)
         Send a key or keys to a window.  Each argument key is the name of
         the key (such as `C-a' or `npage' ) to send; if the string is not
         recognised as a key, it is sent as a series of characters.  The
         -l flag disables key name lookup and sends the keys literally.

34
2017-10-19 01:08





Versuchen Sie Folgendes:

# screen
# cd /path/to/wd
# mkfifo cmd
# my_cmd <cmd
C-A d

Und das zu töten:

# cd /path/to/wd
# echo "stop" > cmd
# rm cmd

4
2017-09-06 12:03



Das ist gut, aber es könnte den Nachteil haben, während des Programmlaufs keine anderen Befehle senden zu können. Wenn das Programm aufhört, wenn EOF auf stdin auftritt, dann auf dem ersten echo "xxx" > cmd Das Programm stoppt (weil die Leitung geschlossen wird). Obwohl einige Programme schlau genug sind, um sie wieder zu öffnen (rewind(3)) ihre stdin, wenn sie EOF treffen. - Cristian Ciupitu


Falls es jemandem hilft:
Ich hatte ein ähnliches Problem, und der Prozess, den ich verwendete, war nicht unter screen oder tmuxIch musste einen anderen Ansatz wählen.

ich habe angehängt gdb zum xterm dass mein Prozess lief und verwendet wurde call write(5, "stop\n", 5) von gdb um in den Master-Pty-Dateideskriptor zu schreiben.
Ich habe herausgefunden, an welchen Dateideskriptor die Daten gesendet werden sollen /proc/<pid>/fd für einen Link zu /dev/ptmx und dann Versuch und Irrtum zwischen den beiden Optionen (das Senden meiner Zeichenfolge an beide übereinstimmenden Dateideskriptoren schien keinen Schaden anzurichten).

BEARBEITEN

Es stellte sich heraus, dass die xterm Prozess, den ich angehängt hatte, wurde mit der spawn-new-terminal()  xterm Aktion von einer Tastatur, und der zweite ptmx Dateideskriptor offen war einfach die ptmx des Elternteils xterm Prozess, der nicht geschlossen wurde.
Daher hatten die Trial-and-Error-Aufrufe die Ausgabe an dieses andere Terminal gesendet.
Die meisten xterm Prozesse haben nicht zwei ptmx Dateideskriptoren.

ENDE EDIT

Dadurch wurde diese Zeichenfolge effektiv in das Terminal eingegeben und somit an den darunter laufenden Prozess gesendet.

n.b. Möglicherweise müssen Sie das Anhängen an einen laufenden Prozess mit etwas Ähnlichem zulassen
sudo bash -c "echo 0 > /proc/sys/kernel/yama/ptrace_scope"


1
2017-12-31 09:42