Bio: (PERL) Das Environment und ps machen mich fertig :'-(

Sup!

Liebe Mitstreiter. Ich habe ein wunderschönes Programm in Perl geschrieben, dessen Aufgabe es ist, zu überprüfen, ob ein anderes Programm noch läuft.

Es tut dies, in dem es mit

undef $/;
open IN,('ps -e|');
$var = <IN>;
close IN;

if ($var =~ 'laufendes_programm.pl')
  {
    print "supi!\n";
  }
else
  {
    print "verdammt!\n";
  }

nachschaut, ob das programm laufendes_programm.pl noch läuft.

Tja, von der Kommandozeitel funktioniert das hervorragend, aber leider wird das Programm als eine Art Dämon von meinem lustigen ip-up.local Skript gestartet, sobald meine Internet-Verbindung hoch kommt. Und in dieser Umgebung scheint das Environment anders eingestellt zu sein, und das scheint Einfluß auf die Pipe zum ps zu haben.

Zum Beispiel bekomme ich in meiner Shell normalerweise mit ps -ef | less die ganze Ausgabe von ps, aber das Programm oben bekommt, in seiner Umgebung, nur die ersten 80 Zeichen.
Und, zu allem Übel, formatiert ps seine Ausgabe nach Regeln, die mir total unersichtlich sind... laufendes_programm.pl ist z.B. einfach ein zu langer Name, der glatt abgeschnitten wird - folglich funktioniert der reguläre Ausdruck nicht, und alles läuft schief.
Ich habe in den ps manpages rumgesucht, aber wie man ps dazu bringt, bestimmte Spaltenbreiten für bestimmte Ausgabe einzuhalten, habe ich nicht finden können.
Und wie man die Umgebung manipuliert, so daß ich mehr als 80 Zeichen bekomme über die Pipe, habe ich auch noch nicht rausbekommen.

Hilfe ;-)

Gruesse,

Bio

  1. Sup!

    Moin.

    Tja, von der Kommandozeitel funktioniert das hervorragend, aber leider wird das Programm als eine Art Dämon von meinem lustigen ip-up.local Skript gestartet, sobald meine Internet-Verbindung hoch kommt. Und in dieser Umgebung scheint das Environment anders eingestellt zu sein, und das scheint Einfluß auf die Pipe zum ps zu haben.

    In Perl gibts die "Backticks", die eigentlich den in ihnen enthaltenen Befehl an die Shell geben, und den Ausgabetext des Befehls an Perl zurückliefern.

    Ich habe mit

    $var = befehl;

    immer gute Erfahrungen gemacht. Das liefert normalerweise exakt die Shellausgabe. Und man kann dann auch nach Ausdrücken suchen. Auf diese Weise habe ich per Perl das manuelle Dialin meines Routers realisiert - ein Klick im Browser und etwa eine Minute Warten... :)

    Es geht also grundsätzlich.

    - Sven Rautenberg

    1. Sup!

      In Perl gibts die "Backticks", die eigentlich den in ihnen enthaltenen Befehl an die Shell geben, und den Ausgabetext des Befehls an Perl zurückliefern.

      Leider behauptet das Perl-Manual, das käme aufs gleiche raus, Backticks und Read-Pipe öffnen... naja, ich werde mal rumprobieren.

      Gruesse,

      Bio

  2. Moin!

    Zum Beispiel bekomme ich in meiner Shell normalerweise mit ps -ef | less die ganze Ausgabe von ps, aber das Programm oben bekommt, in seiner Umgebung, nur die ersten 80 Zeichen.

    Auf der Shell kriegst Du aber auch nur soviele Zeichen, wie Dein Terminal(-fenster) breit ist. ps fragt also wahrscheinlich das Terminal ab, wieviel es darstellen kann. Ich vermute mal, Dein ip-up dings laeuft nicht in einem Terminal und daher wird einfach der kleinste gemeinsame Nenner angenommen, naemlich 80 Zeichen.

    Schau Dir mal die Option -w von ps an. Evtl. mehrmals angeben.

    So long

    1. Moin!

      Zum Beispiel bekomme ich in meiner Shell normalerweise mit ps -ef | less die ganze Ausgabe von ps, aber das Programm oben bekommt, in seiner Umgebung, nur die ersten 80 Zeichen.

      Auf der Shell kriegst Du aber auch nur soviele Zeichen, wie Dein Terminal(-fenster) breit ist. ps fragt also wahrscheinlich das Terminal ab, wieviel es darstellen kann. Ich vermute mal, Dein ip-up dings laeuft nicht in einem Terminal und daher wird einfach der kleinste gemeinsame Nenner angenommen, naemlich 80 Zeichen.

      Schau Dir mal die Option -w von ps an. Evtl. mehrmals angeben.

      So long

      Moin Moin !

      Also zuerst solltest Du mal dafür sorgen, daß Du exakt das ps startest, das Du auch haben willst, sehr wahrscheinlich /bin/ps oder /usr/bin/ps. Ansonsten baust Du ein Sicherheitsloch.

      Dann rufst Du ps mit der -w-Option (mehrfach) auf, so daß Du /bin/ps -wwwwww hast.

      Und Du setzt vor dem Open/Backtick $ENV{'TERM'} auf 'linux' oder 'vt100', damit Du ein halbwegs brauchbares Terminal vorgibst.

      Du kannst /sbin/pidof benutzen, um ein Programm nach Namen zu suchen, z.B. liefert 'pidof init' die PID des init-Prozesses, also 1.

      Dein Algorithmus fällt auf Programme rein, die irgendwo den String laufendes_programm.pl in der Ausgabe von ps enthalten.

      Mit folgendem Script lege ich dein Programm garantiert rein:

      #!/bin/bash
      while true ; do
        /bin/echo Ich bin gemein ich leg ihn rein denn er sucht nur laufendes_programm.pl tralalalala
      done

      MEINE ALTERNATIVE:

      Warum schreibst Du in dem zu überwachenden Script nicht einfach die PID nach /tmp/blabla.pid oder /var/run/blabla.pid raus und löscht sie unmittelbar vor dem Ende des Programms wieder ?

      Dann beschränkt sich die Prüfung auf ein Shell-Script (das Du fast 1:1 in Perl nachprogrammieren kannst):

      #!/bin/bash
      PIDFILE=/var/run/blabla.pid
      if [ -f "$PIDFILE" ] ; then
         # Datei ist da, läuft das Programm ?
         if [ -d /proc/cat "$PIDFILE" ] ; then
            # Pseudo-Verzeichnis des Prozesses (/proc/12345) vorhanden
            echo "Programm laeuft"
         else
            echo "Oooops. Abgestuerzt und PID-Datei nicht geloescht."
            rm -f "$PIDFILE"
         fi
      else
         echo "Programm laeuft nicht"
      fi

      Das ist übrigens Standard-Verhalten von Unix-Programmen, sei mal angemerkt.

      Alexander