chmod 755 oder u+x: Numerische und symbolische Modi
Erfahren Sie, wie chmod Oktalzahlen sowie u/g/o-Syntax setzt, warum ein rekursiver numerischer Modus Verzeichnisse beschädigt und weshalb X den Unterschied macht.
Was chmod ändert
chmod ändert die Berechtigungsbits einer Datei oder eines Verzeichnisses. Das Programm akzeptiert diese Bits in einer von zwei Schreibweisen. Die numerische Form ist eine Oktalzahl, die alle Berechtigungsbits gleichzeitig ersetzt. Die symbolische Form nennt eine Benutzerklasse und einen Operator. Sie ändert nur die angegebenen Bits. Beide Formen führen letztlich zum selben Systemaufruf. Der Unterschied besteht darin, was mit den nicht angegebenen Bits geschieht.
Das Lesen eines Modus und das Ändern eines Modus sind unterschiedliche Aufgaben. Wenn die Buchstaben in einer langen Verzeichnisauflistung noch nicht vertraut sind, lesen Sie zuerst was drwxr-xr-x Feld für Feld bedeutet. In dieser Anleitung werden nur Berechtigungen geändert.
Führen Sie alle Befehle hier als gewöhnlicher Anmeldebenutzer aus. Der root-Account umgeht diese Prüfungen. Eine als root ausgeführte Demonstration von Berechtigungen ist daher nicht aussagekräftig. Wenn Sie auf einem neuen Server noch als root arbeiten, erstellen Sie einen normalen Benutzer mit geringsten erforderlichen Berechtigungen und kehren Sie anschließend hierher zurück.
Eine wegwerfbare Sandbox einrichten
cd "$(mktemp -d)"
touch notes.txtmktemp -d erstellt ein leeres Verzeichnis unter /tmp und gibt den erzeugten Pfad aus. Befehlssubstitution übergibt diesen Pfad direkt an cd. Keine der folgenden Aktionen verändert eine Datei, die Sie benötigen.
Ein Befehl zeigt das Ergebnis jeder Änderung:
stat -c '%a %A %n' notes.txt%a gibt den Modus als Oktalzahl aus, %A gibt denselben Modus in der Buchstabendarstellung einer langen Verzeichnisauflistung aus, und %n gibt den Namen aus. In den folgenden Blöcken geben Sie die mit $ beginnende Zeile ein. Die Zeile darunter zeigt die Ausgabe des Befehls. Führen Sie die Befehle selbst aus. Die Ausgabe auf Ihrem Rechner sollte zeilenweise übereinstimmen, weil ein numerischer Modus nicht von den Umgebungsbedingungen abhängt.
Die numerische Form: eine Oktalziffer pro Klasse
Die erste Ziffer gehört dem Eigentümer der Datei. Die zweite gehört der Gruppe der Datei. Die dritte gehört allen anderen. Jede Ziffer ist eine Summe, jeweils ein Wert pro Bit. Setzen Sie immer nur ein Bit und lesen Sie, was stat meldet.
$ chmod 400 notes.txt
$ stat -c '%a %A %n' notes.txt
400 -r-------- notes.txt
$ chmod 200 notes.txt
$ stat -c '%a %A %n' notes.txt
200 --w------- notes.txt
$ chmod 100 notes.txt
$ stat -c '%a %A %n' notes.txt
100 ---x------ notes.txtDie Buchstaben entsprechen den Ziffern. Nach dem führenden Zeichen für den Dateityp ist die erste Gruppe aus drei Buchstaben die des Eigentümers, die nächsten drei gehören der Gruppe und die letzten drei allen anderen. Addieren Sie die Werte, um Bits innerhalb einer Klasse zu kombinieren.
$ chmod 600 notes.txt
$ stat -c '%a %A %n' notes.txt
600 -rw------- notes.txt
$ chmod 700 notes.txt
$ stat -c '%a %A %n' notes.txt
700 -rwx------ notes.txt
$ chmod 750 notes.txt
$ stat -c '%a %A %n' notes.txt
750 -rwxr-x--- notes.txtEin numerischer Modus ist absolut. Bei jedem Aufruf schreibt er alle neun Bits. Dadurch wird auch eine Klasse geschrieben, an die Sie nicht gedacht haben.
$ chmod 755 notes.txt
$ stat -c '%a %A %n' notes.txt
755 -rwxr-xr-x notes.txt
$ chmod 600 notes.txt
$ stat -c '%a %A %n' notes.txt
600 -rw------- notes.txtDer zweite Befehl enthielt keine Angaben zur Gruppe oder zu allen anderen. Trotzdem änderten sich deren Bits. Das ist die Eigenschaft der numerischen Form. Deshalb ist die numerische Form das falsche Werkzeug für eine kleine Änderung. (chmod verarbeitet auch die setuid-, setgid- und Sticky-Bits. Diese stehen in einer vierten Ziffer vor den hier beschriebenen Ziffern. Das ist ein separates Thema. Diese Anleitung beschränkt sich auf die drei Ziffern.)
Die symbolische Schreibweise: eine Klasse, ein Operator, dann die Bits
Schreiben Sie zuerst die Klasse. u steht für den Eigentümer, g für die Gruppe, o für alle anderen und a für alle drei Klassen gleichzeitig. Danach folgt der Operator: + fügt Bits hinzu, - entfernt Bits und = setzt diese Klasse genau auf die angegebenen Bits und löscht ihre übrigen Bits. Danach folgen die Bits selbst: r, w oder x.
$ chmod 640 notes.txt
$ stat -c '%a %A %n' notes.txt
640 -rw-r----- notes.txt
$ chmod u+x notes.txt
$ stat -c '%a %A %n' notes.txt
740 -rwxr----- notes.txt
$ chmod g-r notes.txt
$ stat -c '%a %A %n' notes.txt
700 -rwx------ notes.txt
$ chmod o=r notes.txt
$ stat -c '%a %A %n' notes.txt
704 -rwx---r-- notes.txtJeder Befehl bearbeitete eine Klasse und ließ die anderen unverändert. Kombinieren Sie Klauseln durch Kommas ohne Leerzeichen. chmod wendet sie von links nach rechts an.
$ chmod u=rw,go=r notes.txt
$ stat -c '%a %A %n' notes.txt
644 -rw-r--r-- notes.txt
$ chmod go= notes.txt
$ stat -c '%a %A %n' notes.txt
600 -rw------- notes.txtgo= ohne Zeichen nach dem Gleichheitszeichen entfernt alle Bits aus der Gruppe und von allen anderen. Das ist die gewünschte Einstellung für eine Datei, die nur ihr Eigentümer lesen darf, beispielsweise für den privaten Teil eines SSH-Schlüsselpaars.
chmod kann seine eigenen Änderungen auch ausgeben. Das ist in einem Skript wichtig, wenn niemand den Bildschirm überwacht.
chmod -v u+x notes.txt
chmod -v u+x notes.txt-v gibt für jede übergebene Datei eine Zeile aus. Führen Sie beide Befehle aus und vergleichen Sie die beiden Zeilen auf dem Bildschirm: Die erste nennt die Datei und zeigt den Modus an, von dem geändert wurde, sowie den neuen Modus. Die zweite meldet den Modus als unverändert, weil das hinzuzufügende Bit bereits gesetzt war. -c gibt nur dann eine Zeile aus, wenn eine Datei tatsächlich geändert wurde. Daher eignet sich dieser Befehl besser für die Protokollierung.
chmod 755 gegenüber u+x: Welche Schreibweise sollten Sie verwenden?
Starten Sie zweimal mit derselben Datei und vergleichen Sie, was jede Schreibweise zurücklässt.
$ chmod 640 notes.txt
$ chmod 755 notes.txt
$ stat -c '%a %A %n' notes.txt
755 -rwxr-xr-x notes.txt
$ chmod 640 notes.txt
$ chmod u+x notes.txt
$ stat -c '%a %A %n' notes.txt
740 -rwxr----- notes.txtBeide Befehle machten die Datei für ihren Eigentümer ausführbar. Nur einer von ihnen ließ die beiden anderen Klassen unverändert. Verwenden Sie einen numerischen Modus, wenn Sie den genauen Endzustand kennen, den Sie erzwingen möchten. Das ist beispielsweise in einem Deployment-Skript der richtige Ansatz, das auf einer unbekannten Maschine immer dasselbe Ergebnis erzeugen muss. Verwenden Sie einen symbolischen Modus, wenn Ihre Formulierung hinzufügen oder entfernen enthält. Die numerische Schreibweise kann nicht ausdrücken, dass ein Teil unverändert bleiben soll.
Der Modus, mit dem eine neue Datei beginnt, stammt nicht von chmod. Er wird durch die umask des Prozesses festgelegt, der die Datei erstellt hat. Führen Sie umask und umask -S in Ihrer eigenen Shell aus, um den dort geltenden Wert anzuzeigen. Rechnen Sie damit, dass er sich zwischen Distributionen, zwischen Ihrer Login-Shell und einem systemd-Dienst sowie zwischen verschiedenen Konten unterscheidet. Die umask legt den Modus jeder neuen Datei fest. Dadurch bestimmt sie den Ausgangszustand, bevor chmod ausgeführt wird.
Was das Ausführungsbit für ein Verzeichnis bewirkt
Dies ist das Missverständnis, das am meisten Zeit kostet. Bei einer regulären Datei gibt das Ausführungsbit an, dass der Kernel die Datei ausführen darf. Ein Verzeichnis enthält keine Anweisungen. Daher gibt es darin nichts auszuführen. Bei einem Verzeichnis bedeutet das Ausführungsbit Traversierung: die Berechtigung, einen Namen darin aufzulösen. Um dir/file zu erreichen, benötigen Sie dieses Bit für dir. Das Lesebit ist eine separate Berechtigung. Es ermöglicht das Auflisten der im Verzeichnis enthaltenen Namen. Sie können jeweils eines der beiden Bits ohne das andere besitzen. Das wird verständlicher, sobald Sie dieses Verhalten selbst beobachtet haben.
$ mkdir vault
$ printf 'hello\n' > vault/secret.txt
$ chmod 600 vault/secret.txt
$ chmod 100 vault
$ echo vault/*
vault/*
$ cat vault/secret.txt
helloDie Shell hat das Muster unverändert ausgegeben, weil die Erweiterung von vault/* das Lesen des Verzeichnisses erfordert. Ein Glob-Muster ohne Treffer wird als literaler Text weitergegeben, statt einen Fehler auszulösen. cat hat weiterhin funktioniert, weil Sie den Namen selbst angegeben haben und die Traversierung erlaubt war. Tauschen Sie nun die beiden Bits.
$ chmod 400 vault
$ echo vault/*
vault/secret.txt
$ cat vault/secret.txt
cat: vault/secret.txt: Permission deniedDie Namen sind sichtbar, der Inhalt jedoch nicht. Das Leserecht liefert die Liste. Das Ausführungsrecht ermöglicht den Zugriff. Fast jedes Verzeichnis, das Sie verwenden, benötigt beide Berechtigungen.
$ chmod 500 vault
$ cat vault/secret.txt
helloWarum chmod -R mit einem numerischen Modus einen Verzeichnisbaum beschädigt
-R durchläuft den gesamten Verzeichnisbaum und wendet den angegebenen Modus auf alles an, was dabei gefunden wird. Ein Verzeichnis und eine Datendatei benötigen unterschiedliche Bits. Eine einzige absolute Zahl kann daher nicht für beide korrekt sein. Erstellen Sie einen kleinen Verzeichnisbaum und beobachten Sie den Fehler.
$ mkdir -p site/css
$ touch site/index.html site/css/main.css
$ printf '#!/bin/bash\necho hi\n' > site/deploy.sh
$ chmod 755 site site/css site/deploy.sh
$ chmod 644 site/index.html site/css/main.css
$ stat -c '%a %A %n' site site/css site/index.html site/css/main.css site/deploy.sh
755 drwxr-xr-x site
755 drwxr-xr-x site/css
644 -rw-r--r-- site/index.html
644 -rw-r--r-- site/css/main.css
755 -rwxr-xr-x site/deploy.shDas ist die Struktur, die ein Verzeichnis mit statischen Dateien benötigt. Hier ist der erste rekursive Fehler.
$ chmod -R 755 site
$ stat -c '%a %A %n' site/index.html site/css/main.css
755 -rwxr-xr-x site/index.html
755 -rwxr-xr-x site/css/main.cssNichts ist kaputtgegangen. Genau das ist das Problem. Dieser Fehler bleibt unbemerkt und wird deshalb über Jahre in kopierten Anleitungen weitergegeben. Zwei Datendateien sind jetzt als Programme markiert. Git speichert das Execute-Bit. Der nächste Commit überträgt die Änderung daher an alle, die das Repository klonen. rsync und tar übertragen sie außerdem auf jeden Rechner, auf den Sie den Verzeichnisbaum kopieren.
Der zweite rekursive Fehler ist offensichtlich. Wenden Sie einen Modus ohne Execute-Bit auf ein Verzeichnis an, wird das Verzeichnis unzugänglich.
$ chmod 644 site
$ stat -c '%a %A %n' site
644 drw-r--r-- site
$ echo site/*
site/css site/deploy.sh site/index.html
$ cd site
bash: cd: site: Permission denied
$ cat site/index.html
cat: site/index.html: Permission deniedDie Namen werden weiterhin aufgelistet, weil das Read-Bit erhalten geblieben ist. Jeder Pfad durch das Verzeichnis ist jedoch unzugänglich, weil das Execute-Bit fehlt. chmod -R 644 site verursacht das mit jedem Verzeichnis im Verzeichnisbaum in einem einzigen Befehl. Das Ergebnis ist danach nicht immer einheitlich. chmod muss dieselben Verzeichnisse durchlaufen, deren Traversierung es gerade entfernt. Prüfen Sie daher mit find site -type d -exec stat -c '%a %n' {} +, was tatsächlich angewendet wurde, statt davon auszugehen. Stellen Sie diesen Zustand wieder her, bevor Sie fortfahren.
$ chmod 755 site
$ chmod 644 site/index.html site/css/main.css
$ stat -c '%a %A %n' site site/index.html
755 drwxr-xr-x site
644 -rw-r--r-- site/index.htmlEin rekursiver chmod kann nicht rückgängig gemacht werden. chmod speichert nicht, welche Berechtigungen ersetzt wurden. Sie müssen die Modi daher anhand Ihrer Annahme über den ursprünglichen Zustand neu aufbauen. Das ist dieselbe langsame und unsichere Arbeit wie beim Wiederherstellen von Dateien nach einem versehentlichen rm -rf. Die Lehre ist ebenfalls dieselbe: Prüfen Sie das Ziel eines rekursiven Befehls, bevor Sie die Eingabetaste drücken.
Das große X: Ausführungsrechte für Verzeichnisse, nicht für jede Datei
Symbolische Modi akzeptieren sowohl X als auch x. X setzt das Ausführungsbit nur dort, wo es sinnvoll ist: bei einem Verzeichnis oder bei einer regulären Datei, die für mindestens eine Klasse bereits ein Ausführungsbit besitzt. Genau dieser Regel sollte -R folgen.
$ chmod -R u=rwX,go=rX site
$ stat -c '%a %A %n' site site/css site/index.html site/css/main.css site/deploy.sh
755 drwxr-xr-x site
755 drwxr-xr-x site/css
644 -rw-r--r-- site/index.html
644 -rw-r--r-- site/css/main.css
755 -rwxr-xr-x site/deploy.shEin Befehl genügt. Die Verzeichnisse blieben durchsuchbar, während die Datendateien unverändert blieben. Das Skript behielt sein Ausführungsbit, weil es bereits eines besaß. Das ist die zweite Hälfte der Regel X. X berücksichtigt die aktuellen Modusbits einer Datei. Eine Datei, bei der bereits alle Ausführungsbits entfernt wurden, kann damit nicht wieder ausführbar gemacht werden.
$ chmod 644 site/deploy.sh
$ chmod -R u=rwX,go=rX site
$ stat -c '%a %A %n' site/deploy.sh
644 -rw-r--r-- site/deploy.sh
$ site/deploy.sh
bash: site/deploy.sh: Permission denied
$ chmod u+x site/deploy.sh
$ stat -c '%a %A %n' site/deploy.sh
744 -rwxr--r-- site/deploy.sh
$ site/deploy.sh
hiDieselbe Regel funktioniert auch umgekehrt. X überträgt ein bereits vorhandenes Ausführungsbit auf eine weitere Klasse:
$ chmod go+X site/deploy.sh
$ stat -c '%a %A %n' site/deploy.sh
755 -rwxr-xr-x site/deploy.shDas kleingeschriebene x ist also für eine einzelne Datei gedacht, die Sie ausführbar machen möchten. X ist für die Verarbeitung eines gesamten Verzeichnisbaums gedacht. Wenn Sie für jede Art von Eintrag einen exakten Modus statt einer Regel auf Grundlage des aktuellen Modus festlegen möchten, teilen Sie die Suche stattdessen mit find auf.
find site -type d -exec chmod 755 {} +
find site -type f -exec chmod 644 {} +
chmod u+x site/deploy.sh-type d wählt Verzeichnisse aus, und -type f wählt reguläre Dateien aus. Dadurch erhält jede Art von Eintrag den vorgesehenen Modus. -exec ... + übergibt viele Pfade gebündelt an einen einzigen chmod-Aufruf, statt für jede Datei einen eigenen Prozess zu starten. Das ist bei einem Verzeichnisbaum mit Tausenden von Einträgen relevant. Das Skript erhält sein Ausführungsbit bewusst in einer separaten Zeile zurück.
Prüfen Sie das Ergebnis, bevor Sie die Arbeit beenden
Mit zwei Befehlen finden Sie die relevanten Fehler nach jeder rekursiven Änderung. Der erste listet Verzeichnisse auf, die Sie nicht mehr betreten können.
find . -type d ! -perm -u+xDer zweite listet Dateien auf, die jedes Konto auf dem System bearbeiten kann.
find . -type f -perm -o+wIn -perm -o+w bedeutet das führende - mindestens diese Bits. Dadurch wird eine Datei gefunden, deren o-Klasse das Schreibbit enthält, unabhängig davon, welche weiteren Bits gesetzt sind. Keiner der beiden Befehle sollte eine Ausgabe erzeugen. Führen Sie beide Befehle am Anfang jedes Verzeichnisbaums aus, den Sie gerade mit -R geändert haben. Führen Sie außerdem stat -c '%a %A %n' für die wenigen Pfade aus, die Sie gezielt ändern wollten. So stellen Sie sicher, dass der Modus, den Sie gesetzt zu haben glauben, tatsächlich dem Modus entspricht, den der Kernel gespeichert hat.
FAQ
Was ist der Unterschied zwischen chmod 755 und chmod u+x?
Ein numerischer Modus ist absolut. Er schreibt jedes Berechtigungsbit der Datei und überschreibt daher auch die Klassen, die Sie nicht berücksichtigt haben. Ein symbolischer Modus ist eine Änderung. u+x fügt dem Eigentümer ein Bit hinzu und lässt alle anderen Bits unverändert. Verwenden Sie die numerische Form, wenn Sie den exakten Zielzustand einer Datei kennen. Verwenden Sie die symbolische Form, wenn Sie eine einzelne Berechtigung hinzufügen oder entfernen möchten. Führen Sie stat -c '%a %A %n' <file> vor und nach beiden Befehlen aus. Der Unterschied ist dann in der Ausgabe sichtbar.
Warum ist chmod -R 755 für ein Verzeichnis mit Webdateien problematisch?
Weil -R denselben absoluten Modus auf Verzeichnisse und reguläre Dateien anwendet, obwohl diese unterschiedliche Bits benötigen. Ein Verzeichnis benötigt das Execute-Bit, damit es durchlaufen werden kann. Datendateien wie HTML und CSS benötigen es nicht. Wenn Sie sie als ausführbar markieren, erfasst git diese Änderung im nächsten Commit, und rsync übernimmt sie auf den nächsten Rechner. Verwenden Sie chmod -R u=rwX,go=rX <dir>, damit das Execute-Bit nur auf Verzeichnisse angewendet wird. Alternativ können Sie mit find, -type d und -type f arbeiten, damit jeder Dateityp seinen eigenen Modus erhält.
Was bewirkt das Execute-Bit bei einem Verzeichnis?
Es erlaubt das Durchlaufen des Verzeichnisses, nicht dessen Ausführung. In einem Verzeichnis gibt es nichts, das ausgeführt werden kann. Das Execute-Bit erlaubt die Auflösung eines Namens innerhalb des Verzeichnisses. Daher benötigen Sie es für jedes Verzeichnis entlang eines Pfads, bevor Sie die Datei am Ende dieses Pfads öffnen können. Das Read-Bit ist davon unabhängig und erlaubt das Auflisten der Namen. Sie können das eine Bit ohne das andere besitzen: Mit dem Execute-Bit allein können Sie eine Datei öffnen, deren Namen Sie bereits kennen, während die Shell keinen Glob in diesem Verzeichnis auflösen kann. Mit dem Read-Bit allein können Sie die Namen sehen, aber jeder Versuch, eine Datei zu öffnen, schlägt fehl.
Wann sollte ich das große X statt des kleinen x verwenden?
Verwenden Sie X bei rekursiven Befehlen. X setzt das Execute-Bit auf Verzeichnissen und auf regulären Dateien nur dann, wenn bereits mindestens ein Execute-Bit gesetzt ist. Dadurch wird ein Verzeichnisbaum in einem Durchlauf durchlaufbar, ohne Datendateien in Programme umzuwandeln. Verwenden Sie das kleine x, wenn Sie auf eine einzelne Datei verweisen und genau diese Datei meinen. Eine Einschränkung sollten Sie beachten: X kann ein Execute-Bit nicht wiederherstellen, das bei einer Datei zuvor überall entfernt wurde, weil keine passende Berechtigung mehr vorhanden ist. Setzen Sie dieses Bit in diesem Fall mit chmod u+x <file> wieder.
Ändert chmod den Eigentümer einer Datei?
Nein. chmod ändert nur die Berechtigungsbits. Die Eigentümerschaft wird für den Benutzer durch chown und für die Gruppe durch chgrp festgelegt. Die Übergabe einer Datei an einen anderen Benutzer erfordert root. Das ist wichtig, weil die Bits anhand des auf der Datei gespeicherten Eigentümers und der gespeicherten Gruppe ausgewertet werden, nicht anhand der Person, die die Datei zuletzt geschrieben hat. Führen Sie stat -c '%U %G %a %n' <file> aus, um Eigentümer, Gruppe und Modus gemeinsam anzuzeigen, bevor Sie entscheiden, welchen der drei Befehle Sie tatsächlich benötigen.