Como elevo privilégios no meio do pipeline?

8

Meu palpite foi o seguinte:

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

Mas sudiz:

su: must be run from a terminal

O que você faria?

x-yuri
fonte
Se você mesmo encontrou uma solução, adicione-a como resposta abaixo.
Braiam
@ Braiam A solução não merece ser uma resposta.
X-yuri

Respostas:

8

sudo suporta isso.

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

A diferença é que sudosolicita 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 runaspwou rootpw) em sudoers.conf.


No entanto, lendo o que você está tentando fazer, enquanto isso resolve o problema de escalação de permissão, ele não fará o que você espera. O significado /output/filenão será criado como o usuário root, será criado / modificado como seu usuário.

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

No entanto, você pode teefazer isso, pois o teeutilitário abrirá o próprio arquivo.

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

Basicamente, teecopia a saída para /output/filee 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.

Patrick
fonte
Você também pode "armazenar em cache" privilégios elevados invocando sudo -v. Ele solicitará sua senha se você não tiver usado o sudo em alguns minutos.
Winny
2

Só para você saber - você 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 |pipeantes de realmente fazer qualquer coisa - desde que eles leiam o |pipeque é. Portanto, se você precisar avaliar uma variável no meio do caminho ou configurar um redirecionamento, poderá. Leve o tempo que precisar.

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

Caso contrário, ( subshell )o comando também $(cat)ficará </dev/tty.

Mas se você estiver usando um documento aqui, não precisará de dois cats:

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

RESULTADO:

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

A maioria dos itens acima é apenas para demonstração. 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
mikeserv
fonte
Eu sei disso. Isso tem pouco ou nada a ver com a questão, ou pelo menos eu acho. Mas de alguma forma isso me levou a uma resposta :) Veja minha pergunta atualizada.
X-yuri
@ x-yuri Você ainda pode colocar um documento aqui no meio de um pipeline. ecoar algo | {su 'faz algumas coisas> /record.here'; } << AQUI | eco final do pipe \ n $ (cat) \ nHERE \ n
mikeserv 06/04
Na verdade, eu não pensei em usar gato dentro deste documento. De qualquer forma, você não precisa se agrupar lá.
X-yuri #
@ x-yuri - isso depende do que você quer fazer com isso. Você pode usar um ou ambos. Eu só estava tentando demonstrar que você tinha opções. A resposta de Patrick é a correta aqui, esta é apenas outra maneira, mais complicada. Porém, esse documento aqui agrupa - agrupa gato em uma subcama.
mikeserv
Agrupando, eu quis dizer chaves .
X-yuri