Hängende SSH-Prozesse, die von einem Skript gestartet wurden

Hängende SSH-Prozesse, die von einem Skript gestartet wurden

ich erstelle einige VMs über ein Skript. Dabei ändere ich die Namen der VMs mithilfe von SSH. Aus irgendeinem Grund funktioniert der folgende Befehl, wenn ich ihn für drei VMs ausführe, aber bei der magischen Zahl beim Erstellen von sieben VMs bleibt SSH hängen. Kann jemand bitte das Verhalten erklären?

Teil des Skripts. Dieses Skript wird gleichzeitig für angegebene X-VMs ausgeführt.

...
ssh-keygen -f ~/.ssh/known_hosts -R $IP
ssh-keyscan $IP >> ~/.ssh/known_hosts
SSH="ssh -i $SSH_KEY -o PasswordAuthentication=no"

echo "hostname $hostname && 
    echo HOSTNAME=$hostname >> /etc/sysconfig/network && 
    echo 127.0.0.1 $hostname >> /etc/hosts " | ssh -i $SSH_KEY -o PasswordAuthentication=no root@IP
...

nicht endende SSH-Prozesse

rag       2867  2808  0 01:05 pts/5  T  00:00:00 ssh -i ssh_key -o PasswordAuthentication=no root@vm4
rag       2869  2812  0 01:05 pts/5  T  00:00:00 ssh -i ssh_key -o PasswordAuthentication=no root@vm7
rag       2872  2818  0 01:05 pts/5  T  00:00:00 ssh -i ssh_key -o PasswordAuthentication=no root@vm1
rag       2875  2811  0 01:05 pts/5  T  00:00:00 ssh -i ssh_key -o PasswordAuthentication=no root@vm6
rag       2879  2814  0 01:05 pts/5  T  00:00:00 ssh -i ssh_key -o PasswordAuthentication=no root@vm5
rag       2881  2813  0 01:05 pts/5  T  00:00:00 ssh -i ssh_key -o PasswordAuthentication=no root@vm3
rag       2884  2807  0 01:05 pts/5  T  00:00:00 ssh -i ssh_key -o PasswordAuthentication=no root@vm2

ich habe Strace bei einem der laufenden Prozesse bekommen.

...
--- SIGTTOU (Stopped (tty output)) @ 0 (0) ---
rt_sigreturn(0x16)                      = -1 EINTR (Interrupted system call)
rt_sigaction(SIGALRM, {SIG_DFL, [], SA_RESTORER, 0x7fd26cd9d4a0}, NULL, 8) = 0
rt_sigaction(SIGHUP, {SIG_IGN, [], SA_RESTORER, 0x7fd26cd9d4a0}, NULL, 8) = 0
rt_sigaction(SIGINT, {SIG_DFL, [], SA_RESTORER, 0x7fd26cd9d4a0}, NULL, 8) = 0
rt_sigaction(SIGQUIT, {SIG_DFL, [], SA_RESTORER, 0x7fd26cd9d4a0}, NULL, 8) = 0
rt_sigaction(SIGPIPE, {SIG_IGN, [], SA_RESTORER, 0x7fd26cd9d4a0}, NULL, 8) = 0
rt_sigaction(SIGTERM, {SIG_DFL, [], SA_RESTORER, 0x7fd26cd9d4a0}, NULL, 8) = 0
rt_sigaction(SIGTSTP, {SIG_DFL, [], SA_RESTORER, 0x7fd26cd9d4a0}, NULL, 8) = 0
rt_sigaction(SIGTTIN, {SIG_DFL, [], SA_RESTORER, 0x7fd26cd9d4a0}, NULL, 8) = 0
rt_sigaction(SIGTTOU, {SIG_DFL, [], SA_RESTORER, 0x7fd26cd9d4a0}, NULL, 8) = 0
close(4)                                = 0
kill(2867, SIGTTOU)                     = 0
--- SIGTTOU (Stopped (tty output)) @ 0 (0) ---
--- SIGTTOU (Stopped (tty output)) @ 0 (0) ---
open("/dev/tty", O_RDWR)                = 4
rt_sigaction(SIGALRM, {0x7fd26e1ef540, [], SA_RESTORER, 0x7fd26cd9d4a0}, {SIG_DFL, [], SA_RESTORER, 0x7fd26cd9d4a0}, 8) = 0
rt_sigaction(SIGHUP, {0x7fd26e1ef540, [], SA_RESTORER, 0x7fd26cd9d4a0}, {SIG_IGN, [], SA_RESTORER, 0x7fd26cd9d4a0}, 8) = 0
rt_sigaction(SIGINT, {0x7fd26e1ef540, [], SA_RESTORER, 0x7fd26cd9d4a0}, {SIG_DFL, [], SA_RESTORER, 0x7fd26cd9d4a0}, 8) = 0
rt_sigaction(SIGPIPE, {0x7fd26e1ef540, [], SA_RESTORER, 0x7fd26cd9d4a0}, {SIG_IGN, [], SA_RESTORER, 0x7fd26cd9d4a0}, 8) = 0
rt_sigaction(SIGQUIT, {0x7fd26e1ef540, [], SA_RESTORER, 0x7fd26cd9d4a0}, {SIG_DFL, [], SA_RESTORER, 0x7fd26cd9d4a0}, 8) = 0
rt_sigaction(SIGTERM, {0x7fd26e1ef540, [], SA_RESTORER, 0x7fd26cd9d4a0}, {SIG_DFL, [], SA_RESTORER, 0x7fd26cd9d4a0}, 8) = 0
rt_sigaction(SIGTSTP, {0x7fd26e1ef540, [], SA_RESTORER, 0x7fd26cd9d4a0}, {SIG_DFL, [], SA_RESTORER, 0x7fd26cd9d4a0}, 8) = 0
rt_sigaction(SIGTTIN, {0x7fd26e1ef540, [], SA_RESTORER, 0x7fd26cd9d4a0}, {SIG_DFL, [], SA_RESTORER, 0x7fd26cd9d4a0}, 8) = 0
rt_sigaction(SIGTTOU, {0x7fd26e1ef540, [], SA_RESTORER, 0x7fd26cd9d4a0}, {SIG_DFL, [], SA_RESTORER, 0x7fd26cd9d4a0}, 8) = 0
ioctl(4, SNDCTL_TMR_TIMEBASE or TCGETS, {B38400 opost isig icanon echo ...}) = 0
ioctl(4, SNDCTL_TMR_TIMEBASE or TCGETS, {B38400 opost isig icanon echo ...}) = 0
ioctl(4, SNDCTL_TMR_CONTINUE or TCSETSF, {B38400 opost isig icanon echo ...}) = ? ERESTARTSYS (To be restarted)
...

Antwort1

Das klingt nach einem Wettlaufzustand, und wenn ich mir Ihr Skript anschaue, glaube ich zu wissen, wo.

So wie ich es verstehe, haben Sie ein Skript, das (unter anderem) die folgenden 2 Zeilen enthält:

ssh-keygen -f ~/.ssh/known_hosts -R $IP
ssh-keyscan $IP >> ~/.ssh/known_hosts

Und dann starten Sie das Skript mehrmals.

Die folgende Abfolge von Ereignissen kann Ihr Problem erklären:

  1. Eines der Skripts wird geöffnet, ~/.ssh/known_hostsum den Befehl auszuführen ssh-keygen -R. An diesem Punkt ssh-keygenliest der Befehl die gesamte Datei in den Speicher, damit er die Zielzeile entfernen kann.
  2. Ein anderes Skript wurde gerade ausgeführt ssh-keyscanund die Zeile in die Datei geschrieben.
  3. Der Prozess des ersten Skripts ssh-keygen(der aus Schritt 1) ​​beginnt mit dem Schreiben der Datei, aber da er die Datei gelesen hat, bevor Schritt 2 abgeschlossen war, enthält die geschriebene Datei nicht die Zeile, die Schritt 2 hinzugefügt hat. Daher wird die Zeile aus Schritt 2 gelöscht.
  4. Das zweite Skript führt dies aus ssh, aber der Hostschlüssel fehlt known_hostsaufgrund des in Schritt 3 genannten Problems. Daher bleibt SSH hängen und der Benutzer muss den Schlüssel bestätigen.

Genauere Einzelheiten:
Hintergrundprogramme können nicht vom Terminal lesen. Wenn Sie dies versuchen, wird dem Programm eine SIGTTIN gesendet. In Ihrem Strace wird jedoch angezeigt, dass das Programm eine SIGTTOU erhält. Normalerweise können Hintergrundprogramme problemlos in das Terminal schreiben, OpenSSH aktiviert jedoch ausdrücklich eine Terminaleinstellung namens , tostopdie zu diesem Verhalten führt. OpenSSH geht sogar noch weiter und verfügt über einen Signalhandler für SIGTTOU (unter anderem), der dazu führt, dass der OpenSSH-Code in eine Endlosschleife gerät, bis Sie den Prozess in den Vordergrund bringen (an diesem Punkt kann er die Eingabeaufforderung anzeigen und keine Signale mehr erhalten).

Wie Sie dieses Problem lösen möchten, ist eine andere Frage.

  • Eine Lösung wäre, eine Sperre hinzuzufügen (dafür gibt es ein flockDienstprogramm, das Sie verwenden können) und die known_hostsDatei vor diesen beiden Zeilen zu sperren und sie danach zu entsperren.
  • Eine andere Lösung wäre, die Option „ssh“ hinzuzufügen StrictHostKeyChecking=no. Mit diesen beiden Zeilen des Skripts machen Sie den Zweck der known_hostsDatei bereits zunichte, daher können Sie sie auch gleich ganz deaktivieren.

verwandte Informationen