Em um comando `sudo find`, como posso garantir que o comando` -exec` seja executado como usuário normal?

10

Estou tentando fazer com que o seguinte comando funcione de maneira que o process_pathsscript não seja executado sob privilégios elevados. Existe uma maneira de fazer isso?

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

Aqui /path/tem alguns arquivos que não têm permissão de leitura para o usuário normal. O script process_pathssó precisa dos caminhos.

pii_ke
fonte
... -exec sudo -u user process_paths {} \+
Satō Katsura
@SatoKatsura às vezes isso falha com sudo: unable to execute /usr/bin/perl: Argument list too long: /
pii_ke 16/02
1
Sim, veja a nota sobre a SUDO_COMMANDvariável em localização. . [^.] * -type f -print0 | xargs -0 sudo chmod 664; funciona
Stéphane Chazelas
2
Se você deseja que os -execcomandos sejam chamados como seu usuário, por que você está findusando sudoem primeiro lugar?
marcelm
2
@marcelm Acho que a última frase da pergunta responde à sua.
Ei

Respostas:

16

Em sistemas que o suportam (GNU e muitos outros), você pode:

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

xargsnão é executado abaixo sudo, por isso ainda possui os uids / gids originais e também o ambiente original (no sentido mais amplo), não o modificado por sudo.

process_pathsstdin acaba sendo modificado embora (dependendo da xargsaplicação, é aberto sobre /dev/nullou ações pipede sudo/ find.

Para evitar isso (com GNU xargse shells como ksh, zshou bashque suportam a substituição de processos), você pode:

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

Com zsh:

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

Em zsh, atribuindo um nome de usuário à $USERNAMEvariável especial, define os uids, gids como os do usuário correspondente no banco de dados do usuário, como sudo -u "$SUDO_USER"faria.

Você poderia fazer:

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

Mas como sudopassa uma $SUDO_COMMANDvariável de ambiente (que contém a concatenação dos argumentos com espaços) para process_paths, a lista de arquivos acaba sendo passada duas vezes, o process_pathsque significa que o limite no tamanho máximo de args + env será atingido se houver um grande número de arquivos.

Com a maioria das suimplementações, você deve ser capaz de:

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

embora sunão tenha o mesmo problema.

Stéphane Chazelas
fonte
1

Você pode usar sudo:

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

Mas, como dito em um comentário, aparentemente pode falhar se o {} for muito longo para o sudo.

Ei
fonte