¿Cómo elevo los privilegios en el medio de la tubería?

8

Mi suposición fue la siguiente:

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

Pero sudice:

su: must be run from a terminal

¿Qué harías?

x-yuri
fuente
Si usted mismo encontró una solución, agréguela como respuesta a continuación.
Braiam
@Braiam La solución no merece ser una respuesta.
x-yuri

Respuestas:

8

sudo apoya esto.

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

La diferencia es que sudole pide su contraseña de usuario, no la contraseña root(usuario objetivo). Sin embargo, si así lo desea, puede cambiar este comportamiento con la directiva targetpw( runaspwo rootpw) sudoers.conf.


Sin embargo, leer lo que está tratando de hacer, aunque esto resuelve el problema de escalado de permisos, no hará lo que espera. El significado /output/fileno se creará como usuario root, se creará / modificará como su usuario.

La razón de esto es que la redirección de salida de shell se realiza antes de invocar cualquier comando. Entonces, el shell se abre /output/filey luego pasa ese archivo abierto a su/ sudo(y, en consecuencia, cat).

Sin embargo, puede teehacer esto en su lugar, ya que la teeutilidad abrirá el archivo en sí.

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

Básicamente teecopia la salida en /output/filey STDOUT, sin embargo, STDOUT se redirige a /dev/null.

También puedes hacer:

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

... que es menos críptico.

Patricio
fuente
También puede "almacenar en caché" privilegios elevados invocando sudo -v. Le pedirá su contraseña si no ha usado sudo en unos minutos.
Winny
2

Para que lo sepas, no estás limitado a un solo comando por |pipe:

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

Todos esos procesos se invocan al mismo tiempo, pero todos esperan |pipeante ellos antes de hacer cualquier cosa, siempre que lean el |pipemensaje, eso es. Entonces, si necesita evaluar una variable midstream o configurar una redirección, puede hacerlo. Solo tomate tu tiempo.

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

it takes time

Aquí hay otra forma:

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

Si no lo hace, ( subshell )el comando también $(cat)se obtendrá </dev/tty.

Pero si está utilizando un documento aquí, no necesita dos 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

SALIDA:

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

La mayor parte de lo anterior es solo para demostrar esto. Todo lo que realmente necesitas es:

su -c 'cat <&3 >./file' 3<<HERE | { wait as needed ; more stuff to do ; }
$(echo "something" | and other things)
HERE
mikeserv
fuente
Yo sé eso. Eso tiene poco o nada que ver con la pregunta, o eso creo. Pero de alguna manera me llevó a una respuesta :) Ver mi pregunta actualizada.
x-yuri
@ x-yuri Todavía puede poner un documento aquí en el medio de una tubería. hacer eco de algo | {su 'haz algunas cosas> /record.here'; } << AQUÍ | echo end of pipe \ n $ (cat) \ nHERE \ n
mikeserv
De hecho, no pensé en usar cat dentro de este documento. De todos modos, no necesitas agruparte allí.
x-yuri
@ x-yuri: eso depende de lo que quieras hacer con él. Puedes usar uno o ambos. Solo intentaba demostrar que tenías opciones. La respuesta de Patrick es la correcta aquí, esta es solo otra forma más complicada. Sin embargo, aquí-doc se agrupa: agrupa cat en una subshell.
mikeserv
Al agrupar me refería a llaves .
x-yuri