unlink Fehlerursache

Einklappen
X
 
  • Filter
  • Zeit
  • Anzeigen
Alles löschen
neue Beiträge

  • unlink Fehlerursache

    hello,

    kennt wer eine zuverlässige Möglichkeit, wie man im nachhinein feststellen kann, warum ein unlink nicht funktioniert hat? Ich würde z. B. danach gerne wissen, ob es nicht geklappt hat, weil es die Datei nicht gegeben hatte.

    Ich will die Fehlermeldung von unlink aber mit @ unterdrücken, d. h. nicht direkt auf dem Bildschirm ausgeben. Ich möchte dann im weiteren Scriptverlauf auf den Fehler reagieren.

    Und vor dem unlink will ich nicht mit if(file_exists(..)) arbeiten.

    error_get_last geht leider nicht. Message ist leider ein Text, keine ID, aufgrund der man auf den Grund Rückschlüsse ziehen könnte. Und mit debug_backtrace geht da anscheinend gar nichts.
    Zuletzt geändert von deedee; 14.06.2009, 22:25.

  • #2
    Was verstehst du an dem Handbucheintrag nicht:
    Beschreibung
    bool unlink ( string $filename )
    Löscht filename . Ähnlich der UNIX C unlink() Funktion.
    [COLOR="Red"]Gibt bei Erfolg TRUE zurück, im Fehlerfall FALSE.[/COLOR]
    PHP: unlink - Manual
    Wir werden alle sterben

    Kommentar


    • #3
      Ich glaube nicht, dass eine solche Möglichkeit existiert.

      unlink selber ist nicht sehr "gesprächig", was eine eventuelle Fehlerursache angeht; liefert nur true oder false zurück.
      Zitat von deedee Beitrag anzeigen
      Und vor dem unlink will ich nicht mit if(file_exists(..)) arbeiten.
      Du kannst dir ja eine Wrapperfunktion dafür schreiben, die erst mal auf Existenz checkt, und dann auch noch die Datei und das Verzeichnis bzgl. Rechten abcheckt (is_writable muss m.E. für beide erfüllt sein, damit PHP die Datei löschen darf) - und dann dem Ergebnis entsprechend einen schönen Fehlercode zurückgibt, oder halt unlink dafür aufruft.
      I don't believe in rebirth. Actually, I never did in my whole lives.

      Kommentar


      • #4
        Du kannst dir ja eine Wrapperfunktion dafür schreiben, die erst mal auf Existenz checkt, und dann auch noch die Datei und das Verzeichnis bzgl. Rechten abcheckt
        Diese ganzen Prüfungen will ich vorher nicht machen, weil während diesen Prüfungen ein anderer Prozess die Datei mittlerweile gelöscht haben könnte.

        Wäre es vielleicht irgendwie möglich in Verbindung mit is_file, file_exists ... im NACHHINEIN? Also vielleicht irgendwie so:
        PHP-Code:
        if(!@unlink($strFile))
           if(
        is_file($strFile))
              ... 
        Aber mir fällt da nichts verlässliches ein. $strFile könnte theoretisch alles mögliche sein: Array, Objekt, null, String, .... Und wenn es ein String und eine Dateiangabe ist, könnte es die Datei geben oder nicht.

        Aber ich glaube, wenn ich diese Prüfungen im nachhinein mache, könnte mir wieder ein anderer Prozess in die Quere kommen, oder?
        Zuletzt geändert von deedee; 14.06.2009, 22:48.

        Kommentar


        • #5
          Zitat von deedee Beitrag anzeigen
          Diese ganzen Prüfungen will ich vorher nicht machen, weil während diesen Prüfungen ein anderer Prozess die Datei mittlerweile gelöscht haben könnte.
          Ja, darauf, dass so eine Lösung nicht mehr atomar wäre, weisst auch ein Nutzerkommentar im Manual hin.

          Wäre es vielleicht irgendwie möglich in Verbindung mit is_file, file_exists ... im NACHHINEIN. Also vielleicht irgendwie so:
          PHP-Code:
          if(!@unlink($strFile))
             if(
          is_file($strFile))
                ... 
          Da kommt aber genau die gleiche Argumentation ins Spiel - ein anderer Prozess könnte die Datei, deren "Löschung" nicht geklappt hat, weil sie schlicht nicht vorhanden war, in der "Zwischenzeit" auch hier erstellt haben. (Wobei die aktuelle Scriptinstanz davon vermutlich nicht mal was mitbekommen würde, wenn nicht vorher clearstatcache aufgerufen wird.)

          $strFile könnte theoretisch alles mögliche sein: Array, Objekt, null, String, ....
          Wenn du nicht mal das vorher abprüfen willst - dann kann man dir diesbezüglich wohl nicht helfen. Du kannst nicht von einer Funktion, die einen ganz klar umrissenen, kleinen Aufgabenbereich hat, erwarten, eine eierlegende Wollmilchsau zu sein.
          I don't believe in rebirth. Actually, I never did in my whole lives.

          Kommentar


          • #6
            Tja ... was macht man da??
            EDIT: Ja OK ... ein if(is_string($strFile)) kann ich vorher machen. Aber ob das wirklich weiterhilft?

            Kommentar


            • #7
              Zitat von deedee Beitrag anzeigen
              Ja OK ... ein if(is_string($strFile)) kann ich vorher machen. Aber ob das wirklich weiterhilft?
              Nö, kaum - das stellt lediglich die winzige, formale Minimalanforderung an den Parameter sicher.

              Aber ob da ggf. grober Unsinn drin stand, und es deshalb keine Datei zum Löschen gab, oder ob die Datei sehr wohl existiert, das Script sie aber nicht löschen darf - darüber verrät dir die Prüfung des Parameters auf den richtigen Typ Nullkommanix.
              I don't believe in rebirth. Actually, I never did in my whole lives.

              Kommentar


              • #8
                Angenommen, ist prüfe auf if(is_string($strFile)), was könnte denn dann eigentlich alles beim unlink schiefgehen?

                An den Rechten sollte es eigentlich nicht scheitern, da ich die Dateien selbst in PHP mit w bzw. w+ erstelle. Könnte es sein, dass ein unset fehlschlägt, weil ein anderer Prozess aktuell die Datei verändert oder daraus liest?

                Oder gibt es eine Möglichkeit, dass man für den unlink irgendwie einen context definiert und darüber eine Fehlerrückmelung erhält?
                Zuletzt geändert von deedee; 14.06.2009, 23:41.

                Kommentar


                • #9
                  Jetzt wäre mir noch etwas eingefallen. Ich hatte die Hoffnung, dass error_get_last() einen anderen Fehlercode meldet, wenn die zu löschende Datei nicht gefunden wurde. Leider ist dem nicht so. Der Fehlercode ist immer 2. MIST!

                  Mein Gott!! Ich programmiere jetzt schon einige Jahre lang PHP. Und erst jetzt wird mir so richtig bewusst, wie mies eigentlich PHP ist. Dieses Problem, nachträglich auf eine Fehlerursache eingehen zu wollen, gibt es ja nicht nur bei unset. Das zieht sich ja durch das ganze PHP durch, oder?

                  Kann man eigentlich darauf vertrauen, dass Fehlermeldungen von error_get_last() prinzipiell immer englisch sind und dass sie über die PHP-Versionen hinweg auch immer gleich lauten? Dann wäre es mir mittels Stringfunktionen möglich, die Fehlerursache zu ermitteln.
                  Warning: unlink(xxxx.txt) [function.unlink]: No such file or directory in C:\xampp\htdocs\test.php on line 3
                  Dann könnte ich nämlich beim unlink auf "No such file or directory in" filtern.
                  Zuletzt geändert von deedee; 15.06.2009, 09:34.

                  Kommentar


                  • #10
                    Meines bescheidenen Erachtens macht das @ vor dem unlink() keinen Sinn!
                    Weil: Das Error_Reporting gehört in produktiv Umgebungen sowieso abgeschaltet.

                    Das "danach" Prüfen ist ebenfalls bedenklich. Meines bescheidenen Erachtens die falsche Logik. Erst prüfen, dann löschen.

                    Angenommen, ist prüfe auf if(is_string($strFile)), was könnte denn dann eigentlich alles beim unlink schiefgehen?
                    PHP-Code:
                    unlink('index.php'); 
                    Wir werden alle sterben

                    Kommentar


                    • #11
                      Wenn ich zuerst prüfe, ob es existiert, und danach lösche (falls es existiert), könnte ein anderer Prozess dazwischenfunken.

                      Prozess A: erkennt, dass Datei existiert
                      Prozess B: erkennt ebenfalls, dass Datei existiert
                      Prozess A: löscht Datei
                      Prozess B: versucht die Datei zu löschen, geht aber nicht, weil sie nicht mehr existiert

                      Prozess B liefert einen Fehler, obwohl man eigentlich das Endergebnis hat, das man haben möchte.

                      Wie wärs damit:
                      PHP-Code:
                            function __unlink($__strFile)
                            {  if(!@
                      unlink($__strFile))
                               {  
                      $arrErr=error_get_last();
                                  if
                                  (  
                      substr($arrErr['message'],6  )!='unlink' ||
                                     
                      substr($arrErr['message'],-25)!='No such file or directory'
                                  
                      )
                                  {  
                      /*
                                      * Datei konnte nicht gelöscht werden.
                                      */
                                     
                      trigger_error(...
                                     return 
                      false;
                                  }
                               }
                               return 
                      true;
                            } 
                      Was anderes würde mir auch noch einfallen. Und zwar, indem man vorher ein blockierendes Element einfügt. Z. B.:
                      PHP-Code:
                      /*
                       * andere Prozesse blockieren:
                       */
                      $fh=fopen('dummy.xxx','r');
                      flock($fh,LOCK_EX);
                      /*
                       * löschen:
                       */
                      if
                      (  
                      file_exists($strFile) &&
                         !@
                      unlink($strFile)
                      )
                         
                      trigger_error(... 
                      Aber das finde ich nicht toll. Ich müsste eine Dummy-Datei anlegen.
                      Gibts vielleicht irgendeine PHP-Funktion, mit der ich einen ähnlichen blockierenden Effekt erzielen könnte??
                      Zuletzt geändert von deedee; 15.06.2009, 11:09.

                      Kommentar


                      • #12
                        Zitat von deedee Beitrag anzeigen
                        Prozess B liefert einen Fehler, obwohl man eigentlich das Endergebnis hat, das man haben möchte.
                        Das ist dann ein Fehler in der Logik des Codes. Er sollte bei korrektem Ergebnis keinen Fehler werfen.

                        PHP-Code:
                        if (!unlink($file) && file_exists($file)) {
                            
                        trigger_error(...);

                        Prozess A führt nur das unlink() aus. Mit Erfolg.
                        In Prozess B liefert das unlink() false, aber das nachfolgende file_exists() ebenfalls und deshalb wird kein Fehler geworfen.

                        Kommentar


                        • #13
                          if (!unlink($file) && file_exists($file)) {
                          Prozess A: kann Datei nicht löschen, weil sie nicht existiert
                          Prozess B: erzeugt die Datei irgendwo
                          Prozess A: file_exists liefert true

                          Jetzt habe ich wieder einen Fehler, obwohl beim unlink eigentlich alles OK war, da die Datei zu diesem Zeitpunkt nicht existiert hatte. Ich will keinen Fehler bekommen, wenn die Datei schon gelöscht war.

                          Also ideal wäre so Funktionen wie:

                          process_lock(String $id)
                          process_unlock(String $id)

                          Dass andere Prozesse blockieren müssen, wenn deren Interpreter auf diese gleiche $id stoßen. Aber so etwas gibt es nicht, oder?
                          Zuletzt geändert von deedee; 15.06.2009, 14:19.

                          Kommentar


                          • #14
                            Evtl. solltest du noch etwas an deinem Konzept arbeiten

                            Oder dich besser auch über Semaphore kundig machen!
                            Wir werden alle sterben

                            Kommentar


                            • #15
                              Semaphore hört sich wirklich sehr interessant an. Scheint es aber nur für Unix zu geben. Ich würde gerne so programmieren, dass es unter Windows und Unix funktioniert (mal abgesehen davon, dass ich momentan unter Windows programmiere).

                              Aber ich habe gelesen, dass unter Windows LOCK/UNLOCK als Mutex-Alternative zu Semaphore eingesetzt wird. So eine Variante hatte ich schon hier reingepostet. Zuerst LOCK einer Dummy-Datei, dann meine eigentlichen Dateioperationen.

                              Nur leider hat diese LOCK-Variante einen starken Nachteil. Damit blockiere ich ALLE unlink-Aufrufe, egal, welche Datei es betrifft. Sollten mit dem Script gleichzeitig 1000 unterschiedliche Dateien gelöscht werden (d. h. 1000 Prozesse), werden 999 Prozesse geblockt. Was 999 mal Unfug ist, wenn es 1000 UNTERSCHIEDLICHE Dateien sind.

                              Darum suche ich eine Alternative. Ich glaube, die Funktion, wo ich mit string-Funktionen die Fehlerrückmeldung analysiere, scheint die beste Variante zu sein, oder? Allerdings ist diese Vorgehensweise auch wieder nur auf 1 PHP-Funktion anwendbar. Sollte ich 2 zusammenhängende Funktionen haben, habe ich schon wieder ein Problem:

                              PHP-Code:
                              if
                                             (  (
                              $nTime=filemtime($strFile))!==false && // TEIL 1
                                                
                              $nTime+$__nMaxLifeTime<time() && 
                                                !
                              unlink($strFile)  // TEIL 2
                                             
                              )
                                                
                              $bOk=false
                              Dann hilft wohl wirklich nur noch LOCK/UNLOCK einer Datei oder einer DB-Tabelle, oder?

                              O. T. in dieses Forum kommt man wirklich nur seeehr schwer rein. Ich hoffe das ändert sich noch.
                              Zuletzt geändert von deedee; 15.06.2009, 16:52.

                              Kommentar

                              Lädt...
                              X