HenKHan: Perl schreibt nicht in eine Datei

Hallo,

ich habe folgendes Script geschrieben:

#!/usr/bin/perl

use strict;
use CGI;

my $cgi = CGI -> new;
print $cgi -> header();

open DAT, "<./data/counter.dat" or die "Kann Counter-Datei nicht oeffnen!";
    my $inhalt = <DAT>;
close DAT;

$inhalt++;

open DAT, ">./data/counter.dat" or die "Kann Counter-Datei nicht oeffnen!";
    print DAT "$inhalt";
close DAT;

print $inhalt;

Das Script stellt einen Counter da. Wenn ich es direkt in der Kommandozeile meines Linux-Rechners ausführe, läuft es grandios. Sobald ich es aber über meinen Apache-Server ausführe, wird die Datei "platt" gemacht. D.h. der Inhalt wird komplett gelöscht. Dabei sind alle Rechte gesetzt:

counter.pl 755
counter.dat 777
data 777

mein System:
Linux-Kernel: 2.2.26
Perl-Version: 5.6.1
Apache: 1.3.19

Schon einmal vielen Dank

  1. Hallo,

    [...]

    open DAT, "<./data/counter.dat" or die "Kann Counter-Datei nicht oeffnen!";

    [...]

    open DAT, ">./data/counter.dat" or die "Kann Counter-Datei nicht oeffnen!";

    versuche es mal mit absoluten Pfadangaben!

    Gruß
    Reiner

    1. versuche es mal mit absoluten Pfadangaben!

      Das funktioniert nicht.

      HenKHan

  2. hallo,

    my $cgi = CGI -> new;

    my $cgi = new CGI;

    Dein Script funktioniert auf der Konsole, weil es da nicht über die CGI-Schnittstelle gehen muß. Und bei Problemen mit einem Script sollte man immer
       use CGI::Carp qw(fatalsToBrowser);
    verwenden, außerdem ist es sinnvoll, ins log zu schauen. Die Fehlermeldungen sollten dich auf die richtige Spur bringen können.

    open DAT, "<./data/counter.dat" or die "Kann Counter-Datei nicht oeffnen!";
    open DAT, ">./data/counter.dat" or die "Kann Counter-Datei nicht oeffnen!";

    Es muß ein absoluter Pfad sein.

    mein System:
    Linux-Kernel: 2.2.26
    Perl-Version: 5.6.1
    Apache: 1.3.19

    Oh. Alles nicht mehr so ganz taufrisch, wobei es auf dein Problem keinen Einfluß haben dürfte.

    Grüße aus Berlin

    Christoph S.

    1. Hallo,

      außerdem ist es sinnvoll, ins log zu schauen.

      Leider gibt es keine Fehlermeldungen!

      Es muß ein absoluter Pfad sein.

      Habe ich geändert bringt auch nichts.

      Oh. Alles nicht mehr so ganz taufrisch, wobei es auf dein Problem keinen Einfluß haben dürfte.

      Ein 486er mit delilinux, was neueres ist da kaum möglich.

      Gruß HenKHan

      1. hallo,

        außerdem ist es sinnvoll, ins log zu schauen.
        Leider gibt es keine Fehlermeldungen!

        Sondern?

        Es muß ein absoluter Pfad sein.
        Habe ich geändert bringt auch nichts.

        Ich habe es eben mal auf einer Windows-Maschine (Perl 5.8, Apache 2.0.54) in dieser Form durchgespielt:

        use strict;  
        use CGI;  
        use CGI::Carp qw(fatalsToBrowser);  
          
        my $cgi = new CGI;  
        print $cgi -> header();  
          
        open DAT, "<I:/root/test.txt" or die "Kann Counter-Datei nicht oeffnen!";  
            my $inhalt = <DAT>;  
        close DAT;  
          
        $inhalt++;  
          
        open DAT, ">I:/root/test.txt" or die "Kann Counter-Datei nicht oeffnen!";  
            print DAT "$inhalt";  
        close DAT;  
          
        print $inhalt;
        

        Funktioniert tadellos. Das zugehörige log sieht so aus:
        pc1 - - [11/Jun/2005:14:37:40 +0200] "GET /cgi-bin/test2.pl HTTP/1.1" 200 2 "-" "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; SV1)"

        Grüße aus Berlin

        Christoph S.

        1. Funktioniert tadellos.

          Das Problem ist: auf der Console funzt es ja, nur über Apache nicht!

          1. hallo,

            Das Problem ist: auf der Console funzt es ja, nur über Apache nicht!

            Dann solltest du mal ein anderes Script nehmen und nachschauen, ob dein Apache überhaupt CGI-Scripts ausführen lassen darf.

            Grüße aus Berlin

            Christoph S.

            1. Ich habe folgendes Script:

              #!/usr/bin/perl

              ##  printenv -- demo CGI program which just prints its environment

              use CGI;
              use CGI::Carp qw(fatalsToBrowser);
              my $cgi = CGI->new;
              print $cgi->header();

              print &template("./printenv/_env_t.tpl");

              foreach $var (sort(keys(%ENV)))
              {
                  $val = $ENV{$var};
                  $val =~ s|\n|\n|g;
                  $val =~ s|"|\"|g;
                  $val =~ s|,|, |g;
                  print &template("./printenv/_env.tpl");
              }
              print &template("./printenv/_env_b.tpl");

              exit;

              sub template {
              local(*FILE);
              local($file);
              local($HTML);

              $file = $_[0] || die "Template: Es wurde keine Template-Datei definiert.\n";
              open(FILE, "<$file") || die "Template: Konnte $file nicht öffnen: $!\n";
              while (<FILE>) {
                $HTML .= $_;
              }
              close(FILE);

              $HTML =~ s/$(\w+)/${$1}/g;
              return $HTML;
              }

              Das läuft.

              Gruß HenKHan

              1. hallo,

                Ich habe folgendes Script:
                [...]
                Das läuft.

                Na gut, aber die Nachfrage wars schon wert. Jetzt haben wir nur das Problem, daß dein ursprünglich diskutiertes Script sowohl bei Struppi wie auch bei mir (ich habs auch mal auf FreeBSD mit Apache 1.3.33 und Perl 5.8 durchgespielt) keinerlei Probleme macht. Am Script also liegts nicht (obwohl ich mir bessere "Counter" vorstellen kann, aber das war ja nicht deine Frage). Also bleibt eben nur übrig, irgendwo in deiner "Umgebung" nachzusehen, ob da etwas verkehrt ist.

                Was passiert denn, wenn du das CGI-Modul nicht ansprichst?

                Grüße aus Berlin

                Christoph S.

                1. Was passiert denn, wenn du das CGI-Modul nicht ansprichst?

                  Was mich auch noch interessiert wie lautet der aktuelle Pfad den du erhälst wie hier beschrieben.

                  Struppi.

                  1. hallo Struppi,

                    Was mich auch noch interessiert wie lautet der aktuelle Pfad den du erhälst wie hier beschrieben.

                    Jau, ich habs grade eben als "hilfreich" markiert ...

                    BTW: es begegnet mir nicht zum erstenmal, und es kommt auch bei PHP-Fragen vor: warum nehmen manche Leute nur immer wieder Pfade, die mit "./" anfangen? Irgendwo muß es da doch ein Tutorial geben, das solche Pfade empfiehlt (SELFHTML ist es nicht ...)

                    Grüße aus Berlin

                    Christoph S.

                    1. Hallo,

                      1.

                      Was passiert denn, wenn du das CGI-Modul nicht ansprichst?

                      Ich erhalte eine 500 Fehler, da der Header fehlt.

                      2.

                      print "Verzeichniss:". cwd();

                      Ergibt: "Verzeichniss:/home/httpd/cgi-bin"

                      3.
                      Wenn ich "open DAT, ">>./data/counter.dat" ... schreibe, kann er Daten an die Datei anhängen!

                      1. hallo,

                        Was passiert denn, wenn du das CGI-Modul nicht ansprichst?
                        Ich erhalte eine 500 Fehler, da der Header fehlt.

                        Naja, du mußt dann natürlich
                          print "Content-Type: text/html\n\n";
                          print "<!DOCTYPE HTML "-//W3C//DTD HTML 4.01 Transitional//EN">\n";
                          print "<html><head></head><body>\n";
                          usw.
                        vorgeben.

                        print "Verzeichniss:". cwd();
                        Ergibt: "Verzeichniss:/home/httpd/cgi-bin"

                        Und welchen Schluß ziehst du daraus? Eindeutiger kanns dir doch nicht gesagt werden

                        Wenn ich "open DAT, ">>./data/counter.dat" ... schreibe, kann er Daten an die Datei anhängen!

                        Ich hatte weiter vorn im Thread schon mal auf eine SELFHTML-Seite aufmerksam gemacht, die ich dir zur Lektüre empfehle.

                        Grüße aus Berlin

                        Christoph S.

                        1. print "Content-Type: text/html\n\n"; ...

                          Hilft nichts.

                          "/home/httpd/cgi-bin" & "./data/counter.dat" = "/home/httpd/cgi-bin/data/counter.dat" oder? (Das würde richtig sein!)

                          Und welchen Schluß ziehst du daraus?

                          Da weiß ich leider nicht was du mir damit sagen willst.

                          SELFHTML-Seite
                          +<datei.dat bedeutet: Datei datei.dat zum Lesen und zum Schreiben von Daten öffnen. Die Datei muss existieren, ansonsten gibt es einen Fehler.

                          Ok, das habe ich mal verwendet:

                          ...
                          open DAT, "+<./data/counter.dat" or die "Kann Counter-Datei nicht oeffnen!";
                          flock(DAT, 2);
                          $inhalt =int(<DAT>);
                          $inhalt++;
                          print DAT "$inhalt";
                          close DAT;
                          ...

                          Warum hängt er die daten dann an die Datei an, anstatt sie zu überschreiben?

                          HenKHan

                          1. hallo,

                            print "Content-Type: text/html\n\n"; ...
                            Hilft nichts.

                            Glaube ich nicht.

                            Und welchen Schluß ziehst du daraus?
                            Da weiß ich leider nicht was du mir damit sagen willst.

                            Du bist von Anfang an darauf aufmerksam gemacht worden, daß du _dringlich_ deine Pfadangaben korrigieren mußt. Du tust es einfach nicht.

                            +<datei.dat bedeutet: Datei datei.dat zum Lesen und zum Schreiben von Daten öffnen. Die Datei muss existieren, ansonsten gibt es einen Fehler.

                            Richtig gelesen, aber wohl noch nicht verstanden.

                            Ok, das habe ich mal verwendet:
                            open DAT, "+<./data/counter.dat" or die "Kann Counter-Datei nicht oeffnen!";
                            Warum hängt er die daten dann an die Datei an, anstatt sie zu überschreiben?

                            Weil "er" dir ziemliches Durcheinander auf deiner Platte beschert. Noch einmal: korrigiere deinen Pfad. Und laß vor allem das "./" sein, weil dir nicht wirklich klar zu sein scheint, was das bedeutet.

                            Grüße aus Berlin

                            Christoph S.

                            1. Ich danke euch für eure Bemühungen!
                              Aber so funzt es:

                              #!/usr/bin/perl -w

                              use CGI;
                              my $cgi = new CGI;
                              print $cgi -> header();

                              open DAT, "+<$datei" or die "Kann Counter-Datei nicht oeffnen!";
                              flock(DAT, 2);
                              $inhalt =int(<DAT>);
                              $inhalt++;
                              seek DAT, 0, 0;
                              print DAT "$inhalt";
                              close DAT;

                              print "$inhalt<br>";

                              Vielen Dank
                              HenKHan

                              1. hallo,

                                Aber so funzt es:
                                [...]
                                open DAT, "+<$datei" or die "Kann Counter-Datei nicht oeffnen!";

                                Das tut es möglicherweise, aber du hast nun verschwiegen, wie du $datei füllst. Das heißt, in der jetzt "funzenden" Lösung hast du genau das Zentralthema ausgespart und den Pfad zu deiner Datendatei sowie deren Namen nicht angegeben. Das Script _kann_ in der jetzt geposteten Form nicht funktionieren.

                                Grüße aus Berlin

                                Christoph S.

          2. Funktioniert tadellos.
            Das Problem ist: auf der Console funzt es ja, nur über Apache nicht!

            "funzt nicht" ist eine denkbar schlechte Fehlerbeschreibung, mit der Garantiert keiner was anfangen kann. Bei mir läuft dein Skript.

            Struppi.

            1. "funzt nicht" ist eine denkbar schlechte Fehlerbeschreibung, mit der Garantiert keiner was anfangen kann. Bei mir läuft dein Skript.

              Tutmir leid, aber es ist halt so: ich habe keine Anzeichen, warum es nicht geht.

              1. "funzt nicht" ist eine denkbar schlechte Fehlerbeschreibung, mit der Garantiert keiner was anfangen kann. Bei mir läuft dein Skript.
                Tutmir leid, aber es ist halt so: ich habe keine Anzeichen, warum es nicht geht.

                Du könntest einfach mal sagen was passiert und was nicht passiert, was du getan hast um rauszufinden warum nicht das passiert was du erwartest (du hast ja hier schon ein paar Ratschläge bekommen), aber mit der Aussage "funzt nicht" läßt sich dir einfach nicht helfen.

                Struppi.

  3. hallo HenKHan

    open DAT, "<./data/counter.dat" or die "Kann Counter-Datei nicht oeffnen!";

    als pfad würde ich den relativen pfad vom script verwenden.
    wenn dein script serverroot/cgi-bin/counter.pl
    und dein textfile serverroot/data/counter.dat heissen
    dann müsstest du
    open DAT, "<../data/counter.dat" or die "Kann Counter-Datei nicht oeffnen!";

    my $inhalt = <DAT>;
    close DAT;

    hier würde ich zur kontrolle ob er richtig gelesen hat
    print($inhalt);
    einfügen.

    $inhalt++;

    open DAT, ">./data/counter.dat" or die "Kann Counter-Datei nicht oeffnen!";

    hier gilt das selbe für den pfad wie oben

    print DAT "$inhalt";

    diese zeile sollte wohl eher
    print DAT $inhalt;
    lauten

    close DAT;

    print $inhalt;

    l.g. karl :-)´

    1. hallo karl,

      open DAT, "<./data/counter.dat" or die "Kann Counter-Datei nicht oeffnen!";
      als pfad würde ich den relativen pfad vom script verwenden.

      Es sollte helfen, noch einmal http://de.selfhtml.org/perl/funktionen/einausgabe.htm#open nachzulesen.

      print DAT "$inhalt";
      diese zeile sollte wohl eher
      print DAT $inhalt;
      lauten

      Warum?

      Grüße aus Berlin

      Christoph S.

      1. hallo christoph
        du weisst also schon wo du nachlesen kannst.

        open DAT, "<./data/counter.dat" or die "Kann Counter-Datei nicht oeffnen!";
        als pfad würde ich den relativen pfad vom script verwenden.

        Es sollte helfen, noch einmal http://de.selfhtml.org/perl/funktionen/einausgabe.htm#open nachzulesen.

        zitat von ebendort:
        2. den Pfadnamen des zu öffnenden Verzeichnisses, entweder als absolute Pfadangabe oder als relative Pfadangabe aus Sicht des aktuellen Verzeichnisses....
        HenKHan kennt sicherlich beide (absoluten u. relativen) pfade. für ihn wäre es also egal. mit der relativen angabe erspart er sich aber viel arbeit wenn sich beim verlegen der werbsite der absolute pfad verändert.

        diese zeile sollte wohl eher
        print DAT $inhalt;
        Warum?

        noch ein zitat aus selfhtml zum thema print.
        Erwartet als Parameter:
        2. Daten[,Daten] = Ein oder mehrere Elemente (Zeichenketten, Zahlen usw.), die geschrieben werden sollen.

        wenn HenKHan den expliziten string "Zählerstand" schreiben möchte dann lautet die anweisung also:
        print DAT "Zählerstand";
        oder auch
        print DAT "Zählerstand $inhalt";
        für explizite strings und kombiationen aus stings und variablen also völlig richtig mit den anführungszeichen.
        wenn jedoch nur der wert der variablen $inhalt geschrieben werden soll dann sind anführungszeichen fehl am platz (überflüssiger code)

        eins schönes wochenende wünscht dir karl :-)´

        1. hallo karl,

          du weisst also schon wo du nachlesen kannst.

          Selbstverständlich. Schau mal ins Impressum von SELFHTML 8.1

          Grüße aus Berlin

          Christoph S.

    2. als pfad würde ich den relativen pfad vom script verwenden.

      Ich verwende jetzt den absoluten Pfad.

      zur kontrolle ob er richtig gelesen hat

      Er ließt richtig.

      print DAT $inhalt;

      Bringt es leider auch nicht.

      mfg HenKHan

      1. hallo HenKHan

        Ich verwende jetzt den absoluten Pfad.

        sollte auch funktionieren.

        Er ließt richtig.

        print DAT $inhalt;
        Bringt es leider auch nicht.

        ich hab nochmal nachgelesen und eines meiner alten scripten ausgegraben.
        dort verwendete ich mehr klammern.
        möglicherweise kann das helfen.

        open(DATEI, ">../da_solls_rein.txt");
        print(DATEI $der_text);
        close(DATEI);

        vieleicht hilft ja auch:
        binmode(DATEI);
        nach dem open befehl.

        l.g. karl :-)´

  4. ich habe folgendes Script geschrieben:

    Das Script stellt einen Counter dar.

    [...]

    Hallo,
    läuft bei mir seit Jahren:

    #!/usr/bin/perl -w

    Author : WOLfgang Schricker wols@wols.org

    use strict;

    my $log_file = "data/counter.dat";

    unless ( open(LOG, "+< $log_file") )
    {
      open(LOG, "> $log_file")  or die "Can't open '$log_file':\n$!\n";

    print LOG "1";

    close(LOG)                or die "Can't close '$log_file':\n$!\n";
    }
    else
    {
      my @log = <LOG>;

    $log[0]++;
       seek(LOG, 0, 0)          or die "Can't seek '$log_file':\n$!\n";
       print LOG @log;
       truncate(LOG, tell(LOG)) or die "Can't truncate '$log_file':\n$!\n";

    close(LOG)                or die "Can't close '$log_file':\n$!\n";
    }

    exit(0);

    1. läuft bei mir seit Jahren:

      sicher?

      #!/usr/bin/perl -w

      Author : WOLfgang Schricker wols@wols.org

      use strict;

      my $log_file = "data/counter.dat";

      unless ( open(LOG, "+< $log_file") )
      {
        open(LOG, "> $log_file")  or die "Can't open '$log_file':\n$!\n";

      print LOG "1";

      close(LOG)                or die "Can't close '$log_file':\n$!\n";
      }
      else
      {
        my @log = <LOG>;

      $log[0]++;
         seek(LOG, 0, 0)          or die "Can't seek '$log_file':\n$!\n";
         print LOG @log;
         truncate(LOG, tell(LOG)) or die "Can't truncate '$log_file':\n$!\n";

      close(LOG)                or die "Can't close '$log_file':\n$!\n";
      }

      exit(0);

      Das der Zähler ohne flock nicht schon mehrmals auf null zurückgesetzt wurde, ist entweder Glück oder du bist der einzige der darauf zugrift.

      Struppi.

      1. läuft bei mir seit Jahren:

        sicher?

        #!/usr/bin/perl -w

        [...]

        Das der Zähler ohne flock nicht schon mehrmals auf null zurückgesetzt wurde, ist entweder Glück oder du bist der einzige der darauf zugrift.

        Stimmt, läuft lokal ;-)

  5. #!/usr/bin/perl

    Warnungen wären auch noch sinvoll
    #!/usr/bin/perl -w

    open DAT, "<./data/counter.dat" or die "Kann Counter-Datei nicht oeffnen!";
        my $inhalt = <DAT>;
    close DAT;

    Wenn du diesen "Counter" wirklich verwenden willst, musst du einserseits die Datei "flocken" und zum lesen und schreiben öffnen

    Außerdem solltest du dir mal das aktuelle Arbeitsverzeichniss ausgeben, das muss in der CGI umgebung nicht das sein wo das Skript liegt.

    use Cwd;

    print "Verzeichniss:". cwd();

    Struppi.