SSD Nodes Learn 🎉 VPS od $5.50/mies.
Przewodniki Matt ConnorAutor: Matt Connor

chmod numerycznie czy symbolicznie: różnice i przykłady

Poznaj różnice między trybem ósemkowym a symbolicznym w chmod. Dowiedz się, dlaczego rekurencyjne nadawanie uprawnień numerycznych psuje katalogi i jak używać flagi X.

Co zmienia polecenie chmod

chmod zmienia bity uprawnień pliku lub katalogu i akceptuje je w jednym z dwóch formatów. Postać numeryczna to liczba ósemkowa, która zastępuje wszystkie bity uprawnień jednocześnie. Postać symboliczna wskazuje klasę użytkownika oraz operatora i modyfikuje tylko wskazane bity. Obie formy kończą się tym samym wywołaniem systemowym. Różnica polega na tym, co dzieje się z bitami, które nie zostały wymienione.

Odczytywanie trybu i jego zmiana to odrębne zadania. Jeśli znaczenie liter w długim formacie listy nie jest jeszcze jasne, najpierw przeczytaj co oznacza drwxr-xr-x pole po polu. Ten przewodnik skupia się wyłącznie na ich zmianie.

Wszystkie poniższe polecenia należy wykonywać jako zwykły użytkownik. Konto root pomija te sprawdzenia, więc demonstracja uprawnień wykonana z konta root niczego nie dowodzi. Jeśli na nowym serwerze nadal pracujesz jako root, utwórz zwykłego użytkownika z ograniczonymi uprawnieniami i wróć tutaj.

Konfiguracja tymczasowego środowiska testowego

cd "$(mktemp -d)"
touch notes.txt

mktemp -d tworzy pusty katalog w /tmp i wyświetla wygenerowaną ścieżkę, a podstawienie polecenia przekazuje tę ścieżkę bezpośrednio do cd. Żadne z poniższych działań nie wpływa na istotne pliki w systemie.

Jedno polecenie raportuje wynik każdej zmiany:

stat -c '%a %A %n' notes.txt

%a wyświetla uprawnienia w formacie ósemkowym, %A wyświetla te same uprawnienia w formie literowej używanej w długiej liście plików, a %n wyświetla nazwę. W poniższych blokach linia zaczynająca się od $ oznacza wpisywaną komendę, a linia poniżej to wynik jej działania. Należy wykonać je samodzielnie. Wynik na danym urządzeniu powinien być identyczny linia po linii, ponieważ tryb numeryczny nie zależy od żadnych zmiennych środowiskowych.

Zapis numeryczny: jedna cyfra ósemkowa na klasę

Pierwsza cyfra odnosi się do właściciela pliku. Druga dotyczy grupy pliku. Trzecia odnosi się do wszystkich pozostałych użytkowników. Każda cyfra jest sumą wartości poszczególnych bitów. Ustaw jeden bit naraz i sprawdź, co raportuje stat.

$ 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.txt

Litery odpowiadają cyfrom. Po początkowym znaku typu pliku, pierwsza grupa trzech liter dotyczy właściciela, kolejne trzy grupy, a ostatnie trzy wszystkich pozostałych. Dodaj wartości, aby połączyć bity wewnątrz jednej klasy.

$ 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.txt

Tryb numeryczny jest bezwzględny. Zapisuje on wszystkie dziewięć bitów przy każdym uruchomieniu, więc klasa, o której nie pomyślałeś, również zostanie nadpisana.

$ 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.txt

Drugie polecenie nie zawierało żadnych informacji o grupie ani o pozostałych użytkownikach, a ich bity i tak uległy zmianie. Taka jest natura zapisu numerycznego i dlatego jest on niewłaściwym narzędziem do wprowadzania drobnych zmian. (chmod obsługuje również bity setuid, setgid oraz sticky, które znajdują się w czwartej cyfrze przed pozostałymi. Jest to osobny temat, a niniejszy przewodnik ogranicza się do trzech cyfr.)

Symboliczna postać: klasa, operator, a następnie bity

Najpierw należy określić klasę. u to właściciel, g to grupa, o to wszyscy pozostali, a a to wszystkie te grupy jednocześnie. Następnie należy podać operator: + dodaje bity, - usuwa bity, a = ustawia klasę dokładnie na wymienione bity i czyści pozostałe. Na końcu podaje się same bity, jako r, w lub 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.txt

Każde polecenie modyfikuje jedną klasę, pozostawiając pozostałe bez zmian. Klauzule można łączyć przecinkami bez spacji, a chmod przetwarza je od lewej do prawej.

$ 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.txt

go= bez żadnych znaków po znaku równości usuwa wszystkie bity z grupy oraz od pozostałych użytkowników. Jest to pożądany stan dla pliku, który może odczytać tylko jego właściciel, na przykład dla prywatnej części pary kluczy SSH.

Polecenie chmod może również raportować swoje działania, co jest istotne w skryptach, gdzie nikt nie obserwuje ekranu na bieżąco.

chmod -v u+x notes.txt
chmod -v u+x notes.txt

-v wyświetla wiersz dla każdego przetworzonego pliku. Po wykonaniu obu poleceń i porównaniu wierszy na ekranie widać, że pierwsze polecenie podaje nazwę pliku oraz raportuje tryb przed zmianą i po niej, natomiast drugie raportuje tryb jako zachowany, ponieważ bit, który miał zostać dodany, był już ustawiony. -c wyświetla wiersz tylko wtedy, gdy plik faktycznie uległ zmianie, dlatego jest to lepszy wybór do prowadzenia dziennika zdarzeń.

chmod 755 a u+x: której notacji używać

Rozpocznij dwukrotnie od tego samego pliku i porównaj, co pozostawia po sobie każda z notacji.

$ 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.txt

Oba polecenia uczyniły plik wykonywalnym dla jego właściciela. Tylko jedno z nich pozostawiło pozostałe dwie klasy uprawnień w niezmienionym stanie. Używaj trybu numerycznego, gdy znasz dokładny stan końcowy, który chcesz osiągnąć i wymusić – jest to właściwe podejście w skrypcie wdrożeniowym, który musi wygenerować ten sam wynik na maszynie, której wcześniej nie widziałeś. Używaj trybu symbolicznego, gdy Twoja intencja zawiera słowa dodaj lub usuń, ponieważ forma numeryczna nie pozwala na wskazanie, aby pozostawić daną część bez zmian.

Tryb, z jakim startuje nowy plik, nie pochodzi z polecenia chmod. Wynika on z wartości umask procesu, który utworzył plik. Uruchom umask oraz umask -S we własnej powłoce, aby sprawdzić aktualnie obowiązującą wartość. Należy oczekiwać, że będzie się ona różnić w zależności od dystrybucji, powłoki logowania a usługi systemd, a także pomiędzy poszczególnymi kontami użytkowników. Umask ustala tryb każdego nowego pliku, więc decyduje o stanie początkowym, zanim uruchomione zostanie polecenie chmod.

Działanie bitu wykonywania dla katalogu

To nieporozumienie generuje najwięcej straconego czasu. W przypadku zwykłego pliku bit wykonywania oznacza, że jądro może uruchomić dany plik. Katalog nie zawiera instrukcji, więc nie ma w nim nic do uruchomienia. W odniesieniu do katalogu bit wykonywania oznacza możliwość przejścia: uprawnienie do rozpoznawania nazw wewnątrz niego. Aby uzyskać dostęp do dir/file, wymagane jest posiadanie tego bitu na dir. Bit odczytu jest osobnym uprawnieniem i pozwala na wyświetlenie listy nazw zawartych w katalogu. Można posiadać jeden z nich bez drugiego, co łatwiej zrozumieć po zaobserwowaniu tego w praktyce.

$ mkdir vault
$ printf 'hello\n' > vault/secret.txt
$ chmod 600 vault/secret.txt
$ chmod 100 vault
$ echo vault/*
vault/*
$ cat vault/secret.txt
hello

Powłoka zwróciła wzorzec w niezmienionej formie, ponieważ rozwinięcie vault/* wymaga odczytu katalogu, a glob, który nie pasuje do żadnego elementu jest przekazywany jako tekst dosłowny zamiast generowania błędu. cat nadal działało, ponieważ nazwa została podana bezpośrednio, a przejście było dozwolone. Teraz należy zamienić oba bity.

$ chmod 400 vault
$ echo vault/*
vault/secret.txt
$ cat vault/secret.txt
cat: vault/secret.txt: Permission denied

Nazwy są widoczne, ale zawartość nie. Odczyt zapewnia listę. Wykonywanie zapewnia dostęp. Prawie każdy używany katalog wymaga obu tych uprawnień.

$ chmod 500 vault
$ cat vault/secret.txt
hello

Dlaczego chmod -R z numerycznym trybem niszczy strukturę plików

-R przechodzi przez całe drzewo katalogów i stosuje podany tryb do każdego napotkanego elementu. Katalogi oraz pliki danych wymagają różnych uprawnień, dlatego jedna liczba bezwzględna nie może być poprawna dla obu typów. Utwórz małe drzewo katalogów i obserwuj, jak proces kończy się niepowodzeniem.

$ 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.sh

To jest układ uprawnień wymagany dla katalogu z plikami statycznymi. Oto pierwszy błąd przy użyciu rekurencji.

$ 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.css

Nic nie uległo awarii i to jest główny problem. Ten błąd nie generuje komunikatów, więc przez lata powielany jest w kopiowanych instrukcjach. Dwa pliki danych są teraz oznaczone jako programy. Git przechowuje bit wykonywalności, więc kolejny commit przeniesie tę zmianę na każdego, kto sklonuje repozytorium, a rsync oraz tar przeniosą ją na każdą maszynę, na którą skopiujesz drzewo plików.

Drugi błąd przy użyciu rekurencji jest wyraźnie widoczny. Zastosowanie trybu bez bitu wykonywalności do katalogu powoduje jego zablokowanie.

$ 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 denied

Nazwy plików są nadal widoczne, ponieważ bit odczytu został zachowany, ale każda ścieżka prowadząca przez katalog jest zamknięta, ponieważ bit wykonywalności został usunięty. chmod -R 644 site wykonuje to na każdym katalogu w drzewie za pomocą jednego polecenia. Stan końcowy nie zawsze jest jednolity, ponieważ chmod musi przechodzić przez te same katalogi, do których dostęp właśnie odbiera, więc sprawdź rzeczywisty stan za pomocą find site -type d -exec stat -c '%a %n' {} +, zamiast zakładać poprawność. Przywróć poprzednie uprawnienia przed kontynuowaniem.

$ 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.html

Rekurencyjne użycie chmod nie posiada funkcji cofania zmian. chmod nie rejestruje tego, co zastąpił, więc naprawa spoczywa na tobie – musisz odtworzyć tryby na podstawie tego, jak według ciebie wyglądały wcześniej. Jest to równie powolna i niepewna praca, co odzyskiwanie plików po przypadkowym rm -rf, a płynąca z tego lekcja jest taka sama: sprawdź cel polecenia rekurencyjnego przed naciśnięciem klawisza Enter.

Wielka litera X: wykonywanie na katalogach, a nie na każdym pliku

Tryby symboliczne akceptują X, podobnie jak x. X ustawia bit wykonywania tylko tam, gdzie ma to sens: na katalogu lub na zwykłym pliku, który już posiada bit wykonywania dla którejkolwiek z klas. Ta zasada jest dokładnie tą, której oczekiwano od -R.

$ 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.sh

Jedno polecenie sprawiło, że katalogi pozostały dostępne do przeglądania, podczas gdy pliki danych pozostały bez zmian. Skrypt zachował swój bit wykonywania, ponieważ już go posiadał, co stanowi drugą część zasady X. X odczytuje tryb, który plik posiada w danej chwili, więc plik, który utracił wszystkie bity wykonywania, nie może zostać przywrócony za pomocą tego parametru.

$ 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
hi

Ta sama zasada działa w drugą stronę. X rozszerzy bit wykonywania, który plik już posiada, na inną klasę:

$ chmod go+X site/deploy.sh
$ stat -c '%a %A %n' site/deploy.sh
755 -rwxr-xr-x site/deploy.sh

Zatem mała litera x służy do nadawania uprawnień wykonywania konkretnemu plikowi, a X służy do operacji na całym drzewie katalogów. Gdy wymagane jest ustawienie dokładnego trybu dla danego typu obiektu, zamiast polegać na regule opartej na bieżącym trybie, należy rozdzielić operację za pomocą find.

find site -type d -exec chmod 755 {} +
find site -type f -exec chmod 644 {} +
chmod u+x site/deploy.sh

-type d wybiera katalogi, a -type f wybiera zwykłe pliki, dzięki czemu każdy typ otrzymuje właściwy tryb. -exec ... + grupuje wiele ścieżek w jednym wywołaniu chmod, zamiast uruchamiać osobny proces dla każdego pliku, co ma znaczenie w przypadku drzewa zawierającego tysiące elementów. Skrypt odzyskuje swój bit w osobnej linii, co jest działaniem zamierzonym.

Weryfikacja wyniku przed zakończeniem pracy

Dwa polecenia pozwalają wykryć istotne błędy po każdej operacji rekurencyjnej. Pierwsze z nich wyświetla katalogi, do których nie można już wejść.

find . -type d ! -perm -u+x

Drugie polecenie wyświetla pliki, które może edytować dowolne konto w systemie.

find . -type f -perm -o+w

W -perm -o+w wiodący - oznacza co najmniej te bity, więc dopasowuje pliki, w których klasa o posiada bit zapisu, niezależnie od innych ustawień. Brak danych wyjściowych z obu poleceń jest pożądanym rezultatem. Wykonaj oba polecenia od najwyższego poziomu drzewa, które zostało zmodyfikowane za pomocą -R, a następnie uruchom stat -c '%a %A %n' dla kilku ścieżek, które miały zostać zmienione. Dzięki temu upewnisz się, że uprawnienia zadeklarowane w poleceniu są zgodne z tymi, które faktycznie przechowuje jądro systemu.

FAQ

Jaka jest różnica między chmod 755 a chmod u+x?

Tryb numeryczny jest bezwzględny. Nadpisuje on wszystkie bity uprawnień pliku, przez co klasy, o których nie pomyślano, również zostają zmienione. Tryb symboliczny to edycja. u+x dodaje jeden bit dla właściciela, pozostawiając wszystkie pozostałe bity bez zmian. Formy numerycznej należy używać, gdy znany jest dokładny stan końcowy, który ma zostać osiągnięty dla pliku. Formy symbolicznej należy używać, gdy wymagane jest dodanie lub usunięcie pojedynczego uprawnienia. Uruchomienie stat -c '%a %A %n' <file> przed i po wykonaniu dowolnego z tych poleceń pozwoli zaobserwować różnicę w wyjściu.

Dlaczego chmod -R 755 dla katalogu z plikami WWW jest złym pomysłem?

Ponieważ -R stosuje ten sam bezwzględny tryb zarówno do katalogów, jak i do zwykłych plików, a te dwa typy wymagają różnych bitów. Katalog wymaga bitu wykonywania, aby można było przez niego przechodzić. Pliki danych, takie jak HTML czy CSS, go nie potrzebują, a oznaczenie ich jako wykonywalne jest zmianą, którą git rejestruje w kolejnym commicie, a rsync kopiuje na następną maszynę. Należy użyć chmod -R u=rwX,go=rX <dir>, aby bit wykonywania został nadany tylko katalogom, lub sterować tym z poziomu find za pomocą -type d i -type f, tak aby każdy typ otrzymał właściwy dla siebie tryb.

Co robi bit wykonywania w przypadku katalogu?

Przyznaje on prawo do przechodzenia (traversal), a nie wykonywania. Wewnątrz katalogu nie ma nic, co można by uruchomić. Bit wykonywania to uprawnienie do rozwiązywania nazw wewnątrz katalogu, dlatego jest on niezbędny dla każdego katalogu na ścieżce, aby móc otworzyć plik znajdujący się na jej końcu. Bit odczytu jest oddzielny i przyznaje prawo do wyświetlania nazw plików. Można posiadać jeden bez drugiego: z samym bitem wykonywania można otworzyć plik, którego nazwę już się zna, podczas gdy powłoka nie może rozwinąć wzorca (glob) w tym katalogu; z samym bitem odczytu można zobaczyć nazwy, podczas gdy każda próba otwarcia pliku zakończy się niepowodzeniem.

Kiedy należy używać wielkiej litery X zamiast małej x?

X należy stosować zawsze, gdy polecenie jest rekurencyjne. X ustawia bit wykonywania dla katalogów, a dla zwykłych plików tylko wtedy, gdy przynajmniej jeden bit wykonywania jest już ustawiony. Dzięki temu pojedyncze przejście czyni drzewo katalogów dostępnym, nie zamieniając plików danych w programy. Małej litery x należy używać, gdy wskazuje się na konkretny plik i odnosi się tylko do niego. Warto pamiętać o jednym ograniczeniu: X nie może przywrócić bitu wykonywania, który został całkowicie usunięty z pliku, ponieważ nie ma już żadnego bitu, do którego można by się odnieść. Należy go przywrócić za pomocą chmod u+x <file>.

Czy chmod zmienia właściciela pliku?

Nie. chmod zmienia wyłącznie bity uprawnień. Własność należy do chown w przypadku użytkownika oraz chgrp w przypadku grupy, a przekazanie pliku innemu użytkownikowi wymaga uprawnień root. Jest to istotne, ponieważ bity są interpretowane w odniesieniu do właściciela i grupy zapisanych w pliku, a nie w odniesieniu do tego, kto ostatnio go edytował. Należy uruchomić stat -c '%U %G %a %n' <file>, aby zobaczyć właściciela, grupę oraz tryb przed podjęciem decyzji, które z tych trzech poleceń jest faktycznie potrzebne.