Variable aus Child-Prozess "Re-exportieren"

Dieses Thema im Forum "Shell-Skripte" wurde erstellt von -eraz-, 28.04.2010.

  1. #1 -eraz-, 28.04.2010
    Zuletzt bearbeitet: 28.04.2010
    -eraz-

    -eraz- Tripel-As

    Dabei seit:
    27.03.2008
    Beiträge:
    151
    Zustimmungen:
    0
    Gibts ne Möglichkeit, wie ich eine in einem Child Prozess erstelle Variable zurückbringe in den Mutterprozess?
    Ich möchte aus einer Schleife wieder entkommen wenn ein Child Prozess seine Arbeit verrichtet hat, ich spiele da grad ein bisschen rum, aber ne andere Lösung als z.b. die hier ist mir nicht eingefallen:

    Code:
    function test {
       sleep 10
       echo "5" > /tmp/x
    }
    
    i=4
    for (( x=0; $x<=$i; x=$x+1 )); do
    
       pid=$(echo $$)
       if [ `ps -ef |grep $pid |wc -l` -le 2 ]; then
            test &
       fi
    
       if [ -e /tmp/x ]; then
            rm -f /tmp/x
            x=5
       else
            p1="."
            p2=".."
            p3="..."
            clear
            echo
            eval echo "Sammle Daten, bitte warten \$p$x"
            sleep 0.3
       fi
    
       if [ $x = 4 ]; then
            x=0
       fi
    
    done
    
    
    Funktioniert aber nicht 100%ig /tmp/x wird manchmal nicht gelöscht und nach Beendigung der Schleife bleiben der Prozess "test" und "sleep" noch eine Weile bestehen.

    PS: Bezieht sich auf Bash
     
  2. Anzeige

    Schau dir mal diese Kategorie an. Dort findest du bestimmt etwas.
    Registrieren bzw. einloggen, um diese und auch andere Anzeigen zu deaktivieren
  3. HBtux

    HBtux Linuxer

    Dabei seit:
    13.04.2010
    Beiträge:
    72
    Zustimmungen:
    0
    Ort:
    $HOME
    so...?
    Code:
    HBtux:/tmp/test # cat test1.sh
    #!/bin/bash
    
    testfunktion () {
            echo "testfunktion aufgerufen"
            sleep 3
            XX="5"
    }
    
    XX="1"
    echo $XX
    testfunktion
    echo $XX
    
    ergibt folgende Ausgabe....
    Code:
    HBtux:/tmp/test # ./test1.sh
    1
    testfunktion aufgerufen
    5
    
     
  4. -eraz-

    -eraz- Tripel-As

    Dabei seit:
    27.03.2008
    Beiträge:
    151
    Zustimmungen:
    0
    Nein das befreit mich leider nicht aus der Schleife, weil die Variable $XX (lt. deinem Beispiel) oder $x (lt. meinem Beispiel) die im Child-Prozess verändert wird, vom "Mutterprozess" nicht erkannt wird (auch nicht per export).
     
  5. HBtux

    HBtux Linuxer

    Dabei seit:
    13.04.2010
    Beiträge:
    72
    Zustimmungen:
    0
    Ort:
    $HOME
    folgende kleine Tipps am Rande.....

    "test" solltest Du nicht als Namen für eine Funktion nehmen, da es einen Betriebssystembefehl namens test gibt....


    pid=$(echo $$)
    geht so auch einfacher ...
    pid=$$


    Sonst fällt mir leider auch nur zurückschreiben über Pipe ein.... :think:
     
  6. #5 floyd62, 29.04.2010
    floyd62

    floyd62 Routinier

    Dabei seit:
    01.05.2007
    Beiträge:
    309
    Zustimmungen:
    0
    Hi,

    wenn ich das richtig verstehe, willst du einen Prozess starten, der sein Ergebnis z.B. nach /tmp/x schreibt, dann im Parent-Prozess darauf warten, dass der fertig wird und sein Resultat abholen?

    Dann scheint mir der Check innerhalb der Schleife, ob nicht schon mehr als 2 Prozesse laufen, unnötig kompliziert: du kannst ja den Child-Prozess vor der Schleife anwerfen, und dann solange warten, bis der fertig ist, entweder gleich mit "wait $!", oder mit einer kleinen kill-Schleife.

    Wenn der Kind-Prozess dann sein Ergebnis in eine Datei geschrieben hat, kannst du die ja ganz einfach einlesen.

    Das Folgende könnte etwa als Ansatz dienen:

    Code:
    #!/bin/sh
    
    
    run() {
            sh -c "echo START \$\$; sleep 3; echo \"X=$RANDOM\" >/tmp/\$\$.out" &
    }
    
    
    run
    CHILD=$!
    sleep 1
    
    
    cleanup() {
            kill -HUP $CHILD 2>/dev/null
            sleep 1
            rm -f /tmp/$CHILD.out
    }
    trap cleanup 0
    
    X="?"
    echo -n "$$: Warte auf $CHILD ."
    while kill -0 $CHILD 2>/dev/null; do
            echo -n .
            sleep 1
    done
    echo
    
    eval $(</tmp/$CHILD.out)
    echo "$CHILD liefert $X"
    
    exit 0
    
    Das Ganze zu erweitern auf z.B. mehrere parallell laufende run-Prozesse (über einen Array von Child-Prozess-Pids), einen Timeout einzubauen etc. dürfte trivial sein.

    Hoffe, das hilft dir mal weiter ...


    Gruss, A.
     
  7. #6 -eraz-, 29.04.2010
    Zuletzt bearbeitet: 29.04.2010
    -eraz-

    -eraz- Tripel-As

    Dabei seit:
    27.03.2008
    Beiträge:
    151
    Zustimmungen:
    0
    Nicht ganz, das schreiben von x=5 nach /tmp/x dient eigentlich nur dazu den Parent Prozess aus seiner Schleife zu befreien, sobald der Child-Prozess fertig ist. Aber die Methode die ich da gewählt habe scheint eh nicht sauber zu funktionieren, warum auch immer ...

    Stimmt, hast Recht :)

    Ich schau mir deine Lösung an, ich hoffe ich steig da durch, sind schon wieder soviele neue Sachen dabei. :D

    /edit

    @floyd62
    Mit Arrays hab ich bisher noch nie was gemacht, hast du da vielleicht ein kleines Beispiel?
    Und andere Frage: Was bewirkt die "cleanup" funktion bzw. der trap Befehl mit dem sie aufgerufen wird?
    .
    .
    .
    EDIT (autom. Beitragszusammenführung) :
    .

    Ich glaub das was ich brauche dürfte das hier sein :) :

    Code:
    #!/bin/bash
    
    function funktion {
       sleep 3
    }
    
    function funktion2 {
       sleep 3
    }
    
    function execute_functions {
       funktionen=("funktion" "funktion2")
       for (( i=0; i<${#funktionen}; i++ )); do
           ${funktionen[$i]}
       done
    }
    
    execute_functions &
    CHILD=$!
    
    i=4
    p1="."
    p2=".."
    p3="..."
    for (( x=0; $x<=$i; x=$x+1 )); do
       kill -0 $CHILD 2>/dev/null
       if [ $? = 1 ]; then
            x=5
       else
            clear
            echo
            eval echo "Sammle Daten, bitte warten \$p$x"
            sleep 0.3
       fi
    
       if [ $x = 4 ]; then
            x=0
       fi
    done
    
    Tut bisher genau das was ich will, muss ich aber noch ausgiebig testen, danke floyd62 für die Hilfe :)

    PS: Shell scripten is GEIL!! :D
     
  8. #7 floyd62, 29.04.2010
    floyd62

    floyd62 Routinier

    Dabei seit:
    01.05.2007
    Beiträge:
    309
    Zustimmungen:
    0
    Na wenns denn läuft ;) ...

    Nur noch kurz zur Ergänzung: mit Hilfe von "trap" kannst du in der Shell eine Funktion definieren, die beim Eintreffen von Signalen (1 "HUP", 2 "INTR", 3 "QUIT") bzw. beim Beenden des Skripts (0) noch aufgerufen wird. Was ich damit erreichen wollte (und mit
    Code:
    trap cleanup 0 1 2 3
    
    wahrscheinlich auch erreicht hätte) ist, dass ich das Skript z.B. mit Ctrl-C von der Konsole aus abbrechen hätte können, und dass beim Beenden auf jeden Fall auch ein noch laufender Child-Prozess mit Hangup-Signal abgeschossen und das Ergebnis-File gelöscht worden wäre ... man will ja den Schrott in /tmp nicht bis zum nächsten Reboot rumhängen lassen ...

    In der neuen Version deines Skripts werden die Funktionen übrigens nicht parallell in den Hintergrund geschickt, sondern schön sequentiell abgearbeitet, was du z.B. mit Ergänzungen wie
    Code:
    function funktion {
       echo START funktion
       sleep 3
       echo ENDE funktion
    }
    
    leicht sehen kannst. Weiss nicht, ob das so gedacht war ...

    Ganz am Rande: wenn du den Wert von $x nur auf 5 setzt, damit du aus der Schleife fliegst, das sollte sich auch einfacher mit dem "break" Kommando lösen lassen, etwa
    Code:
    kill -0 $CHILD 2>/dev/null
    if [ $? = 1 ]; then break; fi
    
    Die Geschichte mit den Arrays hast du ja sowieso schon gepeilt ...

    Und, ja, schon spassig, die Shell - man sieht doch immer wieder mal was Neues ...

    Gruss, A.
     
  9. #8 -eraz-, 30.04.2010
    Zuletzt bearbeitet: 30.04.2010
    -eraz-

    -eraz- Tripel-As

    Dabei seit:
    27.03.2008
    Beiträge:
    151
    Zustimmungen:
    0
    Danke für die Erklärung... im Laufe meiner "Einbauarbeit" ins "echte" Skript hat sich dann eh noch herausgestellt, das ich die Cleanup Funktion sehr gut brauchen kann. :)
    Das mit dem sequentiellen abarbeiten ist übrigens beabsichtigt, die Funktionen die in der Endversion des Skripts aufgerufen werden sind zum Teil etwas Performancelastig und ich will nicht das mir da ein Server in die Knie geht sobald das Skript aufgerufen wird.

    Achja, eins hab ich übrigens noch immer nicht kapiert, und zwar was hier passiert:
    Code:
    eval $(</tmp/$CHILD.out)
    Wenn ich das richtig sehe, wird die Ausgabe des CHILD Prozesses eingelesen, aber wohin?
    Vermutlich in X oder? Aber ich check nicht ganz wie es in X reinkommt durch den Befehl...?:think:
     
  10. HBtux

    HBtux Linuxer

    Dabei seit:
    13.04.2010
    Beiträge:
    72
    Zustimmungen:
    0
    Ort:
    $HOME
    Schaue mal weiter oben im Script, was in die Datei /tmp/$CHILD.out geschrieben wird.....
    Setze nun genau diese Zeichen innerhalb der Klammer ein und Du hast das Ergebnis.....
    Code:
    .... echo \"X=$RANDOM\" >/tmp/\$\$.out
    ....
    eval $(</tmp/$CHILD.out)
    
    das entspricht aufgelöst.....
    
    X=$RANDOM
    
    Es wird also einfach die Variable X gesetzt.
     
  11. -eraz-

    -eraz- Tripel-As

    Dabei seit:
    27.03.2008
    Beiträge:
    151
    Zustimmungen:
    0
    Ja schon, aber weiter oben setzt er ja X auf "?". Und bei eval lest er die datei in PID.out wieder in X ein. ABER, bei dem eval Befehl ist ja nirgens angegeben, dass der Inhalt von PID.out in X gelesen werden soll, also woher weiß die Shell das

    "eval $(</tmp/$CHILD.out)"

    ausgerechnet in die Variable X gelesen werden soll?
     
  12. Anzeige

    Vielleicht findest du HIER Antworten.
    Registrieren bzw. einloggen, um diese und auch andere Anzeigen zu deaktivieren
  13. #11 floyd62, 02.05.2010
    floyd62

    floyd62 Routinier

    Dabei seit:
    01.05.2007
    Beiträge:
    309
    Zustimmungen:
    0
    Hi,

    wie HBTux richtig erklärt: der Sohnprozess schreibt innerhalb der run()-FUnktion nicht nur den neuen Wert für X in die Ausgabedatei, sondern eine Anweisung, mit der der neue Wert für X gesetzt wird ("X=$RANDOM"). Mit $(<FILE) bekommst du den Inhalt einer Datei FILE als String, und den kannst du dann - wenn es denn ein gültiges Shell-Kommando ist - mit eval auswerten. Auf diese Weise könntest du dann auch mehrere Variablen an den Parent-Prozess zurückliefern ...

    Gruesse, A.
     
  14. HBtux

    HBtux Linuxer

    Dabei seit:
    13.04.2010
    Beiträge:
    72
    Zustimmungen:
    0
    Ort:
    $HOME
    Komentiere doch spasseshalber mal die Zeile "rm -f /tmp/$CHILD.out" aus und schaue nach dem Ausführen des Script mal in diese Temp-Datei rein, was dort drinnen steht.....
    Ich denke dann dürfte es klar sein, dass eval mit dem Inhalt macht.....

    Der Inhalt so so oder ähnlich aussehen.....
    Code:
    [B]cat /tmp/$CHILD.out[/B]   (bzw. [B]cat /tmp/2754.out[/B] - entsprechend der verwendeten PID)
    [B]X=2754[/B]
    
     
Thema:

Variable aus Child-Prozess "Re-exportieren"

Die Seite wird geladen...

Variable aus Child-Prozess "Re-exportieren" - Ähnliche Themen

  1. Linux 4.5 will UEFI-Variablen besser schützen

    Linux 4.5 will UEFI-Variablen besser schützen: Das Löschen bestimmter UEFI-Variablen kann manche Rechner nicht mehr startbar machen. Das kommende Linux 4.5 ergreift Maßnahmen dagegen, die im...
  2. Wie komme ich an den Inhalt des Inhalts einer Variable?

    Wie komme ich an den Inhalt des Inhalts einer Variable?: Hallo Zusammen, ich möchte meine Buildumgebung vereinfachen und besser zu automatisieren. Ein Skript schreibt Pfade in die env und diese...
  3. Textdatei zeilenweise in durchnummerierte Variablen schreiben

    Textdatei zeilenweise in durchnummerierte Variablen schreiben: Hi Leute, ich versuche folgendes Problem zu lösen. Ich möchte eine Textdatei einlesen und den Inhalt jeder Zeile in immer eine neue Variable...
  4. mysql Select Abfrageergebnis in unterschiedlichen Variablen sichern

    mysql Select Abfrageergebnis in unterschiedlichen Variablen sichern: Hallo zusammen, es geht um folgenden Teil meiner .sh-Datei: NumberCheck=`mysql $SQL_ARGS "SELECT lkw, Firma FROM adb_group WHERE...
  5. Teil einer Variablen auslesen und in neue Variable schreiben

    Teil einer Variablen auslesen und in neue Variable schreiben: Hallo, ist für Euch bestimmt ganz einfach, aber trotz googlen komme ich nicht auf eine Lösung. In Variable x habe ich stehen: xy,ab Nun möchte...