Dennis: PHP-CLI, in PHP auf kill reagieren

0 111

PHP-CLI, in PHP auf kill reagieren

Dennis
  • php
  1. 0
    Geplagter
    1. 0
      Dennis
  2. 1
    Tom
  3. 0
    Manuel B.
    1. 0
      Tom
      1. 0
        Manuel B.
      2. 0
        eddi
    2. 0
      Dennis
      1. 0
        Manuel B.
        1. 0
          Dennis
          1. 0
            Manuel B.
        2. 0
          eddi
          1. 0
            Manuel B.
    3. 2
      dedlfix
      1. 0
        Tom
        1. 0
          eddi
          1. 0
            Dennis
            1. 0
              Christian Seiler
              1. 0
                Dennis
                1. 0
                  Tom
                  1. 0
                    Christian Seiler
      2. 0

        Funktioniert, aber ich habs noch nicht ganz verstanden...

        Dennis
        1. 0
          Tom
          1. 0

            Noch eine Frage

            Dennis
            • webserver
            1. 0
              Tom
              1. 2
                Christian Seiler
                1. 0
                  Tom
                  1. 0
                    Christian Seiler
                    1. 0
                      Tom
                      1. 0

                        Break, CTRL-C, SIGINT, usw.

                        Tom
                        1. 0
                          Christian Seiler
                      2. 0
                        Christian Seiler
            2. 2
              Christian Seiler
              1. 0
                Dennis
                1. 0
                  Christian Seiler
                  1. 0
                    Dennis
                    1. 0
                      Christian Seiler
                      1. 0
                        eddi
                        1. 0
                          Christian Seiler
                          1. 0

                            sleep() vs. SIGSTOP

                            Dennis
                            1. 0
                              Christian Seiler
                              1. 0
                                Dennis
                                1. 0
                                  Christian Seiler
                      2. 0
                        Christian Seiler
          2. 0
            Tom
            1. 0
              Christian Seiler
              1. 0
                Tom
                1. 0
                  Christian Seiler
                  1. 0
                    Tom
                    1. 0
                      Christian Seiler
                      1. 0
                        Manuel B.
                        1. 0
                          Tom
                          1. 0
                            Christian Seiler
                          2. 0
                            Manuel B.
                      2. 0
                        Tom
                        1. 0
                          Christian Seiler
                          1. 0
                            Dennis
                            1. 1
                              Christian Seiler
        2. 1
          Christian Seiler
          1. 0
            Dennis
            1. 0
              eddi
              1. 0
                Dennis
                1. 0
                  Manuel B.
                  1. 0
                    eddi
                    1. 0
                      Manuel B.
                      1. 0
                        Dennis
                        1. 0
                          Manuel B.
                          1. 0
                            Dennis
                            1. 0
                              Manuel B.
                              1. 0
                                Dennis
                                1. 0
                                  Manuel B.
                                  1. 0
                                    Dennis
                                    1. 0
                                      Manuel B.
                  2. 0
                    Dennis
                    1. 0
                      Manuel B.
            2. 0
              Christian Seiler
              1. 0
                Dennis
                1. 0
                  Christian Seiler
                  1. 0
                    Dennis
  4. 0

    pcntl_fork() und posix_setsid(), was passiert da?

    Dennis
    1. 0
      Dennis
  5. 0

    Optimierung bzgl. Speicherauslastung bei mehreren Prozessen

    Dennis
    1. 0
      Christian Seiler
      1. 0
        Dennis
        1. 0
          eddi
          1. 0
            Dennis
            1. 0
              eddi
              1. 0
                Dennis
                1. 0
                  eddi
                  1. 0
                    Dennis
                    1. 0
                      eddi
      2. 0
        Manuel B.
        1. 0
          eddi
  6. 0

    exec() wartet nicht obwohl aufgerufenes Script sich forked

    Dennis
    1. 0
      eddi
    2. 0
      Christian Seiler
      1. 0
        Dennis
        1. 0
          Christian Seiler
          1. 0
            Christian Seiler
            1. 0
              Dennis
              1. 0
                Christian Seiler
                1. 0
                  Dennis
                  1. 0
                    Dennis
                    1. 0
                      Christian Seiler
                      1. 0

                        mod_auth_pam - Funktionsweise

                        Dennis
                        • webserver
                        1. 0
                          eddi
                          1. 0
                            Dennis
                            1. 0
                              Dennis
                              1. 0
                                eddi
                      2. 0

                        mod_authnz_external und pwauth

                        Dennis

Hallo liebes Forum,

ich arbeite an einem PHP Programm, was über Kommandozeile, also über PHP-CLI laufen soll, Betriebssystem ist Debian 3.1. Dieses Script enthält eine Endlosschleife, in der es immer wieder eine Tätigkeit durchführt, kurz pausiert und wieder beginnt.

Da dieses Script mit einem Stream rumhantiert, der dauernd geöffnet ist, kommt ein beenden und durch Cronjob wieder neu starten nicht in Frage, zumal das Script auf öfters als einmal die Minute durch die while-Schleife laufen wird.

Nun dachte ich daran, zum Beenden des Scriptes den Linux-Befehl kill zu verweden - geht ja auch problemlos, aber ich würde gerne im PHP Script vorher noch den Stream beenden und alle offenen Dateien schließen, damit keine Lost Handles entstehen.

Gibt es irgendeine Möglichkeit im PHP Script darauf zu reagieren, ob das Script per kill (in irgendeiner Art) aufgefordert wurde sich zu beenden?

Ich weiß, dass ich natürlich eine Datei nehmen könnte, in die ich 1 schreiben könnte, wenn das Script sich beenden und 0, wenn es fortfahren sollte - jedoch würde ich das System nur ungerne mit 20 Dateiaufrufen pro Minute das eventuell rund um die Uhr belasten, deshalb würde ich gerne - sofern möglich - eine vorhandene Methode verwenden.

MfG, Dennis.

  1. Dennis,

    sofern möglich - eine vorhandene Methode verwenden.

    unter Unix kann man trap benutzen
    Mach mal "man trap"

    Grüße

    1. Hi Geplagter,

      unter Unix kann man trap benutzen
      Mach mal "man trap"

      v-10040 /home/driehle # man trap
      No manual entry for trap

      :-(

      Aber:

      v-10040 /home/driehle # tr
      tr              traceroute.lbl  troff           try-from
      traceroute      trap            true
      v-10040 /home/driehle # trap --help
      bash: trap: --: invalid option
      trap: usage: trap [-lp] [arg signal_spec ...]

      Ich habe allerdings hier man trap gefuden, werde mir das mal zu Gemüte führen...

      MfG, Dennis.

  2. Hello Dennis,

    kill ist hier die falsche Entscheidung, denn kill beseitigt den Prozess, der das Script ausführt.

    Für Dein Problem benötigst Du einfach nur eine Runcontrol innerhalb des Scriptes. Die einfachste wäre es, dass das Scripte selber beim Start ein Kontrollfile mit seiner PID als Namen erzeugt, und bei jedem Schleifendurchlauf die Existenz des Files abfragt.

    Wenn Du nun einen Deiner Zombi-Prozesse abschießen willt, dann schaust Du Dir einfach in die Control-Files im entsprechnden Verzeichnis, ob da die passenden Begriffe drinstehen. Bei Treffer löschst Du das Controlfile und Dedin Zombi beendet sich selbst.

    Harzliche Grüße vom Berg
    http://www.annerschbarrich.de

    Tom

    --
    Fortschritt entsteht nur durch die Auseinandersetzung der Kreativen
    Nur selber lernen macht schlau

  3. Hi,

    Gibt es irgendeine Möglichkeit im PHP Script darauf zu reagieren, ob das Script per kill (in irgendeiner Art) aufgefordert wurde sich zu beenden?

    Schau mal nach, ob PHP ein Signalhandling mitbringt. Wenn es auf SIGTERM reagieren kann, ist es kein problem, erst den Stream zu schliessen.
    Allerdings befürchte ist, das der Parser das Signal nicht weiterreicht.

    Wieso baust du in das PHP-Script nicht eine funktion ein, damit du es per Kommandozeile beenden kannst? Es geht ja, einem laufenden Script einen Parameter zu übergeben.

    1. Hello,

      Wieso baust du in das PHP-Script nicht eine funktion ein, damit du es per Kommandozeile beenden kannst? Es geht ja, einem laufenden Script einen Parameter zu übergeben.

      Funktioniert sowas auch unter BlinDoofs?

      Die Änderung von System-Variablen während des Prozesses festzustellen, kann Windows das auch?

      Harzliche Grüße vom Berg
      http://www.annerschbarrich.de

      Tom

      --
      Fortschritt entsteht nur durch die Auseinandersetzung der Kreativen
      Nur selber lernen macht schlau

      1. Hi,

        Die Änderung von System-Variablen während des Prozesses festzustellen, kann Windows das auch?

        keine Ahnung, ich benutze WIndows nur, wenn ich mal ein SPielchen wagen will, also so ca. einmal die Woche ;)

      2. Hallo,

        Wieso baust du in das PHP-Script nicht eine funktion ein, damit du es per Kommandozeile beenden kannst? Es geht ja, einem laufenden Script einen Parameter zu übergeben.

        Funktioniert sowas auch unter BlinDoofs?

        Auch dort müßte stdin zur Verfügung stehen.

        Gruß aus Berlin!
        eddi

    2. Hi Manuel,

      Wieso baust du in das PHP-Script nicht eine funktion ein, damit du es per Kommandozeile beenden kannst? Es geht ja, einem laufenden Script einen Parameter zu übergeben.

      Davon habe ich noch nie etwas gehört - habe aber auch noch nie wirklich mit PHP auf Kommandozeile programmiert ;-) Wie geht das?

      @Tom: Das Script muss ausschließlich unter Linux laufen, ich freue mich also sagen zu können, dass Windoofs mir am A**** vorbei geht *ggg*

      MfG, Dennis.

      1. Hi Dennis,

        Davon habe ich noch nie etwas gehört - habe aber auch noch nie wirklich mit PHP auf Kommandozeile programmiert ;-) Wie geht das?

        Du musst nur den Stream STDIN öffnen und auf ankommende Daten warten. Müsste per fgets() am einfachsten gehen. Mit PHP5muss der Stream, wenn ich richtig gelesen hab, nichtmal geöffnet werden, sondern steht sofort zur Verfügung.

        Das sowas aber nicht sehr performant ist, mach ich sowas nicht, sondern schreib einen schnellen Hack in PERL oder gleich was in C oder C++, je nach Umfang und Anwendungsfall ;)

        1. Hi Manuel,

          Du musst nur den Stream STDIN öffnen und auf ankommende Daten warten. Müsste per fgets() am einfachsten gehen. Mit PHP5muss der Stream, wenn ich richtig gelesen hab, nichtmal geöffnet werden, sondern steht sofort zur Verfügung.

          Ok, dass scheint mir dann auf "Named Pipes" herauszulaufen - dazu habe ich übrigens hier noch einen schönen Artikel zu gefunden. Aber auch wegen der von dir genannten Performance, werde ich das jetzt mit kill machen, da dies einwandfrei läuft ;-)

          MfG, Dennis.

          1. Hi Dennis,

            Ok, dass scheint mir dann auf "Named Pipes" herauszulaufen - dazu habe ich übrigens hier noch einen schönen Artikel zu gefunden.

            Mit diesem Artikel hab ich angefangen, mit FIFOs zu programmeren ;) Der ist echt Gold wert.

        2. Hallo,

          Du musst nur den Stream STDIN öffnen und auf ankommende Daten warten.

          CGI- und auch CLI-Binär haben diesen bei Programmaufruf bereits geöffnet.

          Gruß aus Berlin!
          eddi

          1. Hi,

            CGI- und auch CLI-Binär haben diesen bei Programmaufruf bereits geöffnet.

            Stimmt, nicht erst ab PHP5, wie ich geglaubt hab, sondern auch schon ab  4.3.0, als es das erste mal eine CLI-Version gab ;)

            Offen sind bereits

            STDIN
            STDOUT
            STDERR

    3. echo $begrüßung;

      Schau mal nach, ob PHP ein Signalhandling mitbringt. Wenn es auf SIGTERM reagieren kann, ist es kein problem, erst den Stream zu schliessen.

      Du meinst, er soll sich mal die Process Control Functions und da vielleicht pcntl_signal() ansehen?
      Wenn ich mir die Handbuchseiten so ansehe ... könnte das vielleicht die Lösung sein.

      echo "$verabschiedung $name";

      1. Hello,

        Du meinst, er soll sich mal die Process Control Functions und da vielleicht pcntl_signal() ansehen?
        Wenn ich mir die Handbuchseiten so ansehe ... könnte das vielleicht die Lösung sein.

        Jein.
        Man muss dazu ja wissen, welcher Prozess noch läuft, und das muss irgendwo vermerkt werden.
        Ob das Script dann auf ein "sanftes" Signal reagiert, ist immer noch die Frage. Das müsste schließlich irgendwo abgefrat werden. Zumindest müsste eine shutdown Funktion definiert sein.

        Harzliche Grüße vom Berg
        http://www.annerschbarrich.de

        Tom

        --
        Fortschritt entsteht nur durch die Auseinandersetzung der Kreativen
        Nur selber lernen macht schlau

        1. Hallo,

          Man muss dazu ja wissen, welcher Prozess noch läuft, und das muss irgendwo vermerkt werden.
          Ob das Script dann auf ein "sanftes" Signal reagiert, ist immer noch die Frage. Das müsste schließlich irgendwo abgefrat werden. Zumindest müsste eine shutdown Funktion definiert sein.

          richtig. Wenn man PHP nicht mit den benötigten Bibliotheken kompiliert hat, reicht im simpelsten Fall register_shutdown_function(). ACHTUNG! Man sollte dann aber das Script nicht mit "9" SIGKILL über den Jordan schicken!

          Gruß aus Berlin!
          eddi

          1. Hi eddi,

            Wenn man PHP nicht mit den benötigten Bibliotheken kompiliert hat, reicht im simpelsten Fall register_shutdown_function(). ACHTUNG! Man sollte dann aber das Script nicht mit "9" SIGKILL über den Jordan schicken!

            Ja - aber auf SIGKILL (kill -9) kann ich auch mit pcntl_signal() nicht reagieren, das gibt eine Fehlermeldung des PHP Parsers, hatte ich gestern schon mal ausprobiert.

            MfG, Dennis.

            1. Hallo Dennis,

              Ja - aber auf SIGKILL (kill -9) kann ich auch mit pcntl_signal() nicht reagieren, das gibt eine Fehlermeldung des PHP Parsers, hatte ich gestern schon mal ausprobiert.

              Du kannst auf SIGKILL nichtmal in einem C-Programm reagieren. Der Prozess ist dann einfach weg.

              Viele Grüße,
              Christian

              --
              "I have always wished for my computer to be as easy to use as my telephone; my wish has come true because I can no longer figure out how to use my telephone." - Bjarne Stroustrup
              1. Hi Christian,

                Du kannst auf SIGKILL nichtmal in einem C-Programm reagieren. Der Prozess ist dann einfach weg.

                Was ja auch gut so ist - sonst würde ein "böses Programm"[tm] einfach SIGKILL abfangen, ignorieren und ließe sich dann nicht mehr beenden. Würde man dann als "Windows" bezeichnen ;-)

                MfG, Dennis.

                1. Hello,

                  Du kannst auf SIGKILL nichtmal in einem C-Programm reagieren. Der Prozess ist dann einfach weg.

                  Was ja auch gut so ist - sonst würde ein "böses Programm"[tm] einfach SIGKILL abfangen, ignorieren und ließe sich dann nicht mehr beenden. Würde man dann als "Windows" bezeichnen ;-)

                  Und hier kommt wieder der GateKeeper ins Spiel.
                  Er entscheidet, ob der Prozess abgeschossen werden sll, arbeitet die Filehandles, Speicherhandles, Gatehandles, etc ab. Danach sollten alle Ressourcen des gekillten Prozesses zurückgegeben worden sein. danach können auch die LDT des Prozesses aufgelöst werden.

                  Wen Linux (laut Christian) nur einen eienzigen Gatekeeper kennt (den Kernel), dann ist der eben für diese Überwachungsaufgaben zuständig. Das glaub eich allerdings nicht, denn Linux ist ein intelligentes OS und selbst DOS7 kannte schon Childprozesse, die nicht direkte Untertanen vom DOS-Kernel waren, sondern von Prozessen...

                  Harzliche Grüße vom Berg
                  http://www.annerschbarrich.de

                  Tom

                  --
                  Fortschritt entsteht nur durch die Auseinandersetzung der Kreativen
                  Nur selber lernen macht schlau

                  1. Hallo Tom,

                    Was ja auch gut so ist - sonst würde ein "böses Programm"[tm] einfach SIGKILL abfangen, ignorieren und ließe sich dann nicht mehr beenden. Würde man dann als "Windows" bezeichnen ;-)

                    Und hier kommt wieder der GateKeeper ins Spiel.

                    Durch ständiges Wiederholen von Namen fangen Dinge auch nicht an, zu existieren. *sigh*

                    Er entscheidet, ob der Prozess abgeschossen werden sll, arbeitet die Filehandles, Speicherhandles, Gatehandles, etc ab. Danach sollten alle Ressourcen des gekillten Prozesses zurückgegeben worden sein. danach können auch die LDT des Prozesses aufgelöst werden.

                    Wenn ich mal von den ominösen Gatehandles absehe ist das das, was der Linux-Kernel macht. Und zwar ausschließlich der. Allerdings ist z.B. die Erwähnung der LDT eine komplett x86-spezifische Sache, auf anderne Architekturen setzt Linux das anders um, der Benutzer merkt dennoch keinen Unterschied. Du redest hier also mal wieder auf einer Ebene, die mit der Prozessbehandlung, so wie sie für den User/Programmierer sichtbar ist, so gut wie gar nichts zu tun hat. Ich wiederhole mich: Prozesse/Signale sind unter POSIX eben nicht so Low-Level, wie Du annimmst.

                    Das glaub eich allerdings nicht, denn Linux ist ein intelligentes OS und selbst DOS7 kannte schon Childprozesse, die nicht direkte Untertanen vom DOS-Kernel waren, sondern von Prozessen...

                    Du willst allen Ernstes ein Real-Mode-Betriebsystem (DOS) mit einem Protected-Mode-Betriebsystem (Linux) vergleichen? Naja, wenn Du DOS-Konzepte auf Linux überträgst, ist klar, woher Deine total falschen Vorstellungen kommen.

                    Viele Grüße,
                    Christian

                    --
                    "I have always wished for my computer to be as easy to use as my telephone; my wish has come true because I can no longer figure out how to use my telephone." - Bjarne Stroustrup
      2. Hi dedlfix,

        Du meinst, er soll sich mal die Process Control Functions und da vielleicht pcntl_signal() ansehen?
        Wenn ich mir die Handbuchseiten so ansehe ... könnte das vielleicht die Lösung sein.

        Ich kann nun wirklich nicht sagen, dass es auf Anhieb geklappt hätte (zumal in PHP noch neu kompilieren musste, weil ich kein --enable-pcntl drin hatte), aber jetzt funktioniert es hiermit:

        declare(ticks=1);  
          
        function sig_handler($signo) {  
          switch($signo) {  
            case SIGTERM:  
              echo "You want me to shut down!\nBye.";  
              exit;  
              break;  
            case SIGHUP:  
              echo "SIGHUP";  
              break;  
            default:  
              echo "Hm?";  
          }  
        }  
          
        pcntl_signal(SIGTERM, "sig_handler");  
        pcntl_signal(SIGHUP, "sig_handler");  
          
        while(true) {  
          sleep(1);  
        }
        

        Über kill <PID> lässt sich das ganze dann beenden und es wird die Meldung oben ausgegeben.

        Allerdings geht es nicht ohne das declare, dessen Sinn und Zweck ich noch nicht ganz verstanden habe...

        MfG, Dennis.

        1. Hello,

          Nach X Befehls-Zeilen wird die Abbruchbedingung getestet.

          Wenn Du die Ticks nicht setzt, ist X unendlich.

          Wenn Du X setzt, wird aller X Statements die zugehörige Abbruchbedingung gechecked.

          Harzliche Grüße vom Berg
          http://www.annerschbarrich.de

          Tom

          --
          Fortschritt entsteht nur durch die Auseinandersetzung der Kreativen
          Nur selber lernen macht schlau

          1. Hi Tom,

            Wenn Du X setzt, wird aller X Statements die zugehörige Abbruchbedingung gechecked.

            Ja ok - ich glaube das ist mir jetzt klar geworden.

            Noch eine kleine nachgeschobene Frage: Welches Signal wird an einen Prozess geschickt, der auf der Shell im Vordergrund läuft, wenn man Strg+C drückt?

            Und dann noch: Wie schiebt man noch mal Prozesse in den Hintergrund auf der Shell bzw. wie holt man sie wieder vor? Ich hab das schon wieder vergessen *g*

            MfG, Dennis.

            1. Hello,

              Noch eine kleine nachgeschobene Frage: Welches Signal wird an einen Prozess geschickt, der auf der Shell im Vordergrund läuft, wenn man Strg+C drückt?

              Eigentlich wird nur das Break-Flag gesetzt durch das Ctrl-C, und die Standard-Output-Routine (Input auch? Weiß ich jetzt nicht auswendig) des Prozesses prüft das bei jedem Schleifendurchlauf. Sollte das Flag gestzt sein, wird zum Exit-Handler verzweigt.

              Harzliche Grüße vom Berg
              http://www.annerschbarrich.de

              Tom

              --
              Fortschritt entsteht nur durch die Auseinandersetzung der Kreativen
              Nur selber lernen macht schlau

              1. Hallo Tom,

                Noch eine kleine nachgeschobene Frage: Welches Signal wird an einen Prozess geschickt, der auf der Shell im Vordergrund läuft, wenn man Strg+C drückt?

                Eigentlich wird nur das Break-Flag gesetzt durch das Ctrl-C, und die Standard-Output-Routine (Input auch? Weiß ich jetzt nicht auswendig) des Prozesses prüft das bei jedem Schleifendurchlauf. Sollte das Flag gestzt sein, wird zum Exit-Handler verzweigt.

                Nein. Laut POSIX.1 wird auf Grund der Tastenkombination "Interrupt" das Signal SIGINT ausgelöst - sonst nichts. Das Signal hat die Default-Aktion "Prozess beenden", kann aber überschrieben werden (im Gegensatz zu SIGKILL).

                Allgemein: Was hast Du ständig mit Exit-Handlern? Wenn Du C unter POSIX.1 betrachtest: Wenn exit() aufgerufen wird oder die Main-Methode zurückkehrt, werden alle mit atexit() registrierten Exit-Handler ausgeführt (Reihenfolge ist meines Wissens jedoch nicht garantiert), wenn _exit() aufgerufen wird oder der exit-Syscall, werden die exit-Handler ignoriert und der Prozess instantan beendet. Und die PHP-Exit-Handler, die über register_shutdown_function registriert werden, sind etwas vollkommen anderes.

                Viele Grüße,
                Christian

                --
                "I have always wished for my computer to be as easy to use as my telephone; my wish has come true because I can no longer figure out how to use my telephone." - Bjarne Stroustrup
                1. Hello,

                  ich vermute, dass wir uns in unterschiedlichen Schichten bewegen.

                  Ich bin (das ist doch bekannt) ganz unten ;-))

                  Harzliche Grüße vom Berg
                  http://www.annerschbarrich.de

                  Tom

                  --
                  Fortschritt entsteht nur durch die Auseinandersetzung der Kreativen
                  Nur selber lernen macht schlau

                  1. Hallo Tom,

                    ich vermute, dass wir uns in unterschiedlichen Schichten bewegen.

                    Nein, tun wir nicht. Du bewegst Dich außerhalb von UNIX. Keine Ahnung, bei welchem Betriebsystem das so ist, bei UNIX jedoch nicht.

                    Ich bin (das ist doch bekannt) ganz unten ;-))

                    Es gibt unter UNIX kein "Break-Flag".

                    Viele Grüße,
                    Christian

                    --
                    "I have always wished for my computer to be as easy to use as my telephone; my wish has come true because I can no longer figure out how to use my telephone." - Bjarne Stroustrup
                    1. Hello,

                      Es gibt unter UNIX kein "Break-Flag".

                      Da nennt es sich dann SIGINT. Das wird bei Vordergrundprozessen durch das Abragen des "Break-Flag"
                      ausgelöst. Das Flag wird durch CTRL-C gesetzt. Das bezieht sich auf PCs und kompatible. Ich sagte ja, dass wir über unterschiedliche Schichten reden.

                      Wie es bei anderen Maschinen ist, weiß ich nicht. Die durfte ich noch nicht "auseinandernehmen".

                      Harzliche Grüße vom Berg
                      http://www.annerschbarrich.de

                      Tom

                      --
                      Fortschritt entsteht nur durch die Auseinandersetzung der Kreativen
                      Nur selber lernen macht schlau

                      1. Hello,

                        und fürs Archiv noch ein Link auf Signale ...

                        http://users.actcom.co.il/~choo/lupg/tutorials/signals/signals-programming.html

                        Vielleicht finde ich auch noch einen für die Impelementation in die Hardwareumgebung.
                        Verantwortlich für das Auswerten den "Break-Flag" ist die Shell des Prozesses.

                        Harzliche Grüße vom Berg
                        http://www.annerschbarrich.de

                        Tom

                        --
                        Fortschritt entsteht nur durch die Auseinandersetzung der Kreativen
                        Nur selber lernen macht schlau

                        1. Hallo Tom,

                          Vielleicht finde ich auch noch einen für die Impelementation in die Hardwareumgebung.

                          Versteh doch bitte, dass Signale eben *nicht* so Low-Level sind, wie Du denkst.

                          Verantwortlich für das Auswerten den "Break-Flag" ist die Shell des Prozesses.

                          Nein. Es gibt kein Break-Flag (durch ständigens Wiederholen wird's auch nicht richtiger) und die Shell hat bei SIGINT gar nichts zu melden, das ist nur eine Sache zwischen Terminaltreiber (im Kernel) und Prozess. Wenn der Prozess dann weg ist (d.h. beendet), kriegt die Shell das mit und kommt dann erst wieder ins Spiel. Vorher wartet sie nur auf das Beenden oder Stoppen des Kindprozesses (per wait() oder waitpid()) und macht sonst *gar nichts*.

                          Viele Grüße,
                          Christian

                          --
                          "I have always wished for my computer to be as easy to use as my telephone; my wish has come true because I can no longer figure out how to use my telephone." - Bjarne Stroustrup
                      2. Hallo Tom,

                        Es gibt unter UNIX kein "Break-Flag".

                        Da nennt es sich dann SIGINT.

                        Du widersprichst Dir gerade selbst. Ich zitiere nochmal die Diskussion:

                        Dennis fragte:

                        Noch eine kleine nachgeschobene Frage: Welches Signal wird an einen Prozess geschickt, der auf der Shell im Vordergrund läuft, wenn man Strg+C drückt?

                        Du hast geantwortet:

                        Eigentlich wird nur das Break-Flag gesetzt durch das Ctrl-C, und die Standard-Output-Routine (Input auch? Weiß ich jetzt nicht auswendig) des Prozesses prüft das bei jedem Schleifendurchlauf. Sollte das Flag gestzt sein, wird zum Exit-Handler verzweigt.

                        »Eigentlich wird nur« als direkte Antwort daruaf impliziert, dass kein Signal geschickt wird und Du deutest nun das Signal um in Dein ominöses Break-Flag. Bitte, auf diese Art von Diskussion (ich deute meine vorige Meinung so lange um, bis sie mit der Meinung des Gesprächspartners übereinstimmt) habe ich keine Lust.

                        Das wird bei Vordergrundprozessen durch das Abragen des "Break-Flag" ausgelöst.

                        Nein. Zwar wird Hardwäremäßig bei jeder Tastatureingabe ein Interrupt ausgelöst (wie bei jeder Hardware, die etwas zu melden hat), aber das führt nur dazu, dass der Tastaturtreiber im Kernel den Zeichencode ausliest, *ohne* irgendwelche Break-Flags oder sonstiges zu setzen. Die Eingabe wird dann an den Terminal-Treiber weitergerreicht. Der entscheidet dann, ob's eine normale Sequenz ist, oder eine besondere Sequenz. Bei einer besonderen Sequenz wird die Eingabe *nicht* weitergeleitet, sondern eine bestimmte Aktion ausgeführt. Es gibt diverse besondere Sequenzen. Ob die Sequenz aktiviert ist und welche Zeichenkombination die zugehörige Aktion aufruft, kann jeder Prozess per tcsetattr() einstellen. Bei der Sequenz, die auf VINTR eingetragen ist (per Default ist dies Ctrl+C, das ist aber wie gesagt änderbar) wird SIGINT aufgerufen, falls das ISIG-Flag aktiviert ist - wenn nicht, wird die Sequenz an den Prozess normal als Eingabe weitergeleitet.

                        Du siehst: es gibt kein Break-Flag.

                        Das Flag wird durch CTRL-C gesetzt. Das bezieht sich auf PCs und kompatible.

                        Keine Ahnung, wo Du das her hast, aber unter UNIX stimmt das definitiv nicht.

                        Ich sagte ja, dass wir über unterschiedliche Schichten reden.

                        Nein, Du redest von etwas, das mit Sicherheit nicht einmal annähernd UNIX-kompatibel ist.

                        Viele Grüße,
                        Christian

                        --
                        "I have always wished for my computer to be as easy to use as my telephone; my wish has come true because I can no longer figure out how to use my telephone." - Bjarne Stroustrup
            2. Hallo Dennis,

              Noch eine kleine nachgeschobene Frage: Welches Signal wird an einen Prozess geschickt, der auf der Shell im Vordergrund läuft, wenn man Strg+C drückt?

              SIGINT.

              Und dann noch: Wie schiebt man noch mal Prozesse in den Hintergrund auf der Shell bzw. wie holt man sie wieder vor? Ich hab das schon wieder vergessen *g*

              Ctrl+Z -> Job stoppen

              Auf dem Shell-Prompt:

              bg -> Aktuellen Job in den Hintergrund
              fg -> Aktuellen Job in der Vordergrund
              jobs -> Jobs anzeigen
              bg N -> Job N in den Hintergrund
              fg N -> Job N in den Vordergrund

              Prozess gleich im Hintergrund starten (Achtung: falls der Prozess auf's Terminal was ausgibt kommt er nicht dazu, sondern wird instantan per SIGTTOU gestoppt):

              kommando &

              Viele Grüße,
              Christian

              --
              "I have always wished for my computer to be as easy to use as my telephone; my wish has come true because I can no longer figure out how to use my telephone." - Bjarne Stroustrup
              1. Hi Christian,

                Ctrl+Z -> Job stoppen

                Ok - damit ist das größte Mißverständnis meinerseits geklärt, ich dachte, dass auf der Shell auch Prozesse im Hintergrund _laufen_ könnten, aber anscheinend ist es so, dass Prozesse auf der Shell, die im Hintergrund sind, gestoppt sind und erst wieder weiterlaufen, wenn man sie in den Vordergrund holt.

                bg -> Aktuellen Job in den Hintergrund
                fg -> Aktuellen Job in der Vordergrund
                jobs -> Jobs anzeigen
                bg N -> Job N in den Hintergrund
                fg N -> Job N in den Vordergrund

                Vielen Dank - jetzt kann ich also einen Prozess der im Vordergrund ist und auf Strg+C nur mit einem "Hm?" antwortert mit Strg+Z unterbrechen, mit dann per ps -A die PID holen, kill PID sagen, dann per fg den Job wieder in den Vordergrund holen und sehe, wie er vor meinen Augen stirbt - Feine Sache das ;-)

                Prozess gleich im Hintergrund starten (Achtung: falls der Prozess auf's Terminal was ausgibt kommt er nicht dazu, sondern wird instantan per SIGTTOU gestoppt):

                Theoretische Frage: Kann ein Prozess auf SIGTTOU reagieren? Ich denke doch nein, weil der Prozess da bereits gestoppt wird, oder?

                MfG, Dennis.

                1. Hallo Dennis,

                  Ctrl+Z -> Job stoppen

                  Ok - damit ist das größte Mißverständnis meinerseits geklärt, ich dachte, dass auf der Shell auch Prozesse im Hintergrund _laufen_ könnten, aber anscheinend ist es so, dass Prozesse auf der Shell, die im Hintergrund sind, gestoppt sind und erst wieder weiterlaufen, wenn man sie in den Vordergrund holt.

                  Nein. Prozesse können schon im Hintergrund laufen, Ctrl+Z führt nur zu SIGTSTP, was den Prozess anhält, mit bg kannst Du den Prozess dann in den Hintergrund schicken, wo er auch munter weiterläuft.

                  Nur wenn sie Ausgabe produzieren oder Eingabe erwarten, wird automatisch das Signal SIGTTOU (Ausgabe) oder SIGTTIN (Eingabe) generiert - was die Prozesse sofort beendet. Wobei... Bei mir auf meinem System produziert PHP Ausgabe, obwohl der Prozess im Hintergrund läuft. SIGTTIN greift dagegen (d.h. sobald ein Prozess versucht von der Standardeingabe zu lesen, wird SIGTTIN geschickt). Ist vielleicht irgend ein Flag, das bei mir gesetzt ist...

                  Prozess gleich im Hintergrund starten (Achtung: falls der Prozess auf's Terminal was ausgibt kommt er nicht dazu, sondern wird instantan per SIGTTOU gestoppt):

                  Theoretische Frage: Kann ein Prozess auf SIGTTOU reagieren?

                  Ich denke schon, m.W. sind nur SIGKILL und SIGSTOP nicht abfangbar. (SIGTSTP dagegen schon, was bei Ctrl+Z generiert wird)

                  Ich denke doch nein, weil der Prozess da bereits gestoppt wird, oder?

                  Du überfragst mich gerade. ;-) Vor allem frage ich mich, was nach einem Signalhandler passiert: Wird der Prozess gestoppt oder nicht? Muss ich mal in Ruhe austesten.

                  Viele Grüße,
                  Christian

                  --
                  "I have always wished for my computer to be as easy to use as my telephone; my wish has come true because I can no longer figure out how to use my telephone." - Bjarne Stroustrup
                  1. Hi Christian,

                    Prozesse können schon im Hintergrund laufen, Ctrl+Z führt nur zu SIGTSTP, was den Prozess anhält, mit bg kannst Du den Prozess dann in den Hintergrund schicken, wo er auch munter weiterläuft.

                    Ok - statt anhalten würde ich lieber pausieren sagen, der Prozess wird doch wenn in den BG geschickt dort fortgesetzt, wo er durch SIGTSTP "pausiert" wurde, oder? Egal was der Prozess gerade gemacht hat...

                    Interessant wäre aber noch die Frage, was passiert, wenn ich auf SIGTSTP im Prozess reagiere - ist das lediglich als Möglichkeit für den Programmierer gedacht, z.B. offene Dateien zu schließen, damit diese nicht für die ganze Zeit der Pause gesperrt sind - also: wird der Prozess nach seiner Reaktion auf SIGTSTP zwangsgestoppt oder kann der Prozess ein pausieren "unterdrücken", also nicht ermöglichen?

                    Nur wenn sie Ausgabe produzieren oder Eingabe erwarten, wird automatisch das Signal SIGTTOU (Ausgabe) oder SIGTTIN (Eingabe) generiert - was die Prozesse sofort beendet. Wobei... Bei mir auf meinem System produziert PHP Ausgabe, obwohl der Prozess im Hintergrund läuft. SIGTTIN greift dagegen (d.h. sobald ein Prozess versucht von der Standardeingabe zu lesen, wird SIGTTIN geschickt). Ist vielleicht irgend ein Flag, das bei mir gesetzt ist...

                    Ich habe mal einen PHP Prozess gemacht, welcher über Kommandozeile gestartet wurde, sich dann geforked und von der Shell gelöst hat - verwende ich in dem PHP Prozess dann echo, so wir mir (als eingeloggtem User) auf der Shell die Ausgabe angezeigt, die wird einfach zwischendurch eingeblendet, egal was ich gerade mache (nimmt aber keinen Einfluss auf eventuelle Eingaben von mir).

                    Wobei mir noch nicht ganz klar ist, warum es SIGTSTP, SIGTTIN _und_ SIGTTOU gibt - im Prinzip würde doch ersteres reichen um Prozesse zu stoppen. Oder gibt es das nur, damit eine automatische Erkennung möglich ist, weshalb der Prozess gestoppt ist bzw. was er will?

                    Du überfragst mich gerade. ;-) Vor allem frage ich mich, was nach einem Signalhandler passiert: Wird der Prozess gestoppt oder nicht? Muss ich mal in Ruhe austesten.

                    Vermutlich habe ich dich mit manchen Sachen jetzt wieder überfragt - aber wer weiß, vielleicht liest ja noch jemand anderes mit, der es weiß ;-)

                    MfG, Dennis.

                    1. Hallo Dennis,

                      Ok - statt anhalten würde ich lieber pausieren sagen, der Prozess wird doch wenn in den BG geschickt dort fortgesetzt, wo er durch SIGTSTP "pausiert" wurde, oder? Egal was der Prozess gerade gemacht hat...

                      Ja, genau.

                      Interessant wäre aber noch die Frage, was passiert, wenn ich auf SIGTSTP im Prozess reagiere - ist das lediglich als Möglichkeit für den Programmierer gedacht, z.B. offene Dateien zu schließen, damit diese nicht für die ganze Zeit der Pause gesperrt sind - also: wird der Prozess nach seiner Reaktion auf SIGTSTP zwangsgestoppt oder kann der Prozess ein pausieren "unterdrücken", also nicht ermöglichen?

                      Eine sehr gute Frage, ich würde inzwischen darauf tippen, dass der Prozess bei einem abgefangenem Signal weiterläuft, es sei denn, er schickt sich im Signalhandler selbst SIGSTOP (wenn er nochmal SIGTSTP schicken würde, würde er den Signalhandler bloß wieder aufrufen). Ist aber nur Spekulation meinerseits, ich bin noch nicht dazu gekommen, das näher auszutesten, komme vor dem Wochenende wahrscheinlich auch nicht dazu.

                      Ich habe mal einen PHP Prozess gemacht, welcher über Kommandozeile gestartet wurde, sich dann geforked und von der Shell gelöst hat - verwende ich in dem PHP Prozess dann echo, so wir mir (als eingeloggtem User) auf der Shell die Ausgabe angezeigt, die wird einfach zwischendurch eingeblendet, egal was ich gerade mache (nimmt aber keinen Einfluss auf eventuelle Eingaben von mir).

                      Naja, wenn Du mit »von der Shell gelöst« setsid() meinst, dann ist klar, warum das passiert: setsid() legt eine neue Session und eine neue Prozessgruppe für den Prozess an. Außerdem löst es den Prozess vom Terminal. Es gibt unter UNIX das Konzept des »controlling terminal«. Im Prinzip kann ein Prozess nämlich auf jedes Terminal schreiben, sofern es die entsprechende Device-Datei öffnen kann. stdin/stdout/stderr sind bei Dir also immer noch offen, aber das Terminal hat keine Kontrolle über Deinen Prozess -> es schickt auch keine Signale.

                      Was mich eher gewundert hat, ist, dass mein Testprozess kein SIGTTOU bekommen hat, als ich ihn normal im Hintergrund laufen ließ (d.h. ohne setsid()). Beim Lesen von der Eingabe hat das dagegen funktioniert.

                      Wobei mir noch nicht ganz klar ist, warum es SIGTSTP, SIGTTIN _und_ SIGTTOU gibt - im Prinzip würde doch ersteres reichen um Prozesse zu stoppen. Oder gibt es das nur, damit eine automatische Erkennung möglich ist, weshalb der Prozess gestoppt ist bzw. was er will?

                      Genau, Du willst erkennen können, warum der Prozess gestopt wurde. SIGTSTP wird erzeugt, wenn bei einem Vordergrundprozess Ctrl+Z (oder das, was dafür halt eingestellt ist) gedrückt wird, SIGTTIN/SIGTTOU werden bei Hintergrundprozessen erzeugt.

                      Viele Grüße,
                      Christian

                      --
                      "I have always wished for my computer to be as easy to use as my telephone; my wish has come true because I can no longer figure out how to use my telephone." - Bjarne Stroustrup
                      1. Hallo,

                        Interessant wäre aber noch die Frage, was passiert, wenn ich auf SIGTSTP im Prozess reagiere - ist das lediglich als Möglichkeit für den Programmierer gedacht, z.B. offene Dateien zu schließen, damit diese nicht für die ganze Zeit der Pause gesperrt sind - also: wird der Prozess nach seiner Reaktion auf SIGTSTP zwangsgestoppt oder kann der Prozess ein pausieren "unterdrücken", also nicht ermöglichen?

                        Eine sehr gute Frage, ich würde inzwischen darauf tippen, dass der Prozess bei einem abgefangenem Signal weiterläuft, es sei denn, er schickt sich im Signalhandler selbst SIGSTOP (wenn er nochmal SIGTSTP schicken würde, würde er den Signalhandler bloß wieder aufrufen). Ist aber nur Spekulation meinerseits, ich bin noch nicht dazu gekommen, das näher auszutesten, komme vor dem Wochenende wahrscheinlich auch nicht dazu.

                        declare(ticks = 1);  
                          
                        function handleSignals($signal){  
                           echo "$signal\n";  
                        }  
                        pcntl_signal(SIGTERM,"handleSignals");  
                          
                        for($i=0;$i<5;$i++){  
                           posix_kill(getmypid(),SIGTERM);  
                           sleep(2);  
                        }
                        

                        der Prozess läuft einfach weiter

                        declare(ticks = 1);  
                          
                        function handleSignals($signal){  
                           echo "$signal\n";  
                        }  
                        pcntl_signal(SIGTERM,"handleSignals");  
                        pcntl_signal(SIGTERM,"handleSignals");  
                          
                        for($i=0;$i<5;$i++){  
                           posix_kill(getmypid(),SIGTERM);  
                           sleep(2);  
                        }  
                        for($i=0;$i<5;$i++){  
                           posix_kill(getmypid(),SIGTSTP);  
                           sleep(2);  
                        }
                        

                        hier selbes Bild. PHP-Prozesse werden, wenn ein SignalHandler eingerichtet ist, nicht automatisch gestoppt.

                        Gruß aus Berlin!
                        eddi

                        1. Hallo eddi,

                          hier selbes Bild. PHP-Prozesse werden, wenn ein SignalHandler eingerichtet ist, nicht automatisch gestoppt.

                          Naja, wenn SIGTERM abgefangen wird, wird er natürlich nicht beendet, es ging hier darum, wenn SIGTSTP abgefangen wird, ob er dann nicht hinterher doch noch gestoppt wird - und das wird er aber auch nicht, hab's soeben getestet.

                          Ich habe Dein Beispiel mal erweitert, dass der PHP-Prozess sich automagisch selbst stoppt, sobald SIGTSTP abgefangen wird.

                          <?php  
                            
                          declare(ticks = 1);  
                            
                          function handleSignals($signal){  
                             echo "$signal\n";  
                             if ($signal == SIGTSTP)  
                               posix_kill(getmypid(),SIGSTOP);  
                          }  
                          pcntl_signal(SIGTERM,"handleSignals");  
                          pcntl_signal(SIGTSTP,"handleSignals");  
                            
                          for($i=0;$i<5;$i++){  
                             posix_kill(getmypid(),SIGTERM);  
                             sleep(2);  
                          }  
                          ?>
                          

                          Wenn Du auf UNIX-Plattformen Ctrl+Z drückst, während das läuft, dann wird SIGTSTP abgefangen (sieht man an der Ausgabe), der Prozess wird jedoch hinterher gestoppt, da er sich selbst am Ende des Signalhandlers SIGSTOP schickt.

                          Viele Grüße,
                          Christian

                          --
                          "I have always wished for my computer to be as easy to use as my telephone; my wish has come true because I can no longer figure out how to use my telephone." - Bjarne Stroustrup
                          1. Hi Christian,

                            Danke für die lehrreichen Beispiele - sowohl von dir als auch von eddi

                            Wenn Du auf UNIX-Plattformen Ctrl+Z drückst, während das läuft, dann wird SIGTSTP abgefangen (sieht man an der Ausgabe), der Prozess wird jedoch hinterher gestoppt, da er sich selbst am Ende des Signalhandlers SIGSTOP schickt.

                            Also ist sowohl SIGTSTP als auch SITSTOP dafür gedacht, einen Prozess zu stoppen? Dann frage ich mich mal wieder, warum es da beide Signale gibt - in diesem Fall ist es natürlich praktisch, aber wurde das auch dafür erfunden?

                            Und mit welchem Signal kann ich einen wartenden, also pausierten PHP-Prozess wieder ans Laufen bringen?

                            Dabei stelle ich mir gerade eine Frage: Was ist von der Performance her besser, einen Prozess mit sleep() für X Sekunden schlafen zu legen oder den Prozess zu stoppen und per vorher gesetztem Cronjob bzw. at oder wie das heißt (Befehl zu festgeleger Zeit einmalig ausführen) den Prozess wieder fortzuführen? Kurz um, belastet sleep() den Server?

                            MfG, Dennis.

                            1. Hallo Dennis,

                              Also ist sowohl SIGTSTP als auch SITSTOP dafür gedacht, einen Prozess zu stoppen? Dann frage ich mich mal wieder, warum es da beide Signale gibt - in diesem Fall ist es natürlich praktisch, aber wurde das auch dafür erfunden?

                              SIGTSTP kann abgefangen werden und reagiert, wenn im Terminal Ctrl+Z (oder die halt eingestellte Tastenkombination) gedrückt wird. SIGSTOP wird genauso wie SIGKILL direkt vom Kernel interpretiert und kann dagegen nicht abgefangen werden.

                              Und mit welchem Signal kann ich einen wartenden, also pausierten PHP-Prozess wieder ans Laufen bringen?

                              SIGCONT. Das lässt ihn allerdings im aktuellen Status weiterlaufen, d.h. wenn er vorher im Hintergrund lief, tut er das weiterhin, sonst im Vordergrund. Um einen Prozess in den Hintergrund/Vordergrund zu schieben, braucht's Jobkontrolle - diese Aufgabe übernimmt i.d.R. die Shell, allerdings weiß ich nicht, ob man das mit PHP (oder überhaupt von einem Prozess aus, der nicht Session-Leader ist) auch machen resp. beeinflussen kann - müsste ich mal nachlesen.

                              Dabei stelle ich mir gerade eine Frage: Was ist von der Performance her besser, einen Prozess mit sleep() für X Sekunden schlafen zu legen oder den Prozess zu stoppen und per vorher gesetztem Cronjob bzw. at oder wie das heißt (Befehl zu festgeleger Zeit einmalig ausführen) den Prozess wieder fortzuführen? Kurz um, belastet sleep() den Server?

                              Der Cronjob dürfte "teurer" sein, da dafür ein eigenständiger Prozess erzeugt werden muss. sleep() belastet den Server überhaupt nicht, da der Prozess solange sleep() läuft keine Rechenzeit abbekommt.

                              Viele Grüße,
                              Christian

                              --
                              "I have always wished for my computer to be as easy to use as my telephone; my wish has come true because I can no longer figure out how to use my telephone." - Bjarne Stroustrup
                              1. Hi Christian,

                                SIGTSTP kann abgefangen werden und reagiert, wenn im Terminal Ctrl+Z (oder die halt eingestellte Tastenkombination) gedrückt wird. SIGSTOP wird genauso wie SIGKILL direkt vom Kernel interpretiert und kann dagegen nicht abgefangen werden.

                                Ok, wieder etwas gelernt. Gibt es noch mehr Signale, welche vom Kernel direkt interpretiert werden? Wenn ja, wo finde ich eine Liste mit allen Signalen, wie sie interpretiert werden und für welchen Zweck sie gedacht sind? Von man kill kann ich nicht sagen, dass es mir irgendwie geholfen hätte, aber das kann man an der Stelle ja auch nicht erwarten ;-)

                                SIGCONT [...] müsste ich mal nachlesen.

                                Wenn es dich selber interessiert - bitte. Aber bitte fühle dich jetzt bloß nicht dazu gedrungen, dass für mich nachzulesen ;-) Einerseits kann ich auch selber lesen (*g*), andererseits hast du jetzt wirklich schon ne ganze Menge mir erklärt!

                                Der Cronjob dürfte "teurer" sein, da dafür ein eigenständiger Prozess erzeugt werden muss. sleep() belastet den Server überhaupt nicht, da der Prozess solange sleep() läuft keine Rechenzeit abbekommt.

                                Ok, das bringt die Sache auf den Punkt, also einfach mit sleep() schlafen lassen - machen das große Anwendungen wie der Apache auch so?

                                MfG, Dennis.

                                1. Hallo Dennis,

                                  Ok, wieder etwas gelernt. Gibt es noch mehr Signale, welche vom Kernel direkt interpretiert werden? Wenn ja, wo finde ich eine Liste mit allen Signalen, wie sie interpretiert werden und für welchen Zweck sie gedacht sind? Von man kill kann ich nicht sagen, dass es mir irgendwie geholfen hätte, aber das kann man an der Stelle ja auch nicht erwarten ;-)

                                  In »man 7 signal« findest Du eine Zusammenstellung der Signale, die Dein System unterstützt.

                                  Der Cronjob dürfte "teurer" sein, da dafür ein eigenständiger Prozess erzeugt werden muss. sleep() belastet den Server überhaupt nicht, da der Prozess solange sleep() läuft keine Rechenzeit abbekommt.

                                  Ok, das bringt die Sache auf den Punkt, also einfach mit sleep() schlafen lassen - machen das große Anwendungen wie der Apache auch so?

                                  Nein. Der Apache verwendet wahrscheinlich select() - das wartet nämlich auf Änderungen von Zuständen in Dateideskriptoren oder Socket und legt den Prozess so lange schlafen. PHP bietet eine derartige Funktion auch an: http://de3.php.net/manual/de/function.socket-select.php

                                  Viele Grüße,
                                  Christian

                                  --
                                  "I have always wished for my computer to be as easy to use as my telephone; my wish has come true because I can no longer figure out how to use my telephone." - Bjarne Stroustrup
                      2. Hallo nochmal,

                        Was mich eher gewundert hat, ist, dass mein Testprozess kein SIGTTOU bekommen hat, als ich ihn normal im Hintergrund laufen ließ (d.h. ohne setsid()). Beim Lesen von der Eingabe hat das dagegen funktioniert.

                        Ich habe das jetzt nochmal nachgelesen, mit tcsetattr() muss das Attribut »tostop« aktiviert sein, damit SIGTTOU überhaupt aktiv wird. »tostop« ist bei mir defaultmäßig nicht aktiviert. Leider funktioniert das Abfangen mit SIGTTOU, das bei aktiviertem tostop erzeugt wird, nicht richtig in PHP (hab's getestet) - vmtl. auf Grund der Art und Weise, wie PHP Signalhandler realisiert (nicht vollständig asynchron, wie in C).

                        Daher kann man als Rat nur geben: Weder SIGTTIN noch SIGTTOU sollten mit PHP abgefangen werden. Wenn man sie nicht abfängt, verhält sich PHP ordnungsgemäß, wenn diese Signale kommen.

                        Viele Grüße,
                        Christian

                        --
                        "I have always wished for my computer to be as easy to use as my telephone; my wish has come true because I can no longer figure out how to use my telephone." - Bjarne Stroustrup
          2. Hello,

            Wenn Du X setzt, wird aller X Statements die zugehörige Abbruchbedingung gechecked.

            Du benötigst trotzdem einen EXIT-Handler für alle kritischen Operationen.

            Jedesmal, wenn Du eine kritische Operation beginnst, muss die vorher ihre EXIT-Methode dort anmelden und wenn sie fertig geworden ist, dort auch wieder abmelden. Und wenn Du ein "Kill -9" gibst, wird das alles ignoriert und sofort die Exit-Methode des parent aufgerufen.

            Harzliche Grüße vom Berg
            http://www.annerschbarrich.de

            Tom

            --
            Fortschritt entsteht nur durch die Auseinandersetzung der Kreativen
            Nur selber lernen macht schlau

            1. Hallo Tom,

              Und wenn Du ein "Kill -9" gibst, wird das alles ignoriert und sofort die Exit-Methode des parent aufgerufen.

              Nein. Wenn ein Prozess mit kill -9 gekillt wird, ist er sofort weg, außer, er hängt in einem ungünstigen Systemaufruf fest. Der Parent-Prozess kriegt zwar ordnungsgemäß ein SIGCHLD (oder SIGCHILD - bin jetzt zu faul, nachzuschlagen, welches der beiden POSIX.1 ist), aber das hat nichts mit Exit-Handlern zu tun.

              Viele Grüße,
              Christian

              --
              "I have always wished for my computer to be as easy to use as my telephone; my wish has come true because I can no longer figure out how to use my telephone." - Bjarne Stroustrup
              1. Hello,

                Und wenn Du ein "Kill -9" gibst, wird das alles ignoriert und sofort die Exit-Methode des parent aufgerufen.

                Nein. Wenn ein Prozess mit kill -9 gekillt wird, ist er sofort weg, außer, er hängt in einem ungünstigen Systemaufruf fest. Der Parent-Prozess kriegt zwar ordnungsgemäß ein SIGCHLD (oder SIGCHILD - bin jetzt zu faul, nachzuschlagen, welches der beiden POSIX.1 ist), aber das hat nichts mit Exit-Handlern zu tun.

                So ganz bin ich damit noch nicht einverstanden.
                Wenn Du ein kill -9 gibst, wird die Kontrolle sofort an den übergeordneten Prozess zurückgegeben. Dies kann aber nicht duech den Chlied-Prozess geschehen, denn wenn der außer Kontrolle geraten ist, würde der alles andere machen, aber nicht auf Signale reagieren.

                Das kill -9 kann sich also nur direkt an den Gatekeeper des Childprozesses richten, und der gehört dem Parent.

                Harzliche Grüße vom Berg
                http://www.annerschbarrich.de

                Tom

                --
                Fortschritt entsteht nur durch die Auseinandersetzung der Kreativen
                Nur selber lernen macht schlau

                1. Hallo Tom,

                  Und wenn Du ein "Kill -9" gibst, wird das alles ignoriert und sofort die Exit-Methode des parent aufgerufen.

                  Nein. Wenn ein Prozess mit kill -9 gekillt wird, ist er sofort weg, außer, er hängt in einem ungünstigen Systemaufruf fest. Der Parent-Prozess kriegt zwar ordnungsgemäß ein SIGCHLD (oder SIGCHILD - bin jetzt zu faul, nachzuschlagen, welches der beiden POSIX.1 ist), aber das hat nichts mit Exit-Handlern zu tun.

                  So ganz bin ich damit noch nicht einverstanden.
                  Wenn Du ein kill -9 gibst, wird die Kontrolle sofort an den übergeordneten Prozess zurückgegeben.

                  Nein. Wenn Du kill -9 machst, dann wird der Child-Prozess schlichtweg entfernt. Kontrolle hat immer der Prozess, der gerade durch das präemptive Multitasking dran ist, der Parentprozess kann zwar zufälligerweise direkt danach dran sein, muss aber nicht.

                  Dies kann aber nicht duech den Chlied-Prozess geschehen, denn wenn der außer Kontrolle geraten ist, würde der alles andere machen, aber nicht auf Signale reagieren.

                  Der Prozess bekommt das SIGKILL eh nicht zu gesicht. kill() ist eine Systemfunktion unter UNIX, die 2 Parameter erwartet: Die Prozess-ID und die Signal-Nummer. Diese Systemfunktion wird vom Kernel ausgeführt. Wenn der Kernel ein SIGKILL sieht, dann wird der Prozess ganz einfach restlos entfernt, der Prozess bekommt SIGKILL gar nicht zu Gesicht. Nur die Taskstruktur bleibt erhalten, bis der Parent-Prozess wait() oder waitpid() aufruft, um den Exit-Status des Prozesses zu erhalten.

                  Das kill -9 kann sich also nur direkt an den Gatekeeper des Childprozesses richten, und der gehört dem Parent.

                  Was bitteschön soll ein Gatekeeper sein?

                  Tom, bitte, wenn Du keine Ahnung von UNIX-Systemprogrammierung hast, halte Dich da bitte raus.

                  Viele Grüße,
                  Christian

                  --
                  "I have always wished for my computer to be as easy to use as my telephone; my wish has come true because I can no longer figure out how to use my telephone." - Bjarne Stroustrup
                  1. Hello,

                    Der Prozess bekommt das SIGKILL eh nicht zu gesicht.

                    Das habe ich doch gesagt.

                    kill() ist eine Systemfunktion unter UNIX, die 2 Parameter erwartet: Die Prozess-ID und die Signal-Nummer. Diese Systemfunktion wird vom Kernel ausgeführt. Wenn der Kernel ein SIGKILL sieht, dann wird der Prozess ganz einfach restlos entfernt, der Prozess bekommt SIGKILL gar nicht zu Gesicht. Nur die Taskstruktur bleibt erhalten, bis der Parent-Prozess wait() oder waitpid() aufruft, um den Exit-Status des Prozesses zu erhalten.

                    Hier ging es aber auch um das gezielte "herunterfahren" eines Prozesses.
                    Da Du das ja besser weißt, als ich, wäre es nett, wenn Du uns das mal beschreiben könntest...
                    Also wie kann man (natürlich nicht mit einem (-9), den Prozess gezielt herunterfahren, und wie muss er gebaut sein, damit er das auch mit sich machen lässt?

                    Was bitteschön soll ein Gatekeeper sein?

                    Das ist der Prozess, dem das Gate gehört.
                    Der darf entscheiden, was der abgespaltene Prozess (Child) durch dieses Gate tun darf.

                    Tom, bitte, wenn Du keine Ahnung von UNIX-Systemprogrammierung hast, halte Dich da bitte raus.

                    *holla*

                    Na, dann mach man...

                    Harzliche Grüße vom Berg
                    http://www.annerschbarrich.de

                    Tom

                    --
                    Fortschritt entsteht nur durch die Auseinandersetzung der Kreativen
                    Nur selber lernen macht schlau

                    1. Hallo Tom,

                      Der Prozess bekommt das SIGKILL eh nicht zu gesicht.
                      Das habe ich doch gesagt.

                      Ja, aber da standen noch genügend falsche Setze drum herum.

                      kill() ist eine Systemfunktion unter UNIX, die 2 Parameter erwartet: Die Prozess-ID und die Signal-Nummer. Diese Systemfunktion wird vom Kernel ausgeführt. Wenn der Kernel ein SIGKILL sieht, dann wird der Prozess ganz einfach restlos entfernt, der Prozess bekommt SIGKILL gar nicht zu Gesicht. Nur die Taskstruktur bleibt erhalten, bis der Parent-Prozess wait() oder waitpid() aufruft, um den Exit-Status des Prozesses zu erhalten.

                      Hier ging es aber auch um das gezielte "herunterfahren" eines Prozesses.

                      Du hast doch kill -9 ins Spiel gebracht.

                      Also wie kann man (natürlich nicht mit einem (-9), den Prozess gezielt herunterfahren, und wie muss er gebaut sein, damit er das auch mit sich machen lässt?

                      Du schickst dem Prozess SIGTERM. Der Prozess selbst hat einen Signalhandler für SIGTERM (und evtl. auch SIGINT, falls es ein Vordergrundprozess ist, der durch Ctrl+C abgebrochen werden könnte) eingerichtet und dieser führt dann die ganzen Cleanup-Arbeiten durch. Alternativ könnte der Signalhandler auch exit() aufrufen, damit die ganzen Routinen aufgerufen werden, die per atexit() registriert wurden (falls Du sowas machst). Wenn Du SIGTERM jedoch nicht abfängst und im Signalhandler exit aufrufst, sondern den Prozess durch die Default-Aktion des Signals beenden lässt, werden die atexit()-Funktionen *nicht* aufgerufen.

                      Was bitteschön soll ein Gatekeeper sein?

                      Das ist der Prozess, dem das Gate gehört.

                      Und was soll denn ein Gate [1] bitteschön sein? Selbst wenn es sowas unter andern Betriebsystemen gibt - in POSIX.1 gibt's sowas jedenfalls definitiv nicht.

                      Der darf entscheiden, was der abgespaltene Prozess (Child) durch dieses Gate tun darf.

                      Eine Kontrolle über andere Prozesse ist unter POSIX.1 in dieser Form, wie Du beschreibst, nicht möglich. Ich weiß nicht, woher Du das hast, aber es gibt sowas unter POSIX.1 definitiv nicht.

                      Viele Grüße,
                      Christian

                      [1] Und komme mir bitte nicht mit Hardware-Gates - damit haben Prozesse unter POSIX.1 genau so viel zu tun, wie Quarz mit Schokoriegeln - nämlich gar nichts.

                      --
                      "I have always wished for my computer to be as easy to use as my telephone; my wish has come true because I can no longer figure out how to use my telephone." - Bjarne Stroustrup
                      1. Hi,

                        Was bitteschön soll ein Gatekeeper sein?

                        Er meint vermutlich den Teil der Firmware, das ein GateArray gesteuert hat und somit von aussen auf den Prozessor zugreifen und inh damit beeinflussen konnte.

                        Das war recht gängig auf 8-Bit Heimcomputern mit Z80 Prozessor.

                        Mir ist sowas, genau wie dir, unter POSIX noch nie untergekommen, da es völlig schwachsinnig wäre, eine solche Schicht einzubauen, in der die Hardware das Betriebsystem steuert.

                        1. Hello,

                          Das war recht gängig auf 8-Bit Heimcomputern mit Z80 Prozessor.

                          Ich spreche hier von Intel-Kompatiblen, die im Protected Mode arbeiten.

                          Angeforderte Segmente sind entsprechend zu signieren, für welchen Gebrauch sie bestimmt sind, und wer sie wofür verwenden darf. So lassen sich ganze Applikationen kapseln und gegeneinander abgrenzen. Da das Hardware ist (bzw. Microprogramming des Prozessors), kommt auch ein Linux nicht darum herum, wenn es auf einem Intel laufen soll.

                          Der normale Hochsprachenprogrammierer kommt damit allerdings selten in Berührung, da diese Dinge in den PMIs geregelt werden.

                          Harzliche Grüße vom Berg
                          http://www.annerschbarrich.de

                          Tom

                          --
                          Fortschritt entsteht nur durch die Auseinandersetzung der Kreativen
                          Nur selber lernen macht schlau

                          1. Hallo Tom,

                            Angeforderte Segmente sind entsprechend zu signieren, für welchen Gebrauch sie bestimmt sind, und wer sie wofür verwenden darf. So lassen sich ganze Applikationen kapseln und gegeneinander abgrenzen. Da das Hardware ist (bzw. Microprogramming des Prozessors), kommt auch ein Linux nicht darum herum, wenn es auf einem Intel laufen soll.

                            Und was hat die physikalische Speichertrennung von Prozessen im Protected Mode mit dem Thema zu tun?

                            Viele Grüße,
                            Christian

                            --
                            "I have always wished for my computer to be as easy to use as my telephone; my wish has come true because I can no longer figure out how to use my telephone." - Bjarne Stroustrup
                          2. Hello,

                            Das war recht gängig auf 8-Bit Heimcomputern mit Z80 Prozessor.

                            Ich spreche hier von Intel-Kompatiblen, die im Protected Mode arbeiten.

                            Und was hat das ganze jetzt mit PHP-CLI zu tun? Oder soll man PHP so erweitern, das man per Script auf die unterste Hardwareebene zugreifen kann?

                      2. Hello,

                        [1] Und komme mir bitte nicht mit Hardware-Gates - damit haben Prozesse unter POSIX.1 genau so viel zu tun, wie Quarz mit Schokoriegeln - nämlich gar nichts.

                        Ach, so ein Pech. Schon zu spät.

                        Im Grunde sehe ich aber, dass wir das Gleiche meinen. Leider fehlen mir da tatsächlich die Fachbegriffe für POSIX. Muss ich mal dringend nachholen :-)

                        Jedenfalls kann man einen Prozess nicht geordnet runterfahren, wenn dieser dafür keine Methoden zur Verfügung stellt. Stimmst Du mir da zu?
                        Das war eigentlich der Auslöser der Diskussion.

                        Hab ich wirklich das kill -9 ins Spiel gebracht? Ich dachte, dass das von jemandem anderen stammte *tztz*

                        Harzliche Grüße vom Berg
                        http://www.annerschbarrich.de

                        Tom

                        --
                        Fortschritt entsteht nur durch die Auseinandersetzung der Kreativen
                        Nur selber lernen macht schlau

                        1. Hallo Tom,

                          [1] Und komme mir bitte nicht mit Hardware-Gates - damit haben Prozesse unter POSIX.1 genau so viel zu tun, wie Quarz mit Schokoriegeln - nämlich gar nichts.

                          Ach, so ein Pech. Schon zu spät.

                          Im Grunde sehe ich aber, dass wir das Gleiche meinen. Leider fehlen mir da tatsächlich die Fachbegriffe für POSIX. Muss ich mal dringend nachholen :-)

                          Also ich sehe absolut nicht, dass wir das gleiche meinen. Du hast Gatekeeper in Bezug auf Prozesse ins Spiel gebracht - und wie bereits gesagt: Hardware-Gates und Prozesse sind 2 völlig verschiedene Paar Schuhe.

                          Jedenfalls kann man einen Prozess nicht geordnet runterfahren, wenn dieser dafür keine Methoden zur Verfügung stellt. Stimmst Du mir da zu?

                          Kommt auf Deine Definition von »geordnet« an. Selbst bei kill -9 werden alle Dateideskriptoren geschlossen und der komplette Speicher freigegeben. Aber wenn Du noch andere Dinge machen willst, wie Software-Buffer schreiben, dann brauchst Du natürlich noch Signalbehandlung (was natürlich nur bei anderen Signalen als SIGKILL funktioniert).

                          Viele Grüße,
                          Christian

                          --
                          "I have always wished for my computer to be as easy to use as my telephone; my wish has come true because I can no longer figure out how to use my telephone." - Bjarne Stroustrup
                          1. Hi Christian,

                            Selbst bei kill -9 werden alle Dateideskriptoren geschlossen und der komplette Speicher freigegeben.

                            Das macht das System dann von alleine? File-Locks werden wieder freigegeben und alle geöffneten Dateien geschlossen? Wie sieht das mit einer Datenbank-Verbindung aus, exemplarisch: MySQL? Ich vermute mal, das Socket an sich wird korrekt geschlossen, aber ohne dem DBMS brav "Tschüss" zu sagen, stimmt das?

                            MfG, Dennis.

                            1. Hallo Dennis,

                              Selbst bei kill -9 werden alle Dateideskriptoren geschlossen und der komplette Speicher freigegeben.

                              Das macht das System dann von alleine?

                              Ja. Muss es ja auch, sonst würden ja lauter offene Dateileichen rumliegen, sobald das System länger läuft.

                              File-Locks werden wieder freigegeben und alle geöffneten Dateien geschlossen?

                              Bei den Locks kommt es darauf an. flock-Locks meines Wissens schon, da diese ja beim Schließen der Dateidescriptoren auch wegfallen. Aber sicher bin ich mir da nicht.

                              Wie sieht das mit einer Datenbank-Verbindung aus, exemplarisch: MySQL? Ich vermute mal, das Socket an sich wird korrekt geschlossen, aber ohne dem DBMS brav "Tschüss" zu sagen, stimmt das?

                              Exakt.

                              Viele Grüße,
                              Christian

                              --
                              "I have always wished for my computer to be as easy to use as my telephone; my wish has come true because I can no longer figure out how to use my telephone." - Bjarne Stroustrup
        2. Hallo Dennis,

          Allerdings geht es nicht ohne das declare, dessen Sinn und Zweck ich noch nicht ganz verstanden habe...

          So wie ich das vestanden habe, ist folgendes der Grund:

          UNIX-Signale sind asynchron. D.h. sie können zu einem beliebigen Zeitpunkt ausgeführt werden. Auch, wenn gerade ein Stück C-Code von PHP ausgeführt wird, der "kritisch" ist. Deswegen kann PHP nicht direkt asynchron auf Signale reagieren, da der Zustand des Programms sonst u.U. nicht richtig definiert wäre. Also implementiert PHP Signalbehandlung wohl so, dass im C-Signalhandler, den PHP verwendet, bloß ein Flag gesetzt wird. PHP wird dieses Flag dann regelmäßig auswerten. Diese Auswertung geschieht immer dann, wenn ein Tick vorbei ist, PHP verwendet sozusagen eine interne Tick-Funktion, um Signale zu realisieren. Zu Tick-Funktionen siehe: http://de.php.net/manual/en/control-structures.declare.php#control-structures.declare.ticks

          Das ganze ist jetzt zwar Spekulation, nachdem ich jedoch den Abschnitt über Ticks gelesen habe, dürfte das die einzige sinnvolle Erklärung sein.

          Viele Grüße,
          Christian

          --
          "I have always wished for my computer to be as easy to use as my telephone; my wish has come true because I can no longer figure out how to use my telephone." - Bjarne Stroustrup
          1. Hi Christian,

            UNIX-Signale sind asynchron. D.h. sie können zu einem beliebigen Zeitpunkt ausgeführt werden. Auch, wenn gerade ein Stück C-Code von PHP ausgeführt wird, der "kritisch" ist. Deswegen kann PHP nicht direkt asynchron auf Signale reagieren, da der Zustand des Programms sonst u.U. nicht richtig definiert wäre. Also implementiert PHP Signalbehandlung wohl so, dass im C-Signalhandler, den PHP verwendet, bloß ein Flag gesetzt wird. PHP wird dieses Flag dann regelmäßig auswerten. Diese Auswertung geschieht immer dann, wenn ein Tick vorbei ist, PHP verwendet sozusagen eine interne Tick-Funktion, um Signale zu realisieren. Zu Tick-Funktionen siehe: http://de.php.net/manual/en/control-structures.declare.php#control-structures.declare.ticks

            Sehr schön anschaulich erklärt - hört sich auch sehr logisch an. Es scheint dann aber so zu sein, das Tick normalerweise gar nicht gesetzt ist und also auf Signale von außen gar nicht reagiert wird, wo ich eigentlich keinen wirklichen Sinn drin sehe. Die Frage ist dann, ob tick=1 eventuell beim einem permanentn laufenden PHP-Prozess zu einer zusätzlichen Belastung des Servers führt und ob es eventuell besser wäre, tick=5 oder so zu setzen um PHP da etwas Arbeit zu ersparen...

            MfG, Dennis.

            1. Hallo Denis,

              was genau willst Du eigentlich machen (ich baue auch gerade an verschiedenen, in PHP geschriebenen Dämönichen)?

              Gruß aus Berlin!
              eddi

              1. Hi eddi,

                was genau willst Du eigentlich machen (ich baue auch gerade an verschiedenen, in PHP geschriebenen Dämönichen)?

                Nun, es geht um in diesem Thread angesprochene Bots für ICQ, über welche Leute einer bestimmten Gruppe Informationen abrufen können sollen.

                Dazu soll der ICQ User ständig online sein, Nachrichten empfangen, auswerten und entsprechend antworten.

                MfG, Dennis.

                1. Hi,

                  Nun, es geht um in diesem Thread angesprochene Bots für ICQ, über welche Leute einer bestimmten Gruppe Informationen abrufen können sollen.

                  Hällst du es nicht für riskant, über so so löchriges Protokoll, wie ICQ mit einer, in diesem Fall, zu unsicheren Scriptsprache, wie PHP zu nutzen?
                  Da reicht ja sogar eine 512er (Upload) DSL-Leitung um per DoS deinen Server Lahmzulegen.
                  Natürlich nur, wenn du die Anzahl der Sockets (und damit die Zahl der gleichzeitigen Benutzer) nicht beschränkst.

                  Trotzdem noch ein Tip, falls du das nicht schon kennst. Es gibt bei Sourceforge ein Projekt mit Libs für PHP, damit man verbindungen zu Messengerservern aufbauen kann. Da ist die Zusatzprogramierung dann noch eher marginal ;)

                  1. Hallo;

                    ...zu unsicheren Scriptsprache, wie PHP zu nutzen?

                    <wütend style="kochend">Wie bitte?!</wütend> ;)

                    Spaß beiseite: PHP ist dem durchaus gewachsen.

                    Gruß aus Berlin!
                    eddi

                    1. Hi,

                      Spaß beiseite: PHP ist dem durchaus gewachsen.

                      Das ist mir shcon klar, ich meine ja speziell die Verbindung mit dem ICQ-Protokoll ;)
                      Aber nachdem Dennis sowieso über Jabber arbeitet, dürfte das Risiko ziemloich gering sein.

                      1. Hi Manuel,

                        Das ist mir shcon klar, ich meine ja speziell die Verbindung mit dem ICQ-Protokoll ;)
                        Aber nachdem Dennis sowieso über Jabber arbeitet, dürfte das Risiko ziemloich gering sein.

                        Zumal die einzige Gefahr sein könnte, dass der Server lahm gelegt wird - viel auf dem Server wird man nicht machen können, weil die Bots unter einem eigenen User laufen, der bis auf sein Home-Verzeichnis auf nichts Zugriff hat!

                        MfG, Dennis.

                        1. Hi Dennis,

                          Zumal die einzige Gefahr sein könnte, dass der Server lahm gelegt wird - viel auf dem Server wird man nicht machen können, weil die Bots unter einem eigenen User laufen, der bis auf sein Home-Verzeichnis auf nichts Zugriff hat!

                          Wenn da Kundenseite drauf sind, ist IMO diese Gefahr ausreichend ;)

                          1. Hi Manuel,

                            Wenn da Kundenseite drauf sind, ist IMO diese Gefahr ausreichend ;)

                            Das ist ein virtueller Server unserer Schule und auf dem läuft bis jetzt eigentlich noch kaum etwas ;-)

                            Konkret: Welche Gefahren bestehen für mich?

                            => Einer spammt mich zu, das können die Last auf dem Server erhöhen, weil das Script damit beschäftigt ist all die einkommenden Daten zu lesen, richtig?
                            => Jemand kommt über mein Script irgendwie dazu auf dem Server was zu machen.

                            Für letzteren Fall sollte wie gesagt nicht viel passieren, weil das einen eigenen User-Accounnt hat, der nur auf diese Dateien Zugriff hat. Könnte ich den User auch zusätzlich noch chrooten?

                            Für den ersten Fall: Gibt es unter Linux (Debian 3.1) eine Möglichkeit, dem User maximal 20% des Arbeitsspeichers zur Verfügung zu stellen?

                            MfG, Dennis.

                            1. Hi Dennis,

                              => Einer spammt mich zu, das können die Last auf dem Server erhöhen, weil das Script damit beschäftigt ist all die einkommenden Daten zu lesen, richtig?
                              => Jemand kommt über mein Script irgendwie dazu auf dem Server was zu machen.

                              => DoS-Attacke, die dir den Server und im Extremfall die ganze Netzwerkanbindung lahmlegt, je nachdem, wie gross eure Anbindung ist. Da hilft nur eine Begrenzung der maximal gleichzeitigen Zugriffe.

                              Für den ersten Fall: Gibt es unter Linux (Debian 3.1) eine Möglichkeit, dem User maximal 20% des Arbeitsspeichers zur Verfügung zu stellen?

                              Dann dürfte ulimit dein Freund sein, damit kannst du einzelnen Benutzern bestimmtze Ressourcen zuweisen. Bei Root sieht das bei mir so aus:

                              Pegasus:~# ulimit -a
                              core file size          (blocks, -c) 0
                              data seg size           (kbytes, -d) unlimited
                              file size               (blocks, -f) unlimited
                              pending signals                 (-i) unlimited
                              max locked memory       (kbytes, -l) unlimited
                              max memory size         (kbytes, -m) unlimited
                              open files                      (-n) 1024
                              pipe size            (512 bytes, -p) 8
                              POSIX message queues     (bytes, -q) unlimited
                              stack size              (kbytes, -s) 8192
                              cpu time               (seconds, -t) unlimited
                              max user processes              (-u) unlimited
                              virtual memory          (kbytes, -v) unlimited
                              file locks                      (-x) unlimited

                              1. Hi Manuel,

                                => DoS-Attacke, die dir den Server und im Extremfall die ganze Netzwerkanbindung lahmlegt, je nachdem, wie gross eure Anbindung ist. Da hilft nur eine Begrenzung der maximal gleichzeitigen Zugriffe.

                                Das ist allerdings eine generelle Gefahr und nicht speziell für einzelne Scripte. Die maximale Begrenzung der gleichzeitigen Zugriffe müsste aber wahrscheinlich doch auch schon _vor_ dem V-Server stattfinden, also in irgendeiner Firewall des Providers, oder? Weil wenn die Requests einmal am Server angelangt sind...

                                Für den ersten Fall: Gibt es unter Linux (Debian 3.1) eine Möglichkeit, dem User maximal 20% des Arbeitsspeichers zur Verfügung zu stellen?

                                Dann dürfte ulimit dein Freund sein, damit kannst du einzelnen Benutzern bestimmtze Ressourcen zuweisen. Bei Root sieht das bei mir so aus:

                                Vielen Dank, ich werde mir ulimit mal anschauen - für mich wäre ja vor allem die Eingrenzung von RAM und CPU interessant.

                                MfG, Dennis.

                                1. Hi Dennis,

                                  Das ist allerdings eine generelle Gefahr und nicht speziell für einzelne Scripte.

                                  Allerdings bietet dein Script einen Angriffspunkt, wenn es unendlich viele Sockets zur Verfügung stellt. Wenn man die alle per Script gleichzeitig öffnet, macht dein Server dicht, das meinte ich damit ;)

                                  Gruss
                                  Manuel

                                  1. Hi Manuel,

                                    Allerdings bietet dein Script einen Angriffspunkt, wenn es unendlich viele Sockets zur Verfügung stellt.

                                    Hm, tut es das? Eigentlich sollte die class.jabber.php doch nur _eine_ Verbindung zum Jabber-Server öffnen, über die dann alles reinkommt, oder? Und mein PHP-Script ließt alle 5 Sekunden die eingegangenen Informationen in Arrays und arbeitet sie ab.

                                    MfG, Dennis.

                                    1. Hi Dennis,

                                      Hm, tut es das? Eigentlich sollte die class.jabber.php doch nur _eine_ Verbindung zum Jabber-Server öffnen, über die dann alles reinkommt, oder?

                                      Wenn das Script so funktioniert, ist das natüprlich kein Problem. Ich dachte, dein Script nimmt die Nachrichten vom Client an und schickt die an den Jabber-Server weiter. So wie du das jetzt sagst, ist das Script ja praktisch "nur" ein Client.

                                      In dem Fall hast du die von mir genannten Gefahren natürlich nicht :)

                  2. Hi Manuel,

                    Hällst du es nicht für riskant, über so so löchriges Protokoll, wie ICQ mit einer, in diesem Fall, zu unsicheren Scriptsprache, wie PHP zu nutzen?
                    Da reicht ja sogar eine 512er (Upload) DSL-Leitung um per DoS deinen Server Lahmzulegen.

                    Ich verwende die class.jabber.php - ich nutze also das Chat Protokoll Jabber, welches wiederum eine Verbindung zu ICQ herstellt ;-)

                    Zusammen mit 5 Leuten habe ich für ca. eine Minute mal so viele Nachrichten wie möglich an den Bot geschickt, auf dem Server war keine nennenswerte Belastung zu messen. Die PHP-Klasse speichert einkommende Nachrichten in einem Array, aus welchem ich alle 5 Sekunden auf die älteste Nachricht reagieren (wegen den 5 Sek. siehe auch anderer Thread).

                    MfG, Dennis.

                    1. Hi Dennis,

                      Zusammen mit 5 Leuten habe ich für ca. eine Minute mal so viele Nachrichten wie möglich an den Bot geschickt,

                      Naja, wenn ich mit einem kurzen PERL-Script anfange Nachrichten zu senden, dann ist das wie ca. 10.000 User, die gleichzeitig schreiben ;)
                      Je nach Uploadgeschwindigkeit auch wesentlich mehr.

                      Nicht, das ich irgendwas schlecht machen will, wills nur anmerken.
                      Allerdings schliesst du i ndiesem Punkt shcon einiges aus, wenn du über Jabber arbeitest, da dann der Jabberserver einen Angriff bereits abfangen kann

            2. Hallo Dennis,

              Es scheint dann aber so zu sein, das Tick normalerweise gar nicht gesetzt ist und also auf Signale von außen gar nicht reagiert wird,

              Ja. Bzw. PHP selbst reagiert schon auf Signale, aber der PHP-Code kann damit nichts anfangen.

              wo ich eigentlich keinen wirklichen Sinn drin sehe.

              Naja, Du schreibst ja selbst, dass sowas evtl. eine Belastung ist - und wenn 99% der Leute sowas im Normalfall nicht brauchen, dann verstehe ich schon, dass das per Default deaktiviert ist - es lässt sich ja schließlich einfach aktivieren.

              Die Frage ist dann, ob tick=1 eventuell beim einem permanentn laufenden PHP-Prozess zu einer zusätzlichen Belastung des Servers führt und ob es eventuell besser wäre, tick=5 oder so zu setzen um PHP da etwas Arbeit zu ersparen...

              Du könntest ausprobieren, ob ticks=1 eine starke Belastung ist, oder nicht. Ich kann Dir dazu leider keine Erfahrungswerte geben.

              Viele Grüße,
              Christian

              --
              "I have always wished for my computer to be as easy to use as my telephone; my wish has come true because I can no longer figure out how to use my telephone." - Bjarne Stroustrup
              1. Hi Christian,

                Du könntest ausprobieren, ob ticks=1 eine starke Belastung ist, oder nicht. Ich kann Dir dazu leider keine Erfahrungswerte geben.

                Ich habe jetzt folgendes gemacht: 3 Programme, die in einer While-Endlos-Schleife etwas abgearbeitet und dann immer 5 Sek Pause gemacht haben, gestartet und mit ticks=1 laufen lassen.

                Laut top brauchten jeder der Prozesse jeweils 2.9 bis 3.0% des Memorys, bei CPU stand immer nur 0.0%, die Gesampt-CPU oben links kam auf maximal 3% und dabei laufen auf dem Server ja auch noch ständig SSH, Apache, MySQL usw. mit.

                Für mich hört sich das so an, als ob das noch alles im grünen Bereich wäre...

                MfG, Dennis.

                1. Hallo Dennis,

                  Für mich hört sich das so an, als ob das noch alles im grünen Bereich wäre...

                  Würde ich auch sagen. Aber ich gebe keine Garantien! ;-)

                  Viele Grüße,
                  Christian

                  --
                  "I have always wished for my computer to be as easy to use as my telephone; my wish has come true because I can no longer figure out how to use my telephone." - Bjarne Stroustrup
                  1. Hi Christian,

                    Würde ich auch sagen. Aber ich gebe keine Garantien! ;-)

                    Hm, vielleicht kann man ja vorbeugen?

                    MfG, Dennis.

  4. Hi again,

    Mittlerweile bin ich soweit, dass ich den Prozess forke und eigenständig laufen lasse:

    $pid = pcntl_fork();  
    if($pid == -1) {  
      echo "Could not fork, exit.\n";  
      exit;  
    }  
    elseif($pid) {  
      echo "Jabber Bot forked, its PID is $pid.\n";  
      exit;  
    }  
    else {  
      // we are the child  
    }  
      
    if(!posix_setsid()) {  
      echo "Could not detach from terminal, exit.\n";  
      exit;  
    }
    

    Das läuft soweit auch prima, der Prozess wird auf der Kommandozeile gestartet, spaltet sich ab und dann läuft "im Hintergrund", also so das ich es nicht sehe das Programm an sich weiter - soweit alles gut.

    Doch was genau bringt mir das posix_setid()? Das PHP Manual ist sehr spärlich was das anbelangt und die man Seite hilft mir auch nicht wirklich weiter.

    Wenn ich das richtig verstehe, soll der Prozess ja von der Shell gelöst werden - doch was heißt gelöst? Unter gelöst würde ich verstehen, dass der Prozess nichts mehr auf der Kommandozeile ausgibt, und doch tut er genau das, wenn ich ihn per kill <PID> abschieße und die Shutdown-Routine (welche ein paar echo's enthält) ausgeführt wird.

    MfG, Dennis.

    1. Hi Ingrid,

      Doch was genau bringt mir das posix_setid()?

      Ok - mein Fehler, ich habe mich verguckt ;-) Ich dachte vorher, in beiden Fällen, also sowohl bei der Verwendung von posix_setid() als auch beim Verzicht darauf, hätte bei ps -A unter TTY ein "?" gestanden, da habe ich mich aber wohl geguckt.

      Also: Bei der Verwendung von posix_setid() wird der Prozess von der Shell gelöst, bei TTY steht dann "?", verwendet man kein posix_setid(), so steht unter TTY pts/0, oder eben das, wo man gerade angemeldet ist und der Prozess ist damit an die Shell gebunden.

      MfG, Dennis.

  5. Hallo liebes Forum,

    Ich habe ein PHP-Script was über Kommandozeile läuft, eigentlich ist es dreimal dasselbe Script. Nun ist mir aufgefallen, dass die Speicherauslastung pro Script 2,9% des RAMs beträgt.

    Deshalb überlege ich mir, ob ich das irgendwie optimieren kann. Zuerst habe ich folgendes ausprobiert: Ein PHP Script erstellt, welches nur in einer Endlosschleife sleep(10) verwendet hat, und siehe da - alleine das sind schon 2,9% des RAMs.

    Also scheint PHP soviel Overhead mitzubringen. Kann ich das irgendwie optimieren, indem ich einen Kern-PHP-Prozess mache, der sich dann dreimal forked? Wie auch immer? Oder bringt das nichts/kann das nichts bringen?

    MfG, Dennis.

    1. Hallo Dennis,

      Deshalb überlege ich mir, ob ich das irgendwie optimieren kann. Zuerst habe ich folgendes ausprobiert: Ein PHP Script erstellt, welches nur in einer Endlosschleife sleep(10) verwendet hat, und siehe da - alleine das sind schon 2,9% des RAMs.

      Tja, dann kommt der Overhead von PHP. Du könntest Dir ein PHP-Binary kompilieren, das ausschließlich die Extensions enthält, die Du wirklich brauchst, dann wäre der Overhead natürlich geringer. Oder Du könntest die Extensions als Shared Libraries kompilieren (gibt irgend so eine configure-Option bei PHP, unter Gentoo kannst Du, falls Du dev-lang/php als Ebuild verwendest, das USE-Flag »sharedext« setzen), dann würden sie nur einmal geladen werden, auch wenn multiple PHP-Prozesse laufen.

      Und dann wäre noch die Frage zu klären, wie viel denn 2,9% tatsächlich sind. Wenn Du 128 MiB RAM hast, dann sind 2,9% 3.71 MiB - was IMHO noch vertretbar wäre. Bei 1 GiB RAM wären es dagegen schon 29,7 MiB - was dann doch etwas viel wäre.

      Also scheint PHP soviel Overhead mitzubringen. Kann ich das irgendwie optimieren, indem ich einen Kern-PHP-Prozess mache, der sich dann dreimal forked? Wie auch immer? Oder bringt das nichts/kann das nichts bringen?

      Wenn Du das PHP-Script dreimal fork()st, dann ist das von der Speicherbelastung her genauso, als ob Du drei separate Prozesse starten würdest. Bei fork() wird der komplette Speicher des Prozesses einfach kopiert (naja, genaugenommen wird er das aus Performancegründen erst beim erste Schreibzugriff des Kindprozesses auf den Speicher, sog. »copy-on-write«, aber da Du ja den Prozess nicht sofort mit exec() überschreibst nach dem fork(), wird der Speicher bei Dir auf jeden Fall kopiert werden).

      Viele Grüße,
      Christian

      --
      "I have always wished for my computer to be as easy to use as my telephone; my wish has come true because I can no longer figure out how to use my telephone." - Bjarne Stroustrup
      1. Hi Christian,

        Tja, dann kommt der Overhead von PHP. Du könntest Dir ein PHP-Binary kompilieren, das ausschließlich die Extensions enthält, die Du wirklich brauchst, dann wäre der Overhead natürlich geringer. Oder Du könntest die Extensions als Shared Libraries kompilieren (gibt irgend so eine configure-Option bei PHP, unter Gentoo kannst Du, falls Du dev-lang/php als Ebuild verwendest, das USE-Flag »sharedext« setzen), dann würden sie nur einmal geladen werden, auch wenn multiple PHP-Prozesse laufen.

        Hört sich interessant an - ich verwende Debian 3.1, dazu habe ich PHP (aus diversen Gründen) selbst kompiliert und habe dabei immer --with-xyz=shared angegeben, das wird dann in so Extensions kompiliert wie beim Apache es auch die Module gibt, man kann die dann einzeln laden. Hinzu kamen noch ein paar Sachen mit --enable-xyz, wo ich nicht wusste, wie ich die shared machen kann, sodass diese also fest einkompiliert sind.

        Jetzt wollte ich hingehen und eine andere php.ini verwenden, in der alle nicht benötigten Extensions nicht geladen werden, ich habe die php.ini angelegt und wollte folgende Shebang verwenden:

        #!/usr/local/bin/php5 -c /absoluter/pfad/zur/php.ini

        In der php.ini habe ich den IncludePath entsprechend gesetzt, sodass ich eine Datei einfach per include("datei") einbinden kann. Allerdings scheint PHP _nicht_ diese php.ini zu verwenden, was ich daran erkenne, dass der Include-Befehl fehlschlägt mit der Fehlermeldung dass die Datei nicht gefunden wurde. Dabei gibt PHP in der Fehlermeldung ja auch den Include-Path aus, dieser ist aber ganz anders als der aus der php.ini und auch anders als der aus der normalen php.ini - was mich glauben macht, PHP verendet gar keine php.ini in diesem Fall.

        Nächster Schritt was dann, dass ich hingegangen bin und selber auf die php.ini verzichtet habe, die Pfade für die Includes vollständig ins Script geschrieben habe und diese Shebang verwendet habe:

        #!/usr/local/bin/php5 -n

        Allerdings will mir das nicht ganz gefallen, da ich hier keine Einstellungen für PHP mehr vorgeben kann! Geht das vielleicht nicht doch irgendwie auf die erste Art und Weise?

        Erfolg hats auf jeden Fall gebracht, der laufende PHP-Prozess brauchte nur noch 1.7% bis 1.8% des RAMs - also deutlich weniger. Ich mache mir aber auch immer noch Gedanken darüber, ob man für einen User auf dem System die maximale Menge an RAM einschränken kann...

        Und dann wäre noch die Frage zu klären, wie viel denn 2,9% tatsächlich sind. Wenn Du 128 MiB RAM hast, dann sind 2,9% 3.71 MiB - was IMHO noch vertretbar wäre. Bei 1 GiB RAM wären es dagegen schon 29,7 MiB - was dann doch etwas viel wäre.

        Laut top:
          Mem:    257044k total,   251060k used,     5984k free,    66932k buffers
          Swap:   524280k total,       44k used,   524236k free,    68836k cached
        Wären also 251 MB.[1] Ist das eigentlich nich ein gutes Zeichen, wenn der Swap-Bereich noch so gut wie gar nicht genutzt wird?

        Bei 251MB wären das also 7,3MB - eigentlich schon etwas viel. Ohne die geladenen Erweiterungen waren es ja nur noch 1,7%, was nur noch 4,3MB wären - schon deutlich besser.

        Wenn Du das PHP-Script dreimal fork()st, dann ist das von der Speicherbelastung her genauso, als ob Du drei separate Prozesse starten würdest.

        Ok - ich hatte gedacht/gehofft, es wäre möglich, einen PHP-Prozess laufen zu lassen, der von drei Scripte genutzt wird.

        MfG, Dennis.

        [1] Du wunderst dich über die krumme Zahl und warum ich die Zahl nicht aus einem Vertrag oder so weiß? Nun, recht einfache Sache - es handelt sich ja um den VServer unserer Schule und unser Provider Intertech fördert uns da auch ein bisschen, wir kriegen halt so was wir brauchen, so in etwa ;-)

        1. Hallo,

          Hört sich interessant an - ich verwende Debian 3.1, dazu habe ich PHP (aus diversen Gründen) selbst kompiliert und habe dabei immer --with-xyz=shared angegeben, das wird dann in so Extensions kompiliert wie beim Apache es auch die Module gibt, man kann die dann einzeln laden. Hinzu kamen noch ein paar Sachen mit --enable-xyz, wo ich nicht wusste, wie ich die shared machen kann, sodass diese also fest einkompiliert sind.

          Du kannst Dir alle Erweiterugnen nachträglich aus den Sourcen bauen. In Deinem Fall wäre wahrscheinlich folgendes zielführend:

          $ EXTENSION_DIR="/dein/pfad/zur/den/Modulen" \ INCLUDE_PATH="/vorkonfigurierter/includepfad:." \ CFLAGS="-O3 -march=athlon-xp -fomit-frame-pointer -pipe" \ ./configure \ --prefix=/usr/local/bin/php5 \ --disable-all \ --disable-cgi \ --weitere-parameter

          $ make && make install

          $ cd ext/pcntl
          $ /usr/local/bin/php5/phpize
          $ CFLAGS="-O3 -march=athlon-xp -fomit-frame-pointer -pipe" \ ./configure --with-php-config=/usr/local/bin/php5/php-config

          $ make && make install

          Somit hättest Du dann unter "/dein/pfad/zur/den/Modulen" die pcntl.so.

          Jetzt wollte ich hingehen und eine andere php.ini verwenden, in der alle nicht benötigten Extensions nicht geladen werden, ich habe die php.ini angelegt und wollte folgende Shebang verwenden:

          #!/usr/local/bin/php5 -c /absoluter/pfad/zur/php.ini

          Das Problem kenne ich und es läßt sich leider nicht ändern.

          Erfolg hats auf jeden Fall gebracht, der laufende PHP-Prozess brauchte nur noch 1.7% bis 1.8% des RAMs - also deutlich weniger. Ich mache mir aber auch immer noch Gedanken darüber, ob man für einen User auf dem System die maximale Menge an RAM einschränken kann...

          Rufe Dein script bitte mal mit folgendem auf:

          $ env -i ./script.name

          Gruß aus Berlin!
          eddi

          1. Hi eddi,

            $ EXTENSION_DIR="/dein/pfad/zur/den/Modulen" \ INCLUDE_PATH="/vorkonfigurierter/includepfad:." \ CFLAGS="-O3 -march=athlon-xp -fomit-frame-pointer -pipe" \ ./configure \ --prefix=/usr/local/bin/php5 \ --disable-all \ --disable-cgi \ --weitere-parameter

            $ make && make install

            $ cd ext/pcntl
            $ /usr/local/bin/php5/phpize
            $ CFLAGS="-O3 -march=athlon-xp -fomit-frame-pointer -pipe" \ ./configure --with-php-config=/usr/local/bin/php5/php-config

            $ make && make install

            Ok - also zuerst PHP kompilieren, aufgrund von --disable-all ohne sämtliches Zeug, damit die Minimal-Version von PHP und anschließend aus den Sourcen noch die Extensions - werden da dann _alle_ Extension kompiliert? Ich sehe nämlich nirgendwo eine Angabe, welche Extensions denn jetzt zu kompilieren sind und welche nicht...

            Vermutlich wird das aber darauf hinauslaufen, dass ich eine eigene PHP-Version für diese Spielerei installiere, da kann ich dann alles so anpassen wie ich will.

            Übrigens ist /usr/local/bin/php5 kein Ordner bei mir ;-) Das ist schon die ausführbare Datei, die Sourcen habe ich unter /usr/src/php/php-5.0.5/ abgelegt.

            Leider komme ich jetzt nicht mehr dazu das auszuprobieren, da ich gleich auf den Zug muss - ich weiß noch nicht genau, ob ich die nächsten Tage Internet haben werde, wenn dann nur seeehr laaangssamm *g* Ich werde mir das aber merken und dann spätestens nächsten Montag ausprobieren.

            Rufe Dein script bitte mal mit folgendem auf:

            $ env -i ./script.name

            -i, --ignore-environment   start with an empty environment

            Mit einer leeren Umgebung starten - was bewirkt das? Was auch immer das bewirkt, bewirkt es das auch für den Prozess, den PHP geforked hat?

            MfG, Dennis.

            1. Re:

              Ok - also zuerst PHP kompilieren, aufgrund von --disable-all ohne sämtliches Zeug, damit die Minimal-Version von PHP und anschließend aus den Sourcen noch die Extensions - werden da dann _alle_ Extension kompiliert?

              $ cd /usr/src/php/php-5.0.5/ext
              $ ls

              jedes Verzeichnis beheimatet eine Erweiterung ;)

              Rufe Dein script bitte mal mit folgendem auf:

              $ env -i ./script.name

              -i, --ignore-environment   start with an empty environment

              Das bewirkt, das die Variabeln $_ENV und $_SERVER nicht mit Umgebungsvariablen der Shell zugetextet werden (wieder etwas RAM eingespart).

              Gruß aus Berlin!
              eddi

              1. Hi eddi,

                Das bewirkt, das die Variabeln $_ENV und $_SERVER nicht mit Umgebungsvariablen der Shell zugetextet werden (wieder etwas RAM eingespart).

                Ist das denn so viel, dass es sich lohnt? Und bleiben die PHP-Variablen aus $_SERVER davon unberührt?

                MfG, Dennis.

                1. Hallo,

                  Das bewirkt, das die Variabeln $_ENV und $_SERVER nicht mit Umgebungsvariablen der Shell zugetextet werden (wieder etwas RAM eingespart).

                  Ist das denn so viel, dass es sich lohnt? Und bleiben die PHP-Variablen aus $_SERVER davon unberührt?

                  jain. (Ich bin davon ausgegangen, daß Du Version 4.X nutzt. Dabei tritt ein deutlicher Geschwindigkeitszuwachs [ca. 20%] auf, wenn nur das nötigste an Variablen gesetzt wird.) Bei Version 5.X ist dort kein Unterschied, den solange die Superglobalens nicht angefast werden, werden sie auch nicht befüllt.

                  Gruß aus Berlin!
                  eddi

                  1. Hi eddi,

                    Bei Version 5.X ist dort kein Unterschied, den solange die Superglobalens nicht angefast werden, werden sie auch nicht befüllt.

                    Das heißt PHP befüllt die Variablen erst, wenn ich im Script darauf zugreife?

                    MfG, Dennis.

                    1. Re:

                      Bei Version 5.X ist dort kein Unterschied, den solange die Superglobalens nicht angefast werden, werden sie auch nicht befüllt.

                      Das heißt PHP befüllt die Variablen erst, wenn ich im Script darauf zugreife?

                      Ja!

                      Gruß aus Berlin!
                      eddi

      2. Hi,

        Wenn Du das PHP-Script dreimal fork()st, dann ist das von der Speicherbelastung her genauso, als ob Du drei separate Prozesse starten würdest. Bei fork() wird der komplette Speicher des Prozesses einfach kopiert

        Gibt es unter PHP sowas wie p_thread unter C? Dann dürfte das etwas Speicherfreundlicher sein. Ich hab allerdings Null Erfahrung mit Threads unter PHP, da ist solche Anwendungen immer in C/C++ programmiere ;)

        1. Hallo,

          Gibt es unter PHP sowas wie p_thread unter C? Dann dürfte das etwas Speicherfreundlicher sein. Ich hab allerdings Null Erfahrung mit Threads unter PHP, da ist solche Anwendungen immer in C/C++ programmiere ;)

          da träume ich schon seit Jahren von!!!11ELF
          Threads gibts leider leider nicht in PHP.

          Gruß aus Berlin!
          eddi

  6. Hallo liebes Forum,

    Ich habe noch ein weiteres Problem - gegeben sei folgendes PHP-Script:

    $pid = pcntl_fork();  
    if($pid == -1) {  
      echo "Could not fork, exit.\n";  
      exit;  
    }  
    elseif($pid) {  
      echo "Jabber Bot forked, its PID is $pid.\n";  
      exit;  
    }  
    elseif(!posix_setsid()) {  
      echo "Could not detach from terminal, exit.\n";  
      exit;  
    }
    

    Dieses Script macht anschließend noch ein paar Sachen, die einige Zeit benötigen.

    Nun möchte ich dieses Script über einen Webaufruf starten, dazu verwende ich im PHP-Script was über das Web aufgerufen wird folgenden Befehl:

    shell_exec("./pfad/zum/script");

    Ich habe auch schon exec(), passthru() oder den Backtick-Operator probiert, ebenso habe ich schon probiert, an den Prozess noch ein & anzuhängen, um ihn als Hintergrundprozess zu starten - trotzdem will PHP warten bis das Script zu Ende durchgeführt ist, sodass die Seite im Browser nicht weiterlädt.

    Was kann ich machen? Ich dachte eigentlich durch das forken würde das obige PHP-Script als ein anderer, eigenständiger Prozess weiterlaufen und dadurch nicht mehr unter der Kontrolle von PHP laufen und PHP würde die Website dann weiter ausliefern.

    Tja, hab ich mich wohl getäuscht ;-) Doch wie lässt sich das Problem umgehen?

    MfG, Dennis.

    1. Hallo,

      das Problem hatte ich auch mal und glaube es mit proc_open() gelöst zu haben. Setze als STDIN den Pfad zum Script.

      Gruß aus Berlin!
      eddi

    2. Hallo Dennis,

      shell_exec("./pfad/zum/script");

      Ich habe auch schon exec(), passthru() oder den Backtick-Operator probiert, ebenso habe ich schon probiert, an den Prozess noch ein & anzuhängen, um ihn als Hintergrundprozess zu starten - trotzdem will PHP warten bis das Script zu Ende durchgeführt ist, sodass die Seite im Browser nicht weiterlädt.

      Was kann ich machen?

      Habe ich richtig verstanden?

      Du hast 1) ein PHP-Script, das vom Web aus aufgerufen wird und 2) ein PHP-Script, das den obigen fork()-Code enthält? Und 1) ruft 2) per shell_exec auf?

      Naja, wenn PHP fork() wirklich 1:1 umsetzt, dann kann (außer PHP stracet den Kindprozess, was ich mir nicht vorstellen kann) IMHO eigentlich der einzige Grund, warum PHP trotzdem auf den geforkten Prozess wartet, der sein, dass der geforkte Prozess noch Dateideskriptoren offen hat. Versuch mal (ist ein Schuss ins Blaue, ich hab keine Ahnung ob's a) wirklich dran liegt und b) ob das dann auch tatsächlich funktioniert, selbst wenn's dran liegt) die 3 Standard-Dateideskriptoren zu schließen, d.h. fclose(STDIN); fclose(STDOUT); fclose(STDERR); Vielleicht geht's ja.

      Viele Grüße,
      Christian

      --
      "I have always wished for my computer to be as easy to use as my telephone; my wish has come true because I can no longer figure out how to use my telephone." - Bjarne Stroustrup
      1. Hi Christian,

        Versuch mal [...] die 3 Standard-Dateideskriptoren zu schließen, d.h. fclose(STDIN); fclose(STDOUT); fclose(STDERR); Vielleicht geht's ja.

        Wow, gut geraten ;-) Ich habe jetzt die drei Standard-Dateideskriptoren nach dem forken im Child-Prozess geschlossen und siehe da, folgender PHP-Code:

        echo exec("./jabber-bot1.php");

        führt zur Ausgabe dessen, was der Parent-Prozess ausgibt, bevor er sich per exit() beendet, während der Child-Prozess dann noch weiterläuft und die Seite fertig geladen wird.

        Allerdings ist mir folgendes in der Prozessliste aufgefallen:

        21555 ?        00:00:00 php5-cgi <defunct>
          21560 ?        00:00:00 jabber-bot1.php

        Was heißt dieses <defunct> und warum ist da immer noch ein php5-cgi (das ist das PHP-Programm was für die Ausführung von PHP-Scripten in Webseiten zuständig ist bei mir) am laufen? Kann ich auch das irgendwie noch loswerden?

        MfG, Dennis.

        1. Hallo Dennis,

          Wow, gut geraten ;-)

          *hehe*

          Allerdings ist mir folgendes in der Prozessliste aufgefallen:

          21555 ?        00:00:00 php5-cgi <defunct>
            21560 ?        00:00:00 jabber-bot1.php

          Was heißt dieses <defunct>

          Das <defunct> heißt, dass der Prozess ein Zombie ist (wenn Du »ps x« aufrufen würdest hättest Du als Status »Z« statt z.B. »S«, »D« oder »R«. Zombie heißt, dass die Taskstruktur im Kernel noch da ist, der Prozess selbst (und damit auch seine Resourcen) jedoch schon beendet. Normalerweise entsorgt der Kernel die Taskstruktur so bald wie möglich - allerings erst, wenn der Elternprozess den Exit-Status abgefragt hat. Tut der Elternprozess dies nicht, bleibt die Taskstruktur erhalten, bis der Elternprozess dies tut. Die Quizfrage wäre jetzt, welcher Prozess ist der Elternprozess von 21555? Mach mal:

          grep ppid /proc/21555/status

          Damit kriegst Du die Parent-PID raus. Dann gibst Du

          ps PARENTPID

          (PARENTPID ersetzen) ein und weißt dann, welcher Prozess das ist. Dann können wir nämlich weitersehen.

          Viele Grüße,
          Christian

          --
          "I have always wished for my computer to be as easy to use as my telephone; my wish has come true because I can no longer figure out how to use my telephone." - Bjarne Stroustrup
          1. Hallo nochmal,

            grep ppid /proc/21555/status

            Sorry, grep ist ja case sensitive, also:

            grep -i ppid /proc/21555/status

            Viele Grüße,
            Christian

            --
            "I have always wished for my computer to be as easy to use as my telephone; my wish has come true because I can no longer figure out how to use my telephone." - Bjarne Stroustrup
            1. Hi Christian,

              grep -i ppid /proc/21555/status

              Ich habs mal gemacht, es scheint der Apache zu sein:

              go-vpsys@v-10040 ~ $ ps -A
              [...]
              29041 ?        00:00:00 php5-cgi <defunct>
              29050 ?        00:00:00 jabber-bot1.php
              [...]
              go-vpsys@v-10040 ~ $ grep -i ppid /proc/29041/status
              PPid:   19475
              go-vpsys@v-10040 ~ $ ps -A | grep 19475
              19475 ?        00:00:01 apache2

              Allerdings habe ich gesehen, dass dieser php5-cgi Prozess nach einer Weile von alleine verschwindet (Zeitspanne > 1 Min.). Der Apache scheint sich also schon selber darum zu kümmern, nur wohl nicht schnell genug für mein Empfinden ;-)

              Na ja, ist aber wohl auch nur ein Schönheitsfehler...

              MfG, Dennis.

              1. Hallo Dennis,

                Ich habs mal gemacht, es scheint der Apache zu sein:

                Dann hat der Zombie aber nichts mit dem, was Du anstellst, zu tun, sofern PHP wirklich als CGI läuft. Der Apache räumt halt anscheinend nicht sofort auf, sondern erst später. Ich würde mir da keine Gedanken machen, eine Minute würde ich definitiv nicht als kritisch ansehen.

                Viele Grüße,
                Christian

                --
                "I have always wished for my computer to be as easy to use as my telephone; my wish has come true because I can no longer figure out how to use my telephone." - Bjarne Stroustrup
                1. Hi Christian,

                  Dann hat der Zombie aber nichts mit dem, was Du anstellst, zu tun, sofern PHP wirklich als CGI läuft. Der Apache räumt halt anscheinend nicht sofort auf, sondern erst später. Ich würde mir da keine Gedanken machen, eine Minute würde ich definitiv nicht als kritisch ansehen.

                  Ich hab jetzt nicht die Zeit gestoppt oder so, mir ist halt nur aufgefallen, dass der nach einer Minute immer noch da war ;-) Und ja, PHP läuft als CGI - als Modul scheidet aus, weil zwei PHP-Versionen zum Einsatz kommen (müssen) und als FastCGI habe ich noch nicht wirklich hinbekommen, ich glaube es gibt auch noch kein FastCGI-Modul für Apache 2.2.

                  Aber wo wir gerade bei Apache Modulen sind - erinnerst du dich noch an meinen Versuch mod_auth_pam unter Apache 2.2 ans laufen zu bekommen? Ich meine doch, das wärst auch du gewesen, der mir damals geholfen hatte ;-) Jedenfalls hatten wir es damals ja aufgegeben und es auf Inkompatibilitäten zwischen 2.0 und 2.2 beruhen lassen - jedoch lässt sich der unveränderte SourceCode nutzen, man muss lediglich noch eine Kleinigkeit machen.

                  MfG, Dennis.

                  1. Hi Ingrid,

                    Aber wo wir gerade bei Apache Modulen sind - erinnerst du dich noch an meinen Versuch mod_auth_pam unter Apache 2.2 ans laufen zu bekommen? Ich meine doch, das wärst auch du gewesen, der mir damals geholfen hatte ;-) Jedenfalls hatten wir es damals ja aufgegeben und es auf Inkompatibilitäten zwischen 2.0 und 2.2 beruhen lassen - jedoch lässt sich der unveränderte SourceCode nutzen, man muss lediglich noch eine Kleinigkeit machen.

                    Ach ja, aber das wichtigste/interessanteste hab ich jetzt doch glatt vergessen *g* Das Modul funktioniert in der Tat NUR, wenn man für die /etc/shadow Datei Leserechte vergibt! Kann das sein? Ich hatte dich damals ja so verstanden, dass der Sinn von PAM doch gerade wäre, dass dies nicht nötig ist...

                    MfG, Dennis.

                    1. Hallo Dennis,

                      Ach ja, aber das wichtigste/interessanteste hab ich jetzt doch glatt vergessen *g* Das Modul funktioniert in der Tat NUR, wenn man für die /etc/shadow Datei Leserechte vergibt! Kann das sein? Ich hatte dich damals ja so verstanden, dass der Sinn von PAM doch gerade wäre, dass dies nicht nötig ist...

                      Naja, nicht ganz. Alle Programme, die normalerweise mit PAM arbeiten, laufen als root (auch passwd z.B., das ist setuid root). Wenn Du den Apachen also nicht als root laufen lassen willst, brauchst Du halt Leserechte auf /etc/shadow - beides halte ich persönlich aber nicht für ideal.

                      Viele Grüße,
                      Christian

                      --
                      "I have always wished for my computer to be as easy to use as my telephone; my wish has come true because I can no longer figure out how to use my telephone." - Bjarne Stroustrup
                      1. Hi Christian,

                        Naja, nicht ganz. Alle Programme, die normalerweise mit PAM arbeiten, laufen als root (auch passwd z.B., das ist setuid root). Wenn Du den Apachen also nicht als root laufen lassen willst, brauchst Du halt Leserechte auf /etc/shadow - beides halte ich persönlich aber nicht für ideal.

                        Hm, gestartet wird Apache bei mir von root, aber per User und Group wird er zu apache:apache - und das ist dann ja das was zählt.

                        Warum kann nicht einfach irgendwie ein PAM-Deamon im Hintergrund laufen an den Prozesse Benutzername und Passwort geben und der dann richtig oder falsch zurück gibt? Ich kann ich mir irgendwie nicht vorstellen, dass noch nie jemand so etwas geschrieben hat...

                        MfG, Dennis.

                        1. Hallo,

                          Warum kann nicht einfach irgendwie ein PAM-Deamon im Hintergrund laufen an den Prozesse Benutzername und Passwort geben und der dann richtig oder falsch zurück gibt?

                          <I>

                          Gruß aus Berlin!
                          eddi

                          1. Hi eddi,

                            Warum kann nicht einfach irgendwie ein PAM-Deamon im Hintergrund laufen an den Prozesse Benutzername und Passwort geben und der dann richtig oder falsch zurück gibt?

                            <I>

                            Das ist zu hoch für mich - ich fürchte PHP wird dafür nicht geeignet sein und C kann ich nicht...

                            MfG, Dennis.

                            1. Hi Ingrid,

                              Das ist zu hoch für mich - ich fürchte PHP wird dafür nicht geeignet sein und C kann ich nicht...

                              Mit was für einem Algorithmus werden eigentlich die Hashs aus /etc/shadow berechnet?

                              MfG, Dennis.

                              1. Hallo,

                                Mit was für einem Algorithmus werden eigentlich die Hashs aus /etc/shadow berechnet?

                                das ist meist einer der drei DES, MD5 oder Blowfish und kann über chpasswd eingestellt werden.

                                Gruß aus Berlin!
                                eddi

                      2. Hi Christian,

                        Naja, nicht ganz. Alle Programme, die normalerweise mit PAM arbeiten, laufen als root (auch passwd z.B., das ist setuid root). Wenn Du den Apachen also nicht als root laufen lassen willst, brauchst Du halt Leserechte auf /etc/shadow - beides halte ich persönlich aber nicht für ideal.

                        Ich habe gerade noch ein Apache Modul gefunden: mod_authnz_external, in Verbindung pwauth soll auch eine Authentifizierung mit den Systemaccount möglich sein.

                        Wenn ich das richtig verstanden habe ist pwauth ein SetUID-root Programm, welches sich über diese Art und Weise Leserechte auf /etc/shadow holt. Der Vorteil ist, dass der Apache keine Leserechte braucht.

                        Aber irgendwie habe ich das Prinzip hinter PAM immer noch nicht ganz verstanden... Dieser Artikel macht mich wieder glaubens, dass es eine Art "Schicht" gibt, die die Authentifizierung vornimmt und über die Dateien in /etc/pam.d/ kann ich definieren, welche Programme da wie Zugriff drauf haben - aber dann verstehe ich nicht, wie ein Modul, dass PAM verwendet Leserechte auf die /etc/shadow benötigt! Was jetzt - gibt es da eine "Schicht" oder nicht? Wenn ja, wie habe ich mir das vorzustellen?

                        MfG, Dennis.