Führen Sie ein Remote-Skript / eine Remote-Anwendung im getrennten Modus in Ansible aus

32528
SadBunny

Ich habe Probleme, ein Remote-Anwendungs-Startskript "getrennt" von einem Ansible-Playbook auszuführen. Das Skript wird ausgeführt, aber ich kann es nicht loslassen. Ich mache wahrscheinlich etwas falsch, aber was?

Hier ist mein Reproduzent.

  1. Meine Remote-Java-Anwendung in Test.java läuft 10 Sekunden lang:

    class Test { public static void main(String[] args) { for (int I = 1; I <= 10; i++) { System.out.println("Hello world " + I);  try { Thread.sleep(1000); } catch (Exception e) { System.out.println("Exception caught: " + e); } } } } 

Wenn Sie dies in Test.class (javac Test.java) kompilieren und dann diese Klasse mit "java Test" ausführen, funktioniert sie wie erwartet (gibt 10 Ausgabenachrichten aus und beendet dann).

  1. Mein ausführbares Shell-Skript (wie in chmod 755), das diese Anwendung ausführt, sieht folgendermaßen aus:

    #!/bin/bash java Test & 

Das manuelle Ausführen ist auch völlig in Ordnung: Java-App wird ausgeführt und generiert dieselbe Standardausgabe in meiner Konsole. Das Shell-Skript wurde jedoch beendet, und ich habe wieder die Kontrolle über meine bash-Sitzung.

  1. Jetzt können Sie es durch ein Spielbuch von einem anderen Server laufen lassen. Ich habe versucht, das "Kommando" -Modul und das "Shell" -Modul auf verschiedene Weise zu verwenden, aber ohne Erfolg ...

    --- - hosts: vagrant1 gather_facts: false  tasks: - debug: msg="Running test app through Ansible shell module..."  - name: Start application shell: "/tmp/test.sh" args: chdir: "/tmp" executable: "/bin/bash"  - debug: msg="Running test app through Ansible command module..."  - name: Start application command: "nohup /tmp/test.sh &" args: chdir: "/tmp" 

All das läuft einwandfrei, dh das Shell-Skript läuft, die Java-Anwendung läuft und macht ihre Sache (dh 10 Sekunden laufen lassen, Ausgabe erzeugen und beenden). Das Ansible-Playbook wird jedoch ausgeführt, bis die Java-Anwendung abgeschlossen ist, und gibt dann die von der Java-Anwendung generierte Ausgabe zurück. Warum löst es nicht einfach das Shell-Skript ab und beendet das Playbook?

Die Ausgabe des Ansible-Playbooks lautet:

 monsterkill@monsterkill-ub-dt:~/playbooks$ ansible-playbook testrun.yaml -v  PLAY [vagrant1] ***************************************************************   TASK: [debug msg="Running test app through Ansible shell module..."] **********  ok: [vagrant1] => { "msg": "Running test app through Ansible shell module..." }  TASK: [Start application] *****************************************************  changed: [vagrant1] => {"changed": true, "cmd": " /tmp/test.sh ", "delta": "0:00:10.052927", "end": "2015-01-29 00:14:43.327418", "rc": 0, "start": "2015-01-29 00:14:33.274491", "stderr": "", "stdout": "Hello world 1\nHello world 2\nHello world 3\nHello world 4\nHello world 5\nHello world 6\nHello world 7\nHello world 8\nHello world 9\nHello world 10"}  TASK: [debug msg="Running test app through Ansible command module..."] ********  ok: [vagrant1] => { "msg": "Running test app through Ansible command module..." }  TASK: [Start application] *****************************************************  changed: [vagrant1] => {"changed": true, "cmd": ["nohup", "/tmp/test.sh", "&"], "delta": "0:00:10.045643", "end": "2015-01-29 00:14:53.557164", "rc": 0, "start": "2015-01-29 00:14:43.511521", "stderr": "nohup: ignoring input", "stdout": "Hello world 1\nHello world 2\nHello world 3\nHello world 4\nHello world 5\nHello world 6\nHello world 7\nHello world 8\nHello world 9\nHello world 10"}  PLAY RECAP ********************************************************************  vagrant1 : ok=4 changed=2 unreachable=0 failed=0 
6

3 Antworten auf die Frage

13
user1338062

Verwenden Sie einfach eine asynchrone Aktion mit poll: 0:

- command: yourscript.sh async: 45 poll: 0 

Diese Optionen sind erforderlich, um zu verhindern, dass Ansible die untergeordneten Prozesse dieser Aufgabe mit os.killpg beendet .

Dann in yourscript.sh:

java Test & disown 

disown entfernt den Prozess aus der Jobtabelle, sodass SIGHUP nicht an ihn gesendet wird. nohup macht dasselbe, ist aber nicht notwendig.

Bearbeiten : Beachten Sie, dass disown nicht in allen Shells verfügbar ist (z. B. Bindestrich).

Hallo, was soll man tun, um einen Befehl unbegrenzt im Hintergrund auszuführen und nicht ansprechbar zu blockieren? Die async-Option lässt das Skript nur 45 Sekunden lang laufen und beendet es dann. Ich möchte den Befehl auf unbestimmte Zeit ausführen. Ich verwende bereits den Befehl nohup und die Option. Der Befehl wird jedoch beendet, sobald die async-Zeit abgelaufen ist. Ich habe die Umfrage auf 0 gesetzt Mrunal Gosar vor 7 Jahren 0
Hallo, ich stehe vor demselben Problem und asynchrone Aufgaben funktionieren gut. Ich habe jedoch keine klare Erklärung gefunden und auch nicht den Code-Teil von ansible gefunden, der einen untergeordneten Prozess abtötet. Irgendeine Hilfe ? Kassav' vor 6 Jahren 0
5
SadBunny

Die Google-Server müssen jetzt rauchen, aber ich habe eine Lösung gefunden. Als ich realisierte, dass Ansible alle seine Remote-Befehle über separate SSH-Aufrufe ausführt, testete ich dies manuell vom Ansible-Server und stellte fest, dass es sich um die SSH-Funktionalität handelt.

Die Antwort ist anscheinend, das Skript, das ich für den doppelten Hintergrund-Trick aufgerufen habe, zu haben, der mit einem Nohup kombiniert wird, um Hangup-Signale (SIGHUP) zu ignorieren, und mit dem Trennen der Streams stdout und stderr kombiniert. Das Remote-Startskript funktioniert also nicht mehr:

java Test & 

... aber stattdessen jetzt:

( ( nohup java Test 1>/dev/null 2>&1 ) & ) 

was macht was ich will. Das Ansible-Playbook startet jetzt das Remote-Skript, das wiederum die Java-Anwendung startet, dann aber doppelte Hintergründe und keine Zusammenhänge und trennt die Ausgabeströme.

Dieser Stackoverflow-Thread hat mir geholfen.

5
smiller171

Die Ausführung Ihres Skripts als Daemon mit Start-Stop-Daemon scheint hier eine elegantere Lösung zu sein. http://manpages.ubuntu.com/manpages/raring/man8/start-stop-daemon.8.html

- name: Start application shell: "start-stop-daemon --start --quiet --pidfile /var/run/test --exec /tmp/test.sh" args: executable: "/bin/bash" 
Bitte geben Sie alle relevanten Informationen in Ihrer Antwort an. Externe Links sind ideal für Verweise und weiterführende Literatur, sollten jedoch nicht den gesamten Inhalt Ihrer Antwort darstellen. David Richerby vor 8 Jahren 0