Anzeige:
Ergebnis 1 bis 15 von 15

Thema: [SH] Prozess beendet sich nicht mehr automatisch

  1. #1
    Registrierter Benutzer
    Registriert seit
    01.11.2010
    Beiträge
    25

    [SH] Prozess beendet sich nicht mehr automatisch

    Ich habe das folgende Script und möchte damit immer aktuell die Daten eines Prozesses aus /proc/<pid>/status in ein File schreiben und das so lange wie der Prozess ausgeführt wird.

    Code:
    #!/bin/sh
    lang=$1
    code=$2
    #
    #Check the language
    if [ "$lang" = "jruby" ]; then
    	jruby $code &
    	#Is the process still running?
    	until [ $(ps -e | grep -c $!) -ne 0 ]
    	do
    		cat /proc/$!/status >> /opt/data.txt
    	done
    elif [ "$lang" = "clojure" ]; then
    	echo blabla
    else 
    	echo "Ungueltige Eingabe"
    fi
    Ohne die Schleife funktioniert es super. Um nun aber zu prüfen ob der Prozess noch aktiv ist, habe ich eine Schleife hinzugefügt. Das Problem ist jetzt, dass der Prozess den ich aufrufe, sich nicht mehr selbst beendet. Der fällt nun nach der Ausführung in sowas wie einen Sleep-Modus bis man ihn manuell killt. Das führt natürlich dazu, dass auch meine Schliefe sich nicht mehr selbst beendet.

    Hat jemand eine Idee wieso das so ist und was man dagegen machen könnte? Ich hab selbst leider keine allzu grosse Erfahrung mit Shell-Scripts.

    Vielen Dank!

  2. #2
    Registrierter Benutzer Avatar von John W
    Registriert seit
    29.01.2010
    Beiträge
    211
    Hast du mal versucht, ein sleep einzubauen? Zudem würde ich statt "$(ps -e | grep -c $!)" besser "ps $!" schreiben. Die if-elif-else-Konstruktion könntest du auch noch durch ein case-Konstrukt ersetzen.

  3. #3
    Registrierter Benutzer
    Registriert seit
    01.11.2010
    Beiträge
    25
    Danke für die Verbesserungsvorschläge. Aber ich wenn ich "$(ps -e | grep -c $!)" einfach durch "ps $!" ersetzten funktioniert das Script nicht mehr (too many arguments). Eigentlich auch logisch, das Resultat von "ps -e | grep -c $!" ist ja auch nicht das gleiche wie dasjenige von "ps $!".

    Was meinst du genau mit sleep einbauen. Mir ist jetzt nicht wirklich klar, wo mir ein sleep etwas nützen könnte.

  4. #4
    Registrierter Benutzer Avatar von John W
    Registriert seit
    29.01.2010
    Beiträge
    211
    Ich kann mir gut vorstellen, dass der Prozess nicht beendet werden kann, wenn er dauernd inspiziert wird, daher dachte ich, dass folgender Code vl funktioniert:
    Code:
        while ps $! > /dev/null
        do
            cat /proc/$!/status >> /opt/data.txt
            sleep 1
        done
    PS: Ich hab vergessen zu erwähnen, dass die Schleifenlogik dabei umgedreht werden muss und dass test ([ ... ]) dann auch nicht mehr benötigt wird.

  5. #5
    Registrierter Benutzer
    Registriert seit
    01.11.2010
    Beiträge
    25
    Cool. Funktioniert bestens. Vielen Dank.

    Weisst du zufällig auch, wie ich nur bestimmte Zeilen aus einer Datei auslesen kann. Mit "cat /proc/$!/status >> /opt/data.txt" wird ja sozusagen immer die ganze status-Datei in meine "data.txt" Datei kopiert. Ist es irgendwie auch möglich z.B. nur die Zeilen 10-15 zu kopieren?

  6. #6
    Registrierter Benutzer Avatar von John W
    Registriert seit
    29.01.2010
    Beiträge
    211
    Einzelne Zeilenbereiche kannst du mit sed ausgeben lassen:
    Code:
    sed -n '10,15p' /proc/$!/status >> /opt/data.txt
    Mit sed kannst du statt Zeilenangaben als Bereich auch reguläre Ausdrücke benutzen, z.B. "sed -n '/start/,/ende/p'". Wichtig ist der Parameter -n, da sonst alle Zeilen ausgegeben würden und Zeilen im Bereich doppelt.

  7. #7
    Registrierter Benutzer
    Registriert seit
    01.11.2010
    Beiträge
    25
    Vielen Dank. Funktioniert alles soweit. Ich möchte mein Script jetzt aber noch etwas erweitern in dem ich die Prozessdaten welche "top" ausliest in ein anderes File schreibe. Ich habe also die folgenden Zeilen unterhalb der Schleife hinzugefügt.

    Code:
    jruby $code &
    top -p $! -b -d 01.00 >> /opt/data/jruby.top
    Nun hat top ja die Eigenheit auch weiterzulaufen, wenn der Prozess den ich mit -p angebe gar nicht mehr läuft. Wie kann ich jetzt also prüfen ob mein Prozess noch läuft und falls das nicht mehr der Fall ist, wie kann ich top dann abbrechen?

    Ich nehme an, da brauche ich wieder die gleiche Schliefe wie für das vorherige Problem auch um zu prüfen ob der Prozess noch läuft. Da kommt dann ein kill-Befehl rein. Das geht aber wahrscheinlich nicht einfach so, weil top einen neuen Prozess startet. Wenn ich also $! in die Schleifenbedingung schreibe, prüfe ich ob top noch läuft, nicht ob der andere Prozess noch läuft. Hat dafür jemand einen Lösungsvorschlag?

  8. #8
    Registrierter Benutzer Avatar von John W
    Registriert seit
    29.01.2010
    Beiträge
    211
    Um die Prozessnummer zu erhalten, würde ich das Script abändern:
    Nachdem der Prozess gestartet wurde, speicherst du die PID ab und gibt die per acho auf stdout aus.
    Dein Script rufst du dann nicht mehr selbst auf, sondern machst das so:
    Code:
    top -p "$(script)" -b -d 01.00 >> /opt/data/jruby.top

  9. #9
    Registrierter Benutzer
    Registriert seit
    01.11.2010
    Beiträge
    25
    Zitat Zitat von John W Beitrag anzeigen
    Um die Prozessnummer zu erhalten, würde ich das Script abändern:
    Nachdem der Prozess gestartet wurde, speicherst du die PID ab und gibt die per acho auf stdout aus.
    Dein Script rufst du dann nicht mehr selbst auf, sondern machst das so:
    Ich kann dir leider nicht 100%ig folgen.

    Also Prozess starten, PID speichern (in eine Variable nehm' ich an?) und per echo ausgeben. Sowas?

    Code:
    jruby $code &
    pid0=$! &
    echo $pid0
    Das führt schon mal dazu, dass sich mein Programm nicht mehr beendet. Und das Script rufe ich anschliessend mit dem Top-Befehl auf? Ich mir ist ehrlich gesagt überhaupt nicht klar, wie das funktionieren sollte. Wäre echt dankbar, wenn du mir das noch etwas detaillierter erklären könntest. Hab wie gesagt noch nicht viel Erfahrung das scripten angeht.

  10. #10
    Registrierter Benutzer Avatar von John W
    Registriert seit
    29.01.2010
    Beiträge
    211
    Nein, etwa so:
    Code:
    #!/bin/sh
    lang=$1
    code=$2
    #
    #Check the language
    if [ "$lang" = "jruby" ]; then
        jruby $code &
        PID=$!
        echo $PID
        #Is the process still running?
        while ps $PID > /dev/null
        do
            sed -n '10,15p' /proc/$!/status >> /opt/data.txt
            sleep 1
        done
    elif [ "$lang" = "clojure" ]; then
        echo blabla >&2
    else 
        echo "Ungueltige Eingabe" >&2
    fi
    Wichtig ist, dass du dabei nichts auf stdout ausgibst, sonst macht
    Code:
    top -p "$(script)" -b -d 01.00 >> /opt/data/jruby.top
    Unsinn, weil $(script) nicht mehr nur die Pid ausgeben würde.
    Im obigen Code habe ich die Meldungen auf stderr oder nach /dev/null umgeleitet, es sollte so also funktionieren.

  11. #11
    Registrierter Benutzer
    Registriert seit
    01.11.2010
    Beiträge
    25
    Hm, funktioniert bei mir leider so nicht. Hier mal mein Script wies im Moment aussieht, vielleicht kannst du ja einen Fehler erkennen.

    Code:
    #!/bin/sh
    lang=$1
    code=$2
    #
    #Check the language
    case $lang in
    jruby)
    	#Get Memory Data
    	jruby $code &
    	PID=$!
    	echo $PID
    	#Is the process still running?
    	while ps $PID > /dev/null
    	do
    		sed -n '11,20p' /proc/$!/status >> /opt/data/jruby.memory
    		echo '-----------------------' >> /opt/data/jruby.memory		
    		sleep 1
    	done
    	;;
    clojure)
    	echo blabla >&2 ;;
    scala)
    	;;
    *)
    	echo "Ungueltige Eingabe" >&2
    esac
    Aufgerufen hab ich das ganze mit jetzt wie folgt.

    Code:
    top -p "$(./get_performance_data.sh jruby /opt/samples/Test.rb)" -b -d 01.00 >> opt/data/jruby.top
    Da steht dann der folgende Fehler:
    Code:
    top: unknown argument '
    Ich hab schon daran gedacht, dass es vielleicht aufgrund meiner zusätzlichen Parameter nicht geht. Aber ohne die kann mein Script ja auch nicht funktionieren.

  12. #12
    Registrierter Benutzer Avatar von John W
    Registriert seit
    29.01.2010
    Beiträge
    211
    "jruby $code &" wird wohl dran schuld sein - ersetz das mal durch "jruby $code >&2 &", dann werden Ausgaben vom Ruby-Code auch nach stderr geschrieben.

  13. #13
    Registrierter Benutzer
    Registriert seit
    01.11.2010
    Beiträge
    25
    Jetzt gibts keinen Fehler mehr aber leider auch keine Daten. So werden nun nur die Spaltenüberschriften ins File geschrieben, eigentlich das was top macht, wenn der überwachte Prozess nicht aktiv ist.

    Ich hab mir inzwischen überlegt, ob es vielleicht einfacher wäre das ohne den top-Befehl zu machen. Top muss ja seine Daten grundsätzlich auch von irgendwo beziehen. Wahrscheinlich auch irgend ein File im procfs. Wenn man herausfinden könnte wo sich diese Daten befinden, könnte man sie direkt von dort auslesen. Ich werd morgen mal etwas googeln, vielleicht find ichs ja raus oder evtl. weiss es hier sogar jemand. Das Resultat wäre evtl. sogar besser, da ich eh nicht alle Spalten brauche die top ausgibt.

  14. #14
    Registrierter Benutzer
    Registriert seit
    01.11.2010
    Beiträge
    25
    Hab herausgefunden, das man mit ps ebenfalls ähnliche Daten auslesen kann. Ich habs jetzt wie folgt gelöst (falls Interesse vorhanden).

    Code:
    random=tmp$(date +%d%m%Y_%H%M%S)
    jruby $code &	
    while ps $! > /dev/null
    do
    	ps -p $! -o user,pid,%cpu,c,time >> /opt/data/$random
    	sleep 1
    done
    sed '3~2d' /opt/data/$random >> /opt/data/jruby.cpu
    rm /opt/data/$random

  15. #15
    Registrierter Benutzer Avatar von John W
    Registriert seit
    29.01.2010
    Beiträge
    211
    Empfehlung:
    random=tmp$(date +%d%m%Y_%H%M%S)
    durch
    random="$(mktemp --tmpdir=/tmp/jrubyXXXXXX)"
    ersetzen, dein ersteres ist anfällig gegen Race-Conditions.

Lesezeichen

Berechtigungen

  • Neue Themen erstellen: Nein
  • Themen beantworten: Nein
  • Anhänge hochladen: Nein
  • Beiträge bearbeiten: Nein
  •