Timeout für ein Bash Script

A

aeson

Foren As
Hallo,

ich hoffe, dass ich hier richtig bin. Meine Frage ist, glaube ich, nichts besonderes aber dennoch konnte ich bei google leider keine Antwort auf mein Problem finden.

Wie kann ich die maximale Ausführungszeit eines Shell-Scripts festlegen? Also quasi ein set_time_limit (PHP) für ein Shell-Script.

gruß aeson
 
hm,

evtl. schafft hier "sleep" abhilfe?

#!/bin/bash
echo "Warte 10 Sekunden"
/usr/bin/blub &
sleep 10
kill $!
echo "Genug Gewartet"
 
Danke erstmal für die Antwort. Eventuell habe ich mich undeutlich ausgedrückt was ich erreichen wollte. Nehmen wir folgendes Beispiel:

Ich habe ein Shell-Script, das sollte im Idealfall maximal 10 Sekunden laufen. Jetzt will ich einen Timeout bei 15 Sekunden setzen, der das Script auf jeden Fall nach 15 Sekunden beenden soll.
 
Entweder stehe ich gerade auf dem Schlauch oder es ist nicht das was ich gesucht habe. Mir ist leider nicht klar, in wie fern mir der Link weiterhelfen kann.
 
Na du baust einfach eine Abfrage ein, die deinen Prozess nach einer festgelegten Zeit killt, mit meinen primitiven Faehigkeiten sieht das dann so aus.
Code:
#!/bin/sh
echo "$PPID"
sleep $(( 3 * 2 ))
kill $PPID
Beendet das Skript nach 3*2 Sekunden.
Wobei man hier die systemweite Variable $PPID (ID des aktuellen Prozesses) ausnutzt.
 
Oder du machst es mit if

Code:
#!/bin/bash

fortune &

PID=$!
sleep 2

if ps $PID ; then
    kill $PID
    echo "gekillt"
else
    echo "bereits beendet"
fi
 
... oder du schickst einen Wecker in den Hintergrund:
Code:
#!/bin/sh

TIMEOUT=10

cleanup()
{
        echo " cleaning up ..."
        echo "Done."
        exit 0
}

trap cleanup 1 2 3 15

( sleep $TIMEOUT; kill -HUP $$ ) &


while :; do
        echo -n .
        sleep 1
done
 
Danke für die vielen Beispiele. Ich habe schon einiges mit kill usw. probiert. Das Problem ist nicht das killen als solches sondern das, was anschließend passieren soll. Hier mal genau das was ich brauche:

Ich rufe meine PHP-Script auf. Dieses führt ein Shell Script mit exec aus. Wenn das Shell Script länger als 10 Sekunden braucht, soll das Shell Script gekillt werden und es soll normal mit dem PHP-Script weiter gehen.
 
Ich rufe meine PHP-Script auf. Dieses führt ein Shell Script mit exec aus. Wenn das Shell Script länger als 10 Sekunden braucht, soll das Shell Script gekillt werden und es soll normal mit dem PHP-Script weiter gehen.
Wartet dein PHP-Skript den auf die Rueckmeldung des Bash-Skriptes?

Ansonsten (wenn dein PHP-Skript nicht auf das Bash-Skript wartet) ist das doch genau was du suchst.
Oder versteh ich da was falsch? (PHP sagt Hallo, PHP ruft Skript auf, PHP macht andere Sachen (waehrend das Bash-Skript vor sich hinmacht), PHP verabschiedet sich, um meinen Gedankengang mal zu formulieren ;) )
 
Zuletzt bearbeitet:
Ja, das PHP-Script wartet auf das Shell-Script. Wenn sich das Shell-Script aufhängt, hängt auch das PHP-Script. Das, dass PHP-Script nicht weiterläuft solange das Shell-Script läuft ist so gewollt... Deswegen will ich ja auch ein Timeout beim Shell-Script machen worauf ich dann wiederum mit dem PHP-Script reagieren kann um das Shell-Script eventuell erneut ausführen zu können.

Wenn ich das Shell-Script aber kille, bleibt auch mein PHP-Script hängen :(
 
Und was ist, wenn du den sleep-Mechanismus in PHP realisierst?
In etwa sowas (ungetestet)
PHP:
<?php

$pid = system ("fortune &; echo $!;");
sleep(10);
if (system("ps ".$pid." >/dev/null && echo $?") == "0") {
    system("kill ".$pid);
}

?>
 
Ich habe es erstmal nur so probiert um eventuelle Fehler auszuschließen:

PHP:
$pid = system ("download.sh ".urlencode(DATEINAME)." &");
echo "Hallo";

Theoretisch müsste er ja den Prozess starten und dann sofort Hello ausgeben. Das passiert aber leider nicht :(
 
Mit shell_exec geht es leider auch nicht, das Hallo wird wieder nicht angezeigt. Ist es mit PHP vllt nicht möglich Unterprozesse mit & zu starten?
 
In den Kommentaren zu shell_exec() sind Beispiele dazu vorhanden.

PHP:
<?php
    //Run linux command in background and return the PID created by the OS
    function run_in_background($Command, $Priority = 0)
    {
        if($Priority)
            $PID = shell_exec("nohup nice -n $Priority $Command > /dev/null & echo $!");
        else
            $PID = shell_exec("nohup $Command > /dev/null & echo $!");
        return($PID);
    }
?>

Eventuell stimmt der Pfad zum Shellscript nicht? Die Log-Datei sagt vielleicht auch was dazu.
 
Das hilft mir erstmal sehr viel weiter. Jetzt werde ich noch ein bisschen Basteln (aber komme erstmal wieder zurecht). Ich melde mich später nochmal mit Ergebnissen.

Vielen Dank an alle und ein besonderen Dank an slackfan. Ohne deinen letzten Beitrag zu diesem Thema würde ich immer noch hier sitzen und hätte keine Ahnung :)
.
.
.
EDIT (autom. Beitragszusammenführung) :
.

Hallo, ich bins nochmal. Ich hab mir das mal alles durch den Kopf gehen lassen. Mit der Lösung über php habe ich ja quasi ein gezwungenes Timeout oder? Weil PHP wartet ja auf jeden Fall die sleep zeit ab auch wenn das shell script schon fertig sein sollte oder?
 
Zuletzt bearbeitet:
Auch das steht in leicht abgewandelter Form in den besagten Kommentaren.
Du kannst das ja über eine While-Schleife managen.

PHP:
<?php
//Run linux command in background and return the PID created by the OS
function run_in_background($Command, $Priority = 0)
{
    if($Priority)
        $PID = shell_exec("nohup nice -n $Priority $Command > /dev/null & echo $!");
    else
        $PID = shell_exec("nohup $Command > /dev/null & echo $!");
    return($PID);
}

//Verifies if a process is running in linux
function is_process_running($pid)
{
    exec("ps $pid", $ProcessState);
    return(count($ProcessState) >= 2);
}

//Kill a process if running
function kill_process($pid){
    if(is_process_running($pid)){
        exec("kill -KILL $pid");
        return true;
    }
    else{
        return false;
    }
}

$pid = run_in_background("fortune")
$counter = 0
$timeout = 10

while(is_process_running($pid)) {
    if ($counter < $timeout) {
        $counter += 1;
        sleep(1);
    }
    else {
        kill_process($pid);
    }
}
?>

Ungetestet!

Edit: Das Ganze ist ein traumhaftes Beispiel, um es objektorientiert in eine Klasse zu packen.
 
Zuletzt bearbeitet:
Okay ich habe jetzt eine für mich optimale Lösung gefunden. Ich habe mir eine Funktion geschrieben, die jede Minuten den aktuellen Status des Hintergrundprozesses abfragt. Wird die Prozess ID (die vom Hintergrundprozess) nicht mehr gefunden, wurde das Shell-Script komplett ausgefuehrt und meine Funktion gibt "true" zurück. Des Weiteren habe ich einen Parameter übergeben, der der Funktion die Gesamtgröße des Downloads übergibt und einen weiteren Parameter, der der Funktion sagt, wie viel MB der Hintergrundprozess pro Minute abarbeiten muss. Lange rede, kurzer Sinn: Hier meine Funktion:

PHP:
function check_process($PID)
{
    exec('ps '.$PID,$process);

    if(count($process) == 1) {
        return true;
    }

    return false;
}

function set_timeout($pid,$size,$mb,$refresh)
{
    echo 'Downloadvorgang: ';

    for($i=1;$i<=1000*1000;$i++) {
        sleep($refresh);

        if(check_process($pid)) {
            return true;
        }

        if($size >= ($i*$mb)) { //MB pro Minute
            echo ".";
            continue;

        } else {
            return false;
        }
    }
}

Danke nochmal an slackfan für den Denkanstoß. Wie du siehst konnte ich einige Elemente aus deinen Beiträgen auch verwerten :)

gruß aeson
 

Ähnliche Themen

systemd service mit Bash Script und Subshell in einer tmux Umgebung

Nginx als Reverse Proxy für Nextcloud und Emby

Keine grafische Oberfläche (Debian Installation)

Telefoninterview (Wie sich auf Bash-Shell-Fragen vorbereiten?)

iptables Konfigurationsdatei

Zurück
Oben