Dieter: CHMOD bei allen Dateien eines Verzeichnisses ?

Hallo !

Ich habe folgendes Problem:
In einem Verzeichnis liegen etwas über 200.000 einzelne Dateien, diese sind widerrum direkt durch ein PHP-Script dorthin gespeichert worden (werden auch durch Script aufgerufen), leider (mein Fehler) aber mit der Rechtevergabe 0600 - das hat zur Folge, das ich diese Dateien per Standart-FTP (Webbenutzer/kein Root) NICHT laden kann.
Meine Frage daher:
Besteht eine Möglichkeit, alle Dateien per PHP-Script (da PHP als Root ausgeführt wird wäre das dann ja möglich) mit neuen rechten zu versehen ? Der Befehl "chmod()" ist bekannt, kann ich aber kaum verwenden, denn wie gesagt es sind über 200.000 einzelne Dateien...

Viele Grüße
Dieter

  1. Hallo Dieter,

    wieso geht denn

    chmod [-R] xxx * mit xxx = Deine zu vergebenden Rechte

    nicht ?

    Gruß

    Hans

    1. Moin Hans,

      chmod [-R] xxx * mit xxx = Deine zu vergebenden Rechte
      nicht ?

      nur wenn er Zugriff auf die Shell hat. Das wage ich zu bezweifeln, ausserdem hat er das OS nicht benannt.

      regds
      Mike©

      --
      Freunde kommen und gehen. Feinde sammeln sich an.
      1. Hallo nochmal,

        nein, leider kein Zugriff über Shell, OS ist Linux (Suse mit Confixx verwurschtelt). Wenn ich das per "Einzeländerung" machen würde (hab ich versucht mit folgendem Code:

          
        <?php  
        $handle=opendir('./uploads/');  
        while (false !== ($file = readdir ($handle))) {  
          if ($file=='.') $file ='';  
          if ($file=='index.php') $file ='';  
          if ($file=='..') $file ='';  
          if ($file<>'')  
          {  
          $fileurl = './uploads/'.$file;  
          chmod ($fileurl, 0755);  
          }  
        }  
        closedir($handle);  
        ?>  
        
        

        komme ich sehr schnell an die Leistungsgrenzen, besser gesagt an die Zeitbegrenzung, und da das Script ja jedesmal von vorne anfängt, bringt micht das nicht wirklich weiter.

        Gruss
        Dieter

        1. Moin Dieter,

          komme ich sehr schnell an die Leistungsgrenzen, besser gesagt an die Zeitbegrenzung, und da das Script ja jedesmal von vorne anfängt, bringt micht das nicht wirklich weiter.

          hast Du dem Script ein set_time_limit(0); verpasst.
          Kannst Du u.U. die Abarbeitung anhand der Dateinamen in Blöcke splitten?

          regds
          Mike©

          --
          Freunde kommen und gehen. Feinde sammeln sich an.
          1. Moin Dieter,

            komme ich sehr schnell an die Leistungsgrenzen, besser gesagt an die Zeitbegrenzung, und da das Script ja jedesmal von vorne anfängt, bringt micht das nicht wirklich weiter.

            hast Du dem Script ein set_time_limit(0); verpasst.
            Kannst Du u.U. die Abarbeitung anhand der Dateinamen in Blöcke splitten?

            regds
            Mike©

            Hallo Mike,

            leider ist ein set_time_limit dank Confixx wirkungslos (grrrr - ich mag confixx nicht wirklich..), Befehle über system sind ebenfalls nicht möglich. Eine Blockweise Abarbeitung (Die Dateinamen sind mir leider nicht im einzelnen bekannt) hatte ich einmal über MySQL ausprobiert, allerdings scheitert diese Lösung auch wieder am time_limit (Einlesen des Verzeichnisses + Abgleich über DB [Name da = JA/NEIN]) schon in der Startphase (nebenbei bedankt sich MySQL nicht gerade bei den Abfragen...).
            Meine Idee war schon mal, soetwas per CGI zu lösen (da schneller, denk ich), nur leider kann ich das überhaupt nicht.

            Gruss
            Dieter

            1. Moin Dieter,

              Meine Idee war schon mal, soetwas per CGI zu lösen (da schneller, denk ich), nur leider kann ich das überhaupt nicht.

              ich habe zwar keine Ahnung von Perl, aber IMHO könnte ein Perl Script das bewältigen.

              Als Notlösung hätte ich folgendes Konstrukt.

              • Lese in einer Schleife 10.000 Dateien aus dem Verzeiches
              • Mache darauf den chmod und verschiebe sie in ein neues DIR
              • Das machst Du dann 20 mal

              Sollte in der Ausführungszeit machbar sein. Ansonsten auf 5.000 begrenzen.

              regds
              Mike©

              --
              Freunde kommen und gehen. Feinde sammeln sich an.
              1. Moin Dieter,

                Meine Idee war schon mal, soetwas per CGI zu lösen (da schneller, denk ich), nur leider kann ich das überhaupt nicht.

                ich habe zwar keine Ahnung von Perl, aber IMHO könnte ein Perl Script das bewältigen.

                Als Notlösung hätte ich folgendes Konstrukt.

                • Lese in einer Schleife 10.000 Dateien aus dem Verzeiches
                • Mache darauf den chmod und verschiebe sie in ein neues DIR
                • Das machst Du dann 20 mal

                Sollte in der Ausführungszeit machbar sein. Ansonsten auf 5.000 begrenzen.

                regds
                Mike©

                Hallo Mike,

                supi, das könnte die Lösung (immer nur x chmod und move) sein !
                Hatte da gar nicht dran gedacht...
                Werde mich gleich mal dransetzten (und das Ergebnis auch hier posten - vielleicht haben ja auch andere das Problem...).

                Gruss
                Dieter

                1. Hi,

                  Hatte da gar nicht dran gedacht...

                  Also ich frage einfach die aktuellen Rechte ab, und setze nur da die Rechte neu, wo sie nicht passen! 8-)

                  Aber Achtung: Vor dem Scriptstart solltest Du mit clearstatcache() dafür sorgen, daß auch wirklich die aktuellen Werte kommen! ;-)

                  Gruß, Cybaer

                  --
                  Hinweis an Fragesteller: Fremde haben ihre Freizeit geopfert, um Dir zu helfen. Helfe Du auch im Archiv Suchenden: Beende deinen Thread mit einem "Hat geholfen" oder "Hat nicht geholfen"!
                  1. Moin Cybaer,

                    Also ich frage einfach die aktuellen Rechte ab, und setze nur da die Rechte neu, wo sie nicht passen! 8-)

                    da aber alleine die Ausführung von chmod schon zu lange dauert, kann doch die zusätzliche Abfrage auf bestehende Rechte nicht schneller sein. *GRÜBEL*

                    regds
                    Mike©

                    --
                    Freunde kommen und gehen. Feinde sammeln sich an.
                    1. Hi,

                      da aber alleine die Ausführung von chmod schon zu lange dauert, kann doch die zusätzliche Abfrage auf bestehende Rechte nicht schneller sein. *GRÜBEL*

                      Also ich würde schon vermuten, daß das Auslesen von Dateiinformationen schneller geht als das Ändern selbiger. ;-)

                      Kann man ja mal testen:

                      if(substr(sprintf('%o',fileperms($serverFile)),-3)=='600') chmod($serverFile,0644);

                      Einen doppelten Move, hin und wieder zurück, fände ich deutlich aufwendiger.

                      Gruß, Cybaer

                      --
                      Hinweis an Fragesteller: Fremde haben ihre Freizeit geopfert, um Dir zu helfen. Helfe Du auch im Archiv Suchenden: Beende deinen Thread mit einem "Hat geholfen" oder "Hat nicht geholfen"!
                      1. Moin Cybaer,

                        Also ich würde schon vermuten, daß das Auslesen von Dateiinformationen schneller geht als das Ändern selbiger. ;-)

                        ja stimmt, ABER das Auslesen der Dateiinformationen kommt ja _zusätzlich_ zum chmod hinzu und dort wird die Grenze der Ausführungszeit ja schon erreicht. (Ohne das Auslesen) Oder liege ich da falsch?

                        regds
                        Mike©

                        --
                        Freunde kommen und gehen. Feinde sammeln sich an.
                        1. Hi,

                          ja stimmt, ABER das Auslesen der Dateiinformationen kommt ja _zusätzlich_ zum chmod hinzu und dort wird die Grenze der Ausführungszeit ja schon erreicht. (Ohne das Auslesen) Oder liege ich da falsch?

                          Ja, denn wenn chmod nicht notwendig ist, wird es auch gar nicht gemacht! :-)

                          Das kann man also solange treiben, bis alle geändert sind.

                          Es sei denn, der Server wäre schon mit dem Auslesen überfordert.

                          Gruß, Cybaer

                          --
                          Hinweis an Fragesteller: Fremde haben ihre Freizeit geopfert, um Dir zu helfen. Helfe Du auch im Archiv Suchenden: Beende deinen Thread mit einem "Hat geholfen" oder "Hat nicht geholfen"!
                          1. Hallo an alle !
                            Hallo Mike !

                            zuerst nochmal vielen Dank an Mike, seine Idee war goldrichtig !
                            Indem ich einfach nur X Dateien nach einem zweitem Verzeichnis
                            verschiebe und diese mit neuen rechten versehe, klappt es auch bei
                            sehr vielen Dateien.
                            Nachfolgend habe ich für alle Interessierten das entsprechende Script
                            einmal eingefügt:

                              
                            <?php  
                            ###############################################################################  
                            # Folgend die eigenen Werte setzen  
                            $zaehlermax = 10000;  # Anzahl der zu verschiebenden Dateien  
                            $verzeichnis = './uploads./'; # Ordner, in dem sich die Dateien befinden  
                            $alturl = './uploads/';  # Relativer Pfad (alt) mit abschliessendem '/'  
                            $neuurl = './uploads_new/'; # Relativer Pfad wohin die Dateien sollen  
                            $newchm = '0755';  # Chmod-Wert (Oktal !!)  
                            ###############################################################################  
                            # Ab hier nichts mehr ändern !!  
                            ###############################################################################  
                            $zaehler = 0;  
                            $handle=opendir($verzeichnis);  
                            while (false !== ($file = readdir ($handle))) {  
                              if ($zaehler >  $zaehlermax) break;  
                              if ($file=='.') $file ='';  
                              if ($file=='index.php') $file ='';  
                              if ($file=='..') $file ='';  
                              if ($file<>'')  
                              {  
                              $fileurl = $alturl.$file;  
                              $filenewurl = $neuurl.$file;  
                              rename($fileurl, $filenewurl);  
                              chmod ($filenewurl, $newchm);  
                              $zaehler = $zaehler + 1;  
                              }  
                            }  
                            closedir($handle);  
                            $realcount = $zaehler - 1;  
                            echo $realcount." Dateien geändert und nach >".$filenewurl."< verschoben.";  
                            ?>  
                            
                            

                            Natürlich muß man die Datei so häufig aufrufen, bis alle Dateien entsprechend
                            verschoben worden sind, das ist aber sicher besser, als hunderttausende Dateien
                            von Hand zu ändern. Noch ein kleiner Hinweis: Die Datei immer per "Aktualisieren"
                            im IE aufrufen, sonst kommts zu Fehlern.

                            Viele Grüße
                            Dieter

                            Nachtrag an Cybaer & Marc & Co.:
                            Klar logisch, hatte nur deine Antwort (Cybaer) nicht richtig bedacht, anstatt verschieben
                            Rechte ändern bei x Dateien und dann wieder von vorn...
                            Die Möglichkeit per MySQL das gleiche in Grün, d.h. das wäre auch die Lösung.
                            Ich hatte nur immer das ganze Verzeichnis im Kopf (und hab den Wald vor lauter Bäumen
                            nicht mehr gesehen).
                            Ich spare mir bei obiger Lösung einen Move, indem ich die Dateien
                            einmal in das neue
                            Verzeichnis lege, wenn der alte Ursprungsordner leer ist, kill ich diesen einfach und benenne
                            den neuen entsprechend um.

                  2. Hallo Cybaer,

                    auch denkbar, aber leider nicht (für mein Problem) funktional, da ich ja weiß das ALLE Dateien falsche Rechte haben, da diese ja durch ein PHP-Script dorthin erzeugt worden sind.
                    Bin gerade dran den Lösungsansatz von Mike auszuprobieren, werde das Ergebnis selbstverständlich hier posten...

                    Gruss
                    Dieter

                    1. Hi,

                      auch denkbar, aber leider nicht (für mein Problem) funktional, da ich ja weiß das ALLE Dateien falsche Rechte haben, da diese ja durch ein PHP-Script dorthin erzeugt worden sind.

                      Das wäre egal, da die Dateien, die beim ersten Durchlauf geändert wurden, beim 2. Durchlauf nicht mehr geändert werden. Der Rest wird beim 3., 4., ... Durchlauf geändert. ;-)

                      Bin gerade dran den Lösungsansatz von Mike auszuprobieren, werde das Ergebnis selbstverständlich hier posten...

                      Sollte klappen. :-)

                      Gruß, Cybaer

                      --
                      Hinweis an Fragesteller: Fremde haben ihre Freizeit geopfert, um Dir zu helfen. Helfe Du auch im Archiv Suchenden: Beende deinen Thread mit einem "Hat geholfen" oder "Hat nicht geholfen"!
                      1. Hallo Cybaer,

                        Sollte klappen. :-)

                        Und wenn nicht, hab ich auch noch ne Idee... ;-)

                        Grüße

                        Marc Reichelt || http://www.marcreichelt.de/

                        --
                        Linux is like a wigwam - no windows, no gates and an Apache inside!
                        Selfcode: ie:{ fl:| br:> va:} ls:< fo:} rl:( n4:( ss:) de:> js:| ch:? sh:| mo:) zu:)
                        http://emmanuel.dammerer.at/selfcode.html
        2. Moin Dieter,

          komme ich sehr schnell an die Leistungsgrenzen, besser gesagt an die Zeitbegrenzung, und da das Script ja jedesmal von vorne anfängt, bringt micht das nicht wirklich weiter.

          darfst Du exec oder system ausführen?
          Dann könntest Du das Kommando dort ausführen:
          chmod xxx *

          regds
          Mike©

          --
          Freunde kommen und gehen. Feinde sammeln sich an.
        3. Hallo,

          erstens könntest Du die Aufgabe aufteilen, also erst alle mit "a*" dann alle mit "b*" usw. Wie Du das teist, musst Du selber wissen, weil ich Deine Nomenklatur nciht kenne.

          Hast Du schon mal versucht, ob glob() noch alle Dateien ins Array einlesen kann? Miss doch mal, wie lange das dauert. Könnte natürlich sein, dass Du die Speichergrenze sprengst. Ist ein Speicherlimit gesetzt, und wie hoch ist es?

          Dann erstell Dir ein Direct-Access-File mittels gefilterten glob()s und arbeite dann später das File ab. Da kannst Du ja an jeder Stelle zum Lesen aufsetzen.

          Und was sagt set_time_limit() bei Dir?
          http://de.php.net/manual/en/function.set-time-limit.php
          Darst Du das benutzen oder ist es bei Dir ausgeschaltet?

          LG
          Chris

    2. Moin!

      wieso geht denn

      chmod [-R] xxx * mit xxx = Deine zu vergebenden Rechte

      nicht ?

      Das funktioniert bei zuvielen Dateien selbst auf der Shell nicht mehr!

      Der * wird von der Shell expandiert, bevor die daraus resultierenden Dateien an chmod weitergegeben werden. Bei 200.000 Dateien überschreitet das Resultat mit Sicherheit die Begrenzung der Kommandolänge.

      Als Abhilfe muß man sich dann eine for-Schleife nehmen, die nacheinander jede Datei bearbeitet.

      - Sven Rautenberg

      --
      My sssignature, my preciousssss!
      1. Moin Sven,

        Das funktioniert bei zuvielen Dateien selbst auf der Shell nicht mehr!

        Der * wird von der Shell expandiert, bevor die daraus resultierenden Dateien an chmod weitergegeben werden. Bei 200.000

        Indeed, daran habe ich gar nicht gedacht. Wahrscheinlich gibt es den Fehler [...]list to long [...]

        regds
        Mike©

        --
        Freunde kommen und gehen. Feinde sammeln sich an.
        1. Hi,

          Der * wird von der Shell expandiert, bevor die daraus resultierenden Dateien an chmod weitergegeben werden. Bei 200.000

          Indeed, daran habe ich gar nicht gedacht. Wahrscheinlich gibt es den Fehler [...]list to long [...]

          ja - Abhilfe schafft z.B. ein find i.V.m. xargs:

          find . -maxdepth 1 -type f -print0 | xargs -0 chmod 644

          würde z.B. allen Dateien im aktuellen Verzeichnis 644 geben.

          Das müsste auch via PHP und exec() o.ä., selbst auf einem Shared-Hosting-System gehen?!

          Gruß,
          Andreas.

          1. Sup!

            find . -maxdepth 1 -type f -print0 | xargs -0 chmod 644

            würde z.B. allen Dateien im aktuellen Verzeichnis 644 geben.

            Das müsste auch via PHP und exec() o.ä., selbst auf einem Shared-Hosting-System gehen?!

            Für soooo komplexe Shell-Anweisungen sind PHPler nicht klug genug, die programmieren lieber alles nochmal in PHP nach, unter Verwendung von Datenbanken etc... *fg*

            Gruesse,

            Bio

            --
            Never give up, never surrender!!!
            1. Moin Bio,

              Für soooo komplexe Shell-Anweisungen sind PHPler nicht klug genug, die programmieren lieber alles nochmal in PHP nach, unter Verwendung von Datenbanken etc... *fg*

              mein Spaß-O-meter macht hier nur einen winzigen Ausschlag.
              Nach dreimaligem Lesen erfolgt jedoch ein *GRINS*

              Bio

              regds
              Mike©

              --
              Freunde kommen und gehen. Feinde sammeln sich an.
            2. Hallo Bio,

              find . -maxdepth 1 -type f -print0 | xargs -0 chmod 644

              würde z.B. allen Dateien im aktuellen Verzeichnis 644 geben.

              Das müsste auch via PHP und exec() o.ä., selbst auf einem Shared-Hosting-System gehen?!

              Für soooo komplexe Shell-Anweisungen sind PHPler nicht klug genug, die programmieren lieber alles nochmal in PHP nach, unter Verwendung von Datenbanken etc... *fg*

              Hey, soll das etwa eine Anspielung sein? ;-)

              Mit dem Befehl würde es natürlich auch gehen, sogar schneller und besser.
              Allerdings funktioniert dieser Befehl genau dann nicht mehr, wenn man keine Möglichkeit hat, einen Befehl via exec() auf dem System auszuführen.

              Außerdem:
              Wozu um Gottes Willen läuft PHP bei einigen Benutzern als root? Das ist, als würde man den Teufel persönlich darum bitten, die eigene Seele herauszureißen...

              Grüße

              Marc *SCNR* Reichelt || http://www.marcreichelt.de/

              --
              Linux is like a wigwam - no windows, no gates and an Apache inside!
              Selfcode: ie:{ fl:| br:> va:} ls:< fo:} rl:( n4:( ss:) de:> js:| ch:? sh:| mo:) zu:)
              http://emmanuel.dammerer.at/selfcode.html
              1. Tachschoen,

                Außerdem:
                Wozu um Gottes Willen läuft PHP bei einigen Benutzern als root? Das ist, als würde man den Teufel persönlich darum bitten, die eigene Seele herauszureißen...

                Ich bin außerordentlich froh, dass die Frage jemand stellt. Und die Antwort würde mich echt interessieren :)

                bye,
                   -neri

  2. Moin Dieter,

    Besteht eine Möglichkeit, alle Dateien per PHP-Script (da PHP als Root ausgeführt wird wäre das dann ja möglich) mit neuen rechten zu versehen ? Der Befehl "chmod()" ist bekannt, kann ich aber kaum verwenden, denn wie gesagt es sind über 200.000 einzelne Dateien...

    du kannst das Verzeichnis mit PHP readdir auslesen, und jeder einzelnen Datei einen chmod verpassen.
    Eventuell mußt Du bei 200.000 Dateien ein Augenmerk auf die Laufzeit haben.

    regds
    Mike©

    --
    Freunde kommen und gehen. Feinde sammeln sich an.
  3. Hallo Dieter,

    Ich habe folgendes Problem:
    In einem Verzeichnis liegen etwas über 200.000 einzelne Dateien, diese sind widerrum direkt durch ein PHP-Script dorthin gespeichert worden (werden auch durch Script aufgerufen), leider (mein Fehler) aber mit der Rechtevergabe 0600 - das hat zur Folge, das ich diese Dateien per Standart-FTP (Webbenutzer/kein Root) NICHT laden kann.
    Meine Frage daher:
    Besteht eine Möglichkeit, alle Dateien per PHP-Script (da PHP als Root ausgeführt wird wäre das dann ja möglich) mit neuen rechten zu versehen ? Der Befehl "chmod()" ist bekannt, kann ich aber kaum verwenden, denn wie gesagt es sind über 200.000 einzelne Dateien...

    Hier gab es ja mittlerweile ein paar Ansätze. Ich habe noch einen:

    1. Mit einem PHP-Skript werden alle Dateien gesucht (readdir) und deren Pfade in eine MySQL-Tabelle geschrieben.
    2. Mit einem zweiten Skript kannst du einfach alle Zeilen auswählen, und der Reihe nach chmod setzen. Sobald der chmod gesetzt wird, wird die entsprechende Zeile gelöscht.
    3. Dieses zweite Skript läuft so oft, bis es keine Datensätze mehr gibt.

    Ist das ein nützlicher Ansatz für dich? :-)

    Grüße

    Marc Reichelt || http://www.marcreichelt.de/

    --
    Linux is like a wigwam - no windows, no gates and an Apache inside!
    Selfcode: ie:{ fl:| br:> va:} ls:< fo:} rl:( n4:( ss:) de:> js:| ch:? sh:| mo:) zu:)
    http://emmanuel.dammerer.at/selfcode.html
    1. Hi,

      1. Dieses zweite Skript läuft so oft, bis es keine Datensätze mehr gibt.

      200.000 SQL-Zugriffe? Und Du fürchtest Dich um das Auslesen von Dateirechten? =;-)

      Gruß, Cybaer

      --
      Hinweis an Fragesteller: Fremde haben ihre Freizeit geopfert, um Dir zu helfen. Helfe Du auch im Archiv Suchenden: Beende deinen Thread mit einem "Hat geholfen" oder "Hat nicht geholfen"!
      1. Hallo

        200.000 SQL-Zugriffe? Und Du fürchtest Dich um das Auslesen von Dateirechten? =;-)

        400.000 :-) Du hast entweder die INSERT- oder die DELETE-Statements vergessen.

        Freundliche Grüße

        Vinzenz, der zu spät kam.

      2. Hallo Cybaer,

        1. Dieses zweite Skript läuft so oft, bis es keine Datensätze mehr gibt.

        200.000 SQL-Zugriffe? Und Du fürchtest Dich um das Auslesen von Dateirechten? =;-)

        Mein Ansatz habe ich ganz bewusst gewählt. Denn mit zunehmender Anzahl der Skriptdurchläufe steigt die Performance hier an. Zudem kann man sich mit dem Befehl LIMIT eine bestimmte Anzahl von Datensätze geben lassen, um den Datenverkehr zwischen PHP und MySQL etwas einzudämmen. Ich würde es jedenfalls so machen.

        Bestimmt kann man doch folgendes machen:

        1. SELECT id, path FROM paths ORDER BY id LIMIT 500
        2. chmod mit PHP bei diesen Pfaden ausführen
        3. DELETE * FROM paths ORDER BY id LIMIT 500

        Die Frage ist nur, ob MySQL hier die bei den einzelnen Befehlen die gleichen Zeilen auswählt - was es durch das "ORDER BY id" ja machen sollte.

        Die Zahl kann natürlich auf 100 oder ähnlich angepasst werden, je nach Verlangen.

        Grüße

        Marc Reichelt || http://www.marcreichelt.de/

        --
        Linux is like a wigwam - no windows, no gates and an Apache inside!
        Selfcode: ie:{ fl:| br:> va:} ls:< fo:} rl:( n4:( ss:) de:> js:| ch:? sh:| mo:) zu:)
        http://emmanuel.dammerer.at/selfcode.html