W jaki sposób w poleceniu `sudo find` mam się upewnić, że polecenie` -exec` jest uruchamiane jako zwykły użytkownik?

10

Staram się, aby następujące polecenie działało w taki sposób, aby process_pathsskrypt nie był uruchamiany z podwyższonymi uprawnieniami. Czy jest na to sposób?

sudo find /path/ -exec process_paths '{}' \+

Oto /path/niektóre pliki, które nie mają uprawnień do odczytu dla zwykłego użytkownika. Skrypt process_pathspotrzebuje tylko ścieżek.

pii_ke
źródło
... -exec sudo -u user process_paths {} \+
Satō Katsura
@SatoKatsura czasami nie udaje się to z sudo: unable to execute /usr/bin/perl: Argument list too long: /
pii_ke
1
Tak, zobacz notatkę o SUDO_COMMANDzmiennej w find. . [^.] * -type f -print0 | xargs -0 sudo chmod 664; nie działa
Stéphane Chazelas
2
Jeśli chcesz, aby -execpolecenia były wywoływane jako użytkownik, dlaczego findużywasz sudow pierwszej kolejności?
marcelm
2
@marcelm Myślę, że ostatnie zdanie pytania odpowiada na twoje.
Hej,

Odpowiedzi:

16

W systemach, które go obsługują (GNU i kilka innych), możesz:

sudo find /path/ -print0 | xargs -r0 process_paths

xargsnie jest uruchamiany pod sudo, więc nadal ma oryginalne identyfikatory / gids, a także oryginalne środowisko (w szerszym znaczeniu), a nie zmodyfikowane przez sudo.

process_pathsstdin zostaje jednak zmodyfikowany (w zależności od xargsimplementacji, jest otwarty /dev/nulllub udostępnia plik pipez sudo/ find.

Aby tego uniknąć (GNU xargsi muszli jak ksh, zshlub bashzastąpienie innych procesów wsparcia), można zrobić:

xargs -r0a <(sudo find /path/ -print0) process_paths

Z zsh:

sudo zsh -c '
   files=(/path/**/*(D))
   USERNAME=$SUDO_USER
   autoload zargs
   zargs $files -- process_paths'

W zsh, przypisując nazwę użytkownika do $USERNAMEspecjalnej zmiennej, ustawia identyfikatory użytkownika, identyfikatory użytkownika na odpowiadającego użytkownika w bazie danych użytkowników, tak jak sudo -u "$SUDO_USER"zrobiłby to.

Mógłbyś:

 sudo sh -c '
   exec find /path/ -exec sudo -u "$SUDO_USER" process_paths {} +'

Ponieważ jednak sudoprzekazuje $SUDO_COMMANDzmienną środowiskową (która zawiera konkatenację argumentów ze spacjami) process_paths, lista plików jest przekazywana dwukrotnie, process_pathsco oznacza, że ​​limit maksymalnej wielkości argumentów + env zostanie prawdopodobnie osiągnięty, jeśli istnieje duża liczba plików.

W przypadku większości suimplementacji powinieneś być w stanie:

 sudo sh -c '
   exec find /path/ -exec su "$SUDO_USER" -c '\''
     exec "$0" "$@"'\'' process_paths {} +'

chociaż sunie ma tego samego problemu.

Stéphane Chazelas
źródło
1

Możesz użyć sudo:

sudo find <directory> -exec sudo -u <normal_user> <command> {} \;

Ale jak powiedziano w komentarzu, najwyraźniej może się nie powieść, jeśli {} jest za długie na sudo.

Hej
źródło