2016-12-14 8 views
2

Ich versuche, eine zeitgesteuerte Funktion zu implementieren. Wenn der Timer abläuft, sollte die Funktion/der Befehl beendet werden. Wenn die Funktion/der Befehl beendet ist, sollte der Timer die Bash nicht auf den Timeout des Timers warten lassen.Führen Sie eine zeitgesteuerte Funktion in Bash

(cmdpid=$BASHPID; \ 
    (sleep 60; kill $cmdpid 2>/dev/null) & \ 
    child_pid=$!; \ 
    ssh remote_host /users/jj/test.sh; \ 
    kill -9 $child_pid) 

Die test.sh kann oder kann nicht in 60 Sekunden beenden. Das hat gut funktioniert.

Aber wenn ich das Ergebnis der test.sh erhalten möchten, die „ERFOLG“ oder „FAILURE“ Echos, habe ich versucht, mit

result=$(cmdpid=$BASHPID; \ 
    (sleep 60; kill $cmdpid 2>/dev/null) & \ 
    child_pid=$!; \ 
    ssh remote_host /users/jj/test.sh; \ 
    kill -9 $child_pid) 

Hier ist es für Timer wartet, um zu beenden. Ich kann sehen, dass "kill -9 $ child_pid" mit dem Befehl set -x ausgeführt wird, aber die Kill-Funktion zerstört nicht wirklich die Sub-Shell.

+0

Welche Sub-Shell sprechen Sie? Wenn der 'sleep' beendet ist, würde der' kill $ cmdpid' die erste Subshell zerstören ... wenn das nur mit einem QUIT-Signal möglich ist (ich bin mir nicht sicher). Mein Zweifel: Kann eine Subshell mit einem QUIT-Signal getötet werden, wenn einer ihrer Kindprozesse gehängt wird? – Jdamian

+0

Das Problem ist, dass Sie die Subshell töten, nicht den "Schlaf" darin.Wenn Sie in ein 'ps' schauen, werden Sie sehen, dass die Eltern-PID von 'sleep' 0 ist. – cdarke

+1

Ist Ihnen der' timeout' Befehl bekannt? Es scheint, als ob du versuchst, das Rad neu zu erfinden ... – gilez

Antwort

1

Eine Möglichkeit, dieses Problem anzugehen, wäre, den Timer auf einem separaten Skript auszuführen, sagen MyTimerTest, die von aufgerufen wird (MainScriptTest), aber separat ausgeführt wird, und welches Script, das zuerst beendet "tötet" das andere. Zum Beispiel:

Auf MainScriptTest Sie dies am Anfang setzen könnten:

killall MyTimerTest > /dev/null 2>&1 

Die MyTimerTest könnte etwa wie folgt:

nohup /folder/MyTimerTest > /dev/null 2>&1 & 

Auf MainScriptTest Sie diese am Ende setzen könnte:

#!/bin/bash 
sleep 60 
killall MainScriptTest > /dev/null 2>&1 
exit 0 

Hinweis: die Langer Name für die Skripte mit gemischtem Groß- und Kleinbuchstaben (zB: MainScriptTest) ist absichtlich, killall ist Groß- und Kleinschreibung und das verhindert, dass etwas kaputt gemacht wird. Um sehr sicher zu sein, können Sie sogar einen Token zusätzlich zu dem längeren Namen hinzufügen, wie zum Beispiel: MainScriptTest88888 oder so ähnlich.

Bearbeiten: Dank gilez, wer schlug die Verwendung der timeout Befehl. Wenn das Sie auf Ihrem System verfügbar ist, könnte man einen schnellen Einzeiler wie folgt tun:

timeout 60 bash -c "/folder/MainScriptTest" 

Mit timeout bequem ist. Wenn MainScriptTest jedoch unabhängige untergeordnete Prozesse erstellt (z. B. durch Aufrufen von: nohup /folder/OtherScript &), würde timeout diese untergeordneten Prozesse nicht beenden, und der Exit wäre nicht sauber.

Die erste Lösung, die ich gab, ist länger, aber es könnte angepasst werden, um diese Kindprozesse (oder andere Prozesse, die Sie mögen), indem sie zum Beispiel auf die MainScriptTest, wie das Hinzufügen zu töten:

killall OtherScript > /dev/null 2>&1 
+0

Das hat nicht funktioniert. Der aus dem neuen Bash-Skript laufende Schlaf nimmt den Namen "sleep" an und killall konnte ihn nicht finden – user2647717

+0

Ich kann das Problem nicht auf meinen Systemen replizieren - hier funktioniert es einwandfrei. Ich habe 'GNU Bash, Version 4.3.30 (1)'. Ich bin mir auch nicht sicher, dass ich verstehe, was Sie sagen, das Problem war. War "Schlaf" alleine, der weiter lief? Was ist mit "MainScriptTest" und "MyTimerTest", werden sie getötet? Erzähle bitte nochmals, ob du das untersuchen willst - ich würde gerne, wenn du willst, wäre es interessant und möglicherweise lehrreich. –

+0

Wenn ich den von Ihnen erwähnten Weg versuchte, zeigte "ps" "sleep" statt "MyTimerTest". Also konnte ich das Skript nicht mit "killall MyTimerTest" beenden. Die Bash, die ich verwende, ist 4.1.2 (1). Leider kann ich es nicht upgraden. – user2647717

Verwandte Themen