chmod rekurencyjne uprawnienia do tysięcy plików

16

To jest bardziej ogólne pytanie dotyczące rekodowania „chmodowania”.

Mam ten skrypt, który w pewnym momencie musi rekurencyjnie zmieniać uprawnienia w folderze zawierającym kilkaset tysięcy plików. W tym folderze są dodawane nowe pliki każdego dnia, ale te, które już tam są, mają już ustawione uprawnienia i nie ulegają zmianie.

Moje pytanie brzmi ... kiedy dzwonię

chmod 775. -R

czy próbuje ustawić uprawnienia dla plików, które mają już ustawione odpowiednie uprawnienia, czy tylko dla nowych plików, które nie mają odpowiednich uprawnień?

Wydaje się, że przekroczenie tej komendy w skrypcie zawsze zajmuje całe wieki, mimo że „nowe” pliki to tylko kilka tysięcy i powinno to zrobić dość szybko.

Przeglądałem stronę podręcznika dla chmod, ale wydaje się, że nie wspomina nic w tej sprawie.

Jeśli chmod nie sprawdzi wcześniej uprawnień, czy powinienem zacząć szukać połączenia „find” z „chmod”?

Titi Dumi
źródło
3
Zastanawiam się, czy naprawdę wolniej jest sprawdzać uprawnienia i je zmieniać, jeśli nie są poprawne, niż bezpośrednio ustawiać na odpowiednią wartość.
lgeorget
1
jeśli ktoś natknie się na to i chce polecenia find + chmod, oto on: find. ! -perm 775 -print0 | xargs -0 -I {} chmod 775 {}
Titi Dumi,
@lgeorget, więc mówisz, że wolniej jest używać find | chmod? niż tylko chmod wszystko. (przepraszam, nie rozumiem z twojego komentarza). na zdrowie
Titi Dumi,
Moim skromnym zdaniem jest to prawdopodobnie wolniejsze, ponieważ musi wydłużyć dwa procesy i przekierować wyjście z pierwszego do drugiego, ale nie jestem pewien. Zależy to od czasu ustawiania uprawnień, co może nie być tak ważne, ponieważ do zmodyfikowania w i-węźle są to tylko 3 bajty.
lgeorget
1
@depquid Głównym problemem związanym z wydajnością jest wczytywanie danych do pamięci podręcznej dysku. Po pierwszym uruchomieniu wszystko znajduje się w pamięci podręcznej dysku (chyba że jest za mało pamięci), dlatego testujesz wydajność czegoś, co nie jest wąskim gardłem w rzeczywistej sytuacji.
Hauke ​​Laging

Odpowiedzi:

9

chmodmoże, ale nie musi, zmienić uprawnienia do plików, które są już ustawione na żądane, ale jeśli nie, nadal będzie musiał je sprawdzić, aby zobaczyć, jakie są ich bieżące uprawnienia [0]. Przy setkach tysięcy plików nie sądzę, by miało to jakiekolwiek znaczenie; czas najprawdopodobniej spędzają narzędzia w statkażdym pliku.

Możesz spróbować użyć finddo sprawdzenia plików nowszych niż ostatnie uruchomienie lub plików, które należy chmoduruchomić, ale nie sądzę, że uzyskasz znaczną poprawę prędkości.

Jeśli jest to możliwe dla skryptu, możesz najpierw umieścić nowe pliki w osobnym katalogu, jako obszar „trzymania”. Następnie możesz chmodTEGO katalogu (który ma tylko nowe pliki), a mvwraz z resztą. Powinno to być znacznie szybsze, ale niestety nie będzie działać dla każdej aplikacji.

[0] Nawet jeśli spróbuje ustawić uprawnienia dla plików, które nie wymagają żadnych zmian, bazowy system plików prawdopodobnie nie zrobi nic z żądaniem, ponieważ jest to niepotrzebne.

mrb
źródło
Dziękuję za to. Spróbuję znaleźć | wersja chmod i sprawdź, czy to przyspieszy. Jeśli nie, spróbuję zmodyfikować skrypt, aby zaimplementować folder „trzymający”, tak jak sugerowałeś.
Titi Dumi,
Powodem, dla którego nie uzyskasz poprawy prędkości, jest to, że i-węzeł musi być czytany zarówno dla czasu ctime, jak i praw dostępu.
Hauke ​​Laging
10

optymalizacja find / chmod

Zarówno findi chmodmuszę przeczytać

  1. wszystkie wpisy katalogu
  2. i-węzły dla wszystkich tych wpisów

Prawdopodobnie poprawiasz wydajność, najpierw czytając wszystkie wpisy, a następnie wszystkie i-węzły (na obracającym się dysku), ponieważ wtedy głowica dysku nie przemieszcza się między katalogiem a i-węzłami). Jak chmod to jest głupie (jak wyjaśnia jedna z pozostałych odpowiedzi), należy je wywoływać findtylko poprzez . Ale nawet wtedy może pomóc odczytać wszystkie i-węzły przed pierwszym zapisaniem (zakładając, że masz wystarczającą ilość wolnej pamięci RAM na pamięć podręczną dysku). Sugeruję to:

find . -printf "" # reading the file names only
find . ! -perm 775 -printf "" # reading all the inodes (file names are cached)
find . ! -perm 775 -exec chmod 775 + # writing to the cache without reading from disk

Dobre rozwiązanie: listy ACL

Dobre rozwiązanie może być zupełnie inne: jeśli pliki są tworzone w tym katalogu (i nie są przenoszone gdzie indziej), listy ACL mogą wykonywać zadanie w locie. Musisz tylko ustawić domyślne listy ACL w katalogu nadrzędnym.

Dalszą poprawę można osiągnąć dzięki optymalizacji systemu plików. Jeśli jest to ext3 / ext4, możesz e2fsck -Dod czasu do czasu uruchamiać . Może pomaga umieścić ten katalog w osobnym woluminie. Możesz wypróbować różne systemy plików lub ustawienia systemu plików (np. Różne rozmiary i-węzłów).

Hauke ​​Laging
źródło
Listy ACL są dobre, o ile nie pracujesz na montażu NFSv4.
ostrokach
findRozwiązanie o podwojeniu mój czas, chmoding wewnątrz kontenera Döcker.
Nathan Reinstate Monica Arthur,
8

Zakładając, że korzystanie chmodz pakietu GNU coreutils na Ubuntu 12.10.

chmod 775 . -Rwykonuje fchmodatwywołanie systemowe dla każdego znalezionego pliku, niezależnie od tego, czy uprawnienia wymagają zmiany, czy nie. Potwierdziłem to zarówno poprzez sprawdzenie kodu, jak i użycie strace chmod 775 . -R(fragmentu poniżej) do wyświetlenia faktycznego zachowania.

newfstatat(4, "d", {st_mode=S_IFREG|0666, st_size=0, ...}, AT_SYMLINK_NOFOLLOW) = 0
fchmodat(4, "d", 0775)                  = 0
newfstatat(4, "c", {st_mode=S_IFREG|0666, st_size=0, ...}, AT_SYMLINK_NOFOLLOW) = 0
fchmodat(4, "c", 0775)                  = 0
newfstatat(4, "a", {st_mode=S_IFREG|0666, st_size=0, ...}, AT_SYMLINK_NOFOLLOW) = 0
fchmodat(4, "a", 0775)                  = 0
newfstatat(4, "b", {st_mode=S_IFREG|0666, st_size=0, ...}, AT_SYMLINK_NOFOLLOW) = 0
fchmodat(4, "b", 0775)                  = 0

Uruchomienie fchmodatkażdego pliku ma kilka wad

  • Dodatkowe wywołanie systemowe prawdopodobnie stanie się znaczące, jeśli zmieni się duża liczba plików. find/ xargs/ chmodMetoda wspomniano przez innych będzie prawdopodobnie szybciej przez zmianę tylko pliki, które trzeba wymieniać.
  • Wezwanie do fchmodatzmiany modyfikacji statusu pliku (ctime) każdego pliku. Spowoduje to, że każdy plik / i-węzeł zmieni się za każdym razem i prawdopodobnie spowoduje nadmierne zapisy na dysku. Może być możliwe użycie opcji montowania, aby zatrzymać nadmiar zapisu.

Prosty eksperyment pokazuje zmiany czasu dla prostej chmod

auser@duncow:/tmp/blah.test$ ls -lc
total 0
-rwxrwxr-x 1 laptop laptop 0 Jun 18 18:17 a
-rwxrwxr-x 1 laptop laptop 0 Jun 18 18:17 b
-rwxrwxr-x 1 laptop laptop 0 Jun 18 18:17 c
-rwxrwxr-x 1 laptop laptop 0 Jun 18 18:17 d
auser@duncow:/tmp/blah.test$ chmod 775 . -R
auser@duncow:/tmp/blah.test$ ls -lc
total 0
-rwxrwxr-x 1 laptop laptop 0 Jun 18 18:25 a
-rwxrwxr-x 1 laptop laptop 0 Jun 18 18:25 b
-rwxrwxr-x 1 laptop laptop 0 Jun 18 18:25 c
-rwxrwxr-x 1 laptop laptop 0 Jun 18 18:25 d

Ale to się nie zmienia przez find/ xargs/ chmodkilka minut później

auser@duncow:/tmp/blah.test$ date
Tue Jun 18 18:27:27 BST 2013
auser@duncow:/tmp/blah.test$ find . ! -perm 775 -print0 | xargs -0 -I {} chmod 775 {}
auser@duncow:/tmp/blah.test$ ls -lc
total 0
-rwxrwxr-x 1 laptop laptop 0 Jun 18 18:25 a
-rwxrwxr-x 1 laptop laptop 0 Jun 18 18:25 b
-rwxrwxr-x 1 laptop laptop 0 Jun 18 18:25 c
-rwxrwxr-x 1 laptop laptop 0 Jun 18 18:25 d

Zawsze miałbym tendencję do używania wersji find/ xargs/, chmodponieważ find daje większą kontrolę nad wyborem rzeczy.

Richm
źródło
1

[Źródło] (1) pokazuje, że chmod(1)zawsze próbuje ustawić tryb, a następnie sprawdza ponownie za pomocą [fstatat (2)] (2).

Pliki są przetwarzane za pomocą [fts (3)] (3), który musi wcześniej „stat” wszystkich przemierzonych obiektów systemu plików, aby zbudować swoje drzewo danych.

Unixlore zawiera [fajny artykuł] (4), w którym mierzy się chmod(1)czas z podejściem find/ xargspodejście: ta ostatnia wygrywa pod względem wielkości.

Oto linia poleceń dostosowana do pierwotnego pytania:

find . -print0 | xargs -0 chmod 775

Dwa powody:

  1. Przejście systemu plików jest oddzielone od operacji na plikach poprzez potok między dwoma procesami, który może nawet działać na różnych rdzeniach.

    1. fts(3)operacja jest zminimalizowana, ponieważ xargs(1)„spłaszcza” drzewo katalogów.

Więc tak: zdecydowanie powinieneś użyć find/ xargs. dla prostego rozwiązania.

Inne opcje:

  • Graj z [umask] (5) i kodem źródłowym procesu (procesów) pisania nowych plików.

  • Jeśli używasz Linuksa, istnieje prawdopodobieństwo, że Twój system włączył inotifypodsystem jądra. W takim przypadku możesz napisać skuteczne rozwiązanie za pomocą [inotifywait (1)] (6).


Sidenote: chyba że chcesz wykonać uprawnienia do plików, sugeruję zmodyfikować wywołanie w następujący sposób:

find . -type f -print0 | xargs -0 chmod 664
find . -type d -print0 | xargs -0 chmod 775

Uwaga dla redaktorów: Nie wolno mi dodawać więcej niż dwóch linków do postu, ani komentować innych postów. Zostawiam adresy URL tutaj i mam nadzieję, że jakiś otwarty użytkownik o wystarczającej reputacji ponownie umieści je w tekście i usunie ten akapit.


Komentarz na temat przygotowania pamięci podręcznej dysku za pomocą find . -printf "":

Może to przyspieszyć wykonanie następujących chmodoperacji, jednak zależy to od dostępnej pamięci i obciążenia we / wy. Więc to może działać, czy nie. Oddzielenie traversal ( find) i chmodoperacji już zapewnia buforowanie, więc uruchomienie pamięci podręcznej może być zbędne.

  1. https + lingrok.org / xref / coreutils / src / chmod.c # plik_procesu
  2. https + linux.die.net / man / 2 / fstatat
  3. https + linux.die.net / man / 3 / fts
  4. http + www.unixlore.net / article / speeding-up-bulk-file-Operations.html
  5. https + en.wikipedia.org / wiki / Umask
  6. https + linux.die.net / man / 1 / inotifywait
Georg Lehner
źródło
0

Czy zastanawiałeś się nad zmianą procesów tworzących plik, aby były tworzone w trybie 0775? Spójrz na wartość umask w środowisku - 0002 może pomóc.

D McKeon
źródło