Como faço para elevar privilégios no meio do pipeline?

8

Meu palpite foi o seguinte:

echo "Generating some text" | su - -c cat >/output/file

Mas su diz:

su: must be run from a terminal

O que você faria?

    
por x-yuri 04.04.2014 / 16:19

2 respostas

8

sudo suporta isso.

$ echo hello world | sudo cat  
SUDO password: 
hello world

A diferença é que sudo solicita sua senha de usuário, não a senha root (usuário de destino). No entanto, se você desejar, poderá alterar esse comportamento com a diretiva targetpw (ou runaspw ou rootpw ) em sudoers.conf .

No entanto, ao ler o que você está tentando fazer, embora isso resolva o problema de escalonamento de permissões, ele não fará o que você espera. O significado /output/file não será criado como o usuário raiz, ele será criado / modificado como seu usuário.

A razão para isto é que o redirecionamento de saída do shell é feito antes de chamar qualquer comando. Portanto, o shell abre /output/file e, em seguida, passa esse arquivo aberto para su / sudo (e, consequentemente, cat ).

No entanto, você pode usar tee para fazer isso, pois o utilitário tee abrirá o arquivo em si.

echo "hello world" | sudo tee /output/file >/dev/null

Basicamente tee copia a saída em /output/file e STDOUT, no entanto STDOUT é redirecionado para /dev/null .

Você também pode fazer:

echo "hello world" | sudo sh -c 'cat > /output/file'

... o que é menos enigmático.

    
por 04.04.2014 / 16:35
2

Só para você saber - não está limitado a um único comando por |pipe :

this happens | then this | { then ; all of ; this too ; } | before this

Todos esses processos são invocados ao mesmo tempo - mas todos esperam no |pipe antes deles antes de fazer qualquer coisa - desde que leiam o |pipe , isto é. Então, se você precisa avaliar uma variável midstream, ou configurar um redirecionamento, você pode. Apenas tome seu tempo.

echo "it takes time" |
{ exec 4>|file ; cat >&4 ; } |
( sleep 1 && cat <file )

it takes time

Aqui está outra maneira:

echo "more of the same" |
( IFS= ; su -mc 'echo '"$(printf "'%s' " "'cat'")"' >|file' </dev/tty ) |
echo end of pipe

Se você não ( subshell ) , o comando $(cat) também receberá </dev/tty .

Mas se você estiver usando um aqui-doc, não precisará de dois cat s:

rm ./file
su -c 'cat <&3 >|./file; echo "middle here"' 3<<HERE >&2 | {\
    until [ -s ./file ] ; do sleep 1 ; done ;\
    sed 's/beginning/end/' ./file ; }
$(echo "this is the beginning" | sed 'a\of the pipeline' | tee /dev/stderr)
HERE

OUTPUT:

this is the beginning
of the pipeline
Password:
middle here
this is the end
of the pipeline

A maioria das opções acima é apenas para demonstrar isso. Tudo o que você realmente precisa é:

su -c 'cat <&3 >./file' 3<<HERE | { wait as needed ; more stuff to do ; }
$(echo "something" | and other things)
HERE
    
por 05.04.2014 / 23:41