Script läuft im Vordergrund aber nicht im Hintergrund

Heute ist Stammtischzeit:
Jeden Donnerstag 20:30 Uhr hier im Chat.
Wer Lust hat, kann sich gerne beteiligen. ;)
  • Für das
    hier behandelte Problem habe ich diese Script gebastelt, dass abhänging von der CPU-Usage eines Prozesses ein GPIO (über wiringPi) schaltet:



    Das Ganze funktioniert perfekt wenn ich das Script einfach im Vordergrund laufen lasse. Ich möchte es aber mit " &" im Hintergrund laufen lassen. Dann funktioniert es jedoch nicht (schaltet nicht).
    Habe auch mit screen und nohup rumprobiert.
    Bin allerdings auch absoluter Anfänger...

    Jemand eine Idee?

  • Script läuft im Vordergrund aber nicht im Hintergrund? Schau mal ob du hier fündig wirst!

  • Schreibe mal ganz vorne im Script

    Code
    LOG_FILE="/tmp/$(basename $0).log"
    exec 1> >(tee -a $LOG_FILE >&1)
    exec 2> >(tee -a $LOG_FILE >&2)


    rein. Dann kommentier mal das

    Code
    while true
    do


    und das zugehörige

    Code
    done


    aus dass die ganze Sache nur einmal durchläuft. Dann rufe es mit

    Code
    bash -xv meinProg &


    auf. Dann findest Du auf dem Bildschirm wie auch in /tmp/myProg.log eine identische detailierte Ausgabe was das Script macht, welche Zwischenwerte berechtet werden und wie sie aussehen. Sieh Dir das mal genauer an. Vermutlich wirst Du dann rausfinden können was nicht funktioniert und warum.

  • Die Kommentare die du teilweise direkt hinter dem Befehl oder der Schleife stehen hast würd ich lieber dadrüber oder drunter in einer eigenen Zeile schreiben

    Dann dreht sich deine while Schleife auch nur solange im Kreis, solange kein Fehler auftritt also das innerhalb der Schleife " true " bleibt, passiert da aber irgendwo ein Fehler ändert sich der Status auf "false" und die Schleife wird beendet...
    Um das zu verhindern änder wie while Schleife einfach so ab:

    Code
    while :; do

    Was mir auch noch aufgefallen is:

    Code
    pid=`less /var/run/mpd/pid`


    Ist wie ich finde eher schlecht... Benutz anstatt "less" lieber "cat" sodass es dann so aussähe:

    Code
    pid=`cat /var/run/mpd/pid`


    Alternativ ginge aber auch:

    Code
    pid=`< /var/run/mpd/pid`

    Was für einen Unterschied das macht kann ich dir zeigen:

    Code
    root@raspberry-pi:~# START=$(date +%s%N); pid=`less /var/run/sshd.pid`; END=$(date +%s%N);  echo $(($(($END - $START)) / 1000000))
    34
    root@raspberry-pi:~# START=$(date +%s%N); pid=`cat /var/run/sshd.pid`; END=$(date +%s%N);  echo $(($(($END - $START)) / 1000000))   
    23
    root@raspberry-pi:~# START=$(date +%s%N); pid=`< /var/run/sshd.pid`; END=$(date +%s%N);  echo $(($(($END - $START)) / 1000000))   
    17
    root@raspberry-pi:~#

    ...Angabe ist in Millisekunden...

    Das kann man auch anders machen:

    Code
    for i in 1 2 3 4 5 6 7 8 9 10


    Und zwar so:

    Code
    for i in {1..10}


    (kein Scherz ;) )

    Da weiss ich nicht genau wieso du "top" benutzt um die aktuelle Auslastung auszulesen, das bremst das Script eigentlich aus..

    Code
    load=`top -p $pid -n1 | awk 'FNR==8{print $10}'`


    Stattdessen kann du besser "ps up" verwenden:

    Code
    load=`ps up $pid | grep $pid | awk {'print $3'}`

    Inwiefern deine Benutzung von top langsamer ist kann ich dir auch zeigen:

    Code
    root@raspberry-pi:~# START=$(date +%s%N); load=`ps up $pid | grep $pid | awk {'print $3'}`; END=$(date +%s%N);  echo $(($(($END - $START)) / 1000000))      
    98
    root@raspberry-pi:~# START=$(date +%s%N); load=`top -p $pid -n1 | awk 'FNR==8{print $10}'`; END=$(date +%s%N);  echo $(($(($END - $START)) / 1000000))     
    207


    ...Angabe wie oben auch schon: in Millisekunden... Dein "top" brauch also fast 10 millisekunden länger
    ( Kleinvieh macht auch Mist :D )
    Wesendlich schneller ginge es übers auslesen der /proc/$pid/stat aber das is auch unter Umständen komplizierter

    Ansonsten sehe ich da aber keinen Fehler - vermutlich liegts an der while true...

  • Vielen Dank für Eure Hilfe - es läuft!!!!!! :bravo2:

    Mit Hilfe des Logs habe ich gesehen, das es beim top hängen bleibt. Das gibt im Hintergrund wohl nix aus wenn nicht der Batch-Modus aktiviert wird:

    Zitat


    -b : Batch mode operation
    Starts top in 'Batch mode', which could be useful for sending output from top to other programs or to a file. In this mode, top will not accept input and runs until the iterations limit you've set with the '-n' command-line option or until killed.


    Quelle: http://linux.die.net/man/1/top


    Allerdings war das nicht alles - die Ausgabe scheint leicht anders zu sein, die %CPU ist jetzt im Feld 9. Muss man auch erst mal druff kommen, weil halt im Feld 10 auch kein Mist steht...

    So muss es nun lauten:

    Code
    load=`top -b -p $pid -n1 | awk 'FNR==8{print $9}'`


    meigrafd: Vielen Dank für die sehr anschaulichen Optimierungstipps. Da ist Folgendes bei rausgekommen:

    Auslesen des pid-Files in die pid-Variable:
    Geht mit cat, aber der dritten Variante bleibt die Variable leer...?!??

    Code
    pid=`< /var/run/mpd/pid`


    Keine Ahnung warum, aber wegen der nur geringen Geschwindigskeitsoptimierung gegenüber cat lass ich cat sowieso (übersichtlicher).

    For-Schleife:
    Die {1..10}-Schreibweise habe ich schon beim Script-Basteln ausprobiert. Geht nicht... Es scheint die Schleife nur einmal zu durchlaufen... (hab ich aber nicht mit dem Log getestet). Ich habe das do analog zu deinem Hinweis zu while auch mal dahinter geklemmt. Sieht nun so aus:

    Code
    for i in {1..10};do


    Siehst du da was??

    ps statt top:
    Als ich mit dem Script angefangen habe, bin ich auch zuerst auf ps gestoßen und habe damit experimentiert, allerdings gab es dort keine offensichtliche Änderung wenn mpd "aktiv" war (d.h. Wiedergabe an) oder nicht...
    Nach ein bisschen suchen habe ich diese Erklärung gefunden:
    http://unix.stackexchange.com/questions/5853…same-cpu-result


  • For-Schleife:
    Die {1..10}-Schreibweise habe ich schon beim Script-Basteln ausprobiert. Geht nicht... Es scheint die Schleife nur einmal zu durchlaufen... (hab ich aber nicht mit dem Log getestet). Ich habe das do analog zu deinem Hinweis zu while auch mal dahinter geklemmt. Sieht nun so aus:

    Code
    for i in {1..10};do


    Siehst du da was??

    'so' sehe ich da nix, nein... Aber so:

    Aber siehst du einen Unterschied zum folgenden?:


    ..also nich nicht :D nur die Schreibweise vom Code


    ps statt top:
    Als ich mit dem Script angefangen habe, bin ich auch zuerst auf ps gestoßen und habe damit experimentiert, allerdings gab es dort keine offensichtliche Änderung wenn mpd "aktiv" war (d.h. Wiedergabe an) oder nicht...
    Nach ein bisschen suchen habe ich diese Erklärung gefunden:
    http://unix.stackexchange.com/questions/5853…same-cpu-result

    Ja oke, einfacher ist es über "top" aber lies die Erklärung:

    Zitat


    ps, as well as top, uses data from files stored under /proc/

    Das ist das was ich zum schluss meinte - aber ist eben komplizierter manuell/selber umzusetzen ;)
    "top" ist eben auch nur ein monitoring Tool, also auch nur eine Momentaufnahme - aber ich denke für deine Zwecke ausreichend :)
    :angel:

Jetzt mitmachen!

Du hast noch kein Benutzerkonto auf unserer Seite? Registriere dich kostenlos und nimm an unserer Community teil!