Comment élever des privilèges au milieu d'un pipeline?

8

Ma supposition était la suivante:

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

Mais sudit:

su: must be run from a terminal

Qu'est-ce que tu ferais?

x-yuri
la source
Si vous avez trouvé une solution vous-même, veuillez l'ajouter comme réponse ci-dessous.
Braiam
@Braiam La solution ne mérite pas d'être une réponse.
x-yuri

Réponses:

8

sudo soutient cela.

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

La différence étant que vous sudodemandez votre mot de passe utilisateur, pas le mot de passe root(utilisateur cible). Cependant, si vous le souhaitez, vous pouvez modifier ce comportement avec la directive targetpw(ou runaspwou rootpw) dans sudoers.conf.


Cependant, lire ce que vous essayez de faire, même si cela résout le problème de l'escalade des autorisations, ne fera pas ce que vous attendez. La signification /output/filene sera pas créée en tant qu'utilisateur root, elle sera créée / modifiée en tant qu'utilisateur.

La raison en est que la redirection de sortie du shell est effectuée avant d'appeler des commandes. Ainsi, le shell s'ouvre /output/filepuis passe ce fichier ouvert à su/ sudo(et par conséquent, cat).

Cependant, vous pouvez le faire teeà la place, car l' teeutilitaire ouvrira le fichier lui-même.

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

Copie essentiellement teela sortie dans /output/fileet STDOUT, mais STDOUT est redirigé vers /dev/null.

Vous pourriez également faire:

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

... qui est moins cryptique.

Patrick
la source
Vous pouvez également "mettre en cache" des privilèges élevés en invoquant sudo -v. Il vous demandera votre mot de passe si vous n'avez pas utilisé sudo depuis quelques minutes.
Winny
2

Juste pour que vous le sachiez - vous n'êtes pas limité à une seule commande par |pipe:

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

Tous ces processus sont invoqués en même temps - mais ils attendent tous |pipeavant eux avant de faire quoi que ce soit - tant qu'ils lisent le |pipetout, c'est-à-dire. Donc, si vous avez besoin d'évaluer une variable en cours de route ou de configurer une redirection, vous le pouvez. Prenez votre temps.

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

it takes time

Voici une autre façon:

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

Si vous ne ( subshell )le faites pas, la commande $(cat)sera </dev/ttyégalement récupérée.

Mais si vous utilisez un here-doc, vous n'avez pas besoin de deux 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

PRODUCTION:

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

La plupart de ce qui précède est juste pour faire une démonstration. Tout ce dont vous avez vraiment besoin est:

su -c 'cat <&3 >./file' 3<<HERE | { wait as needed ; more stuff to do ; }
$(echo "something" | and other things)
HERE
mikeserv
la source
Je le sais. Cela n'a rien ou presque rien à voir avec la question, du moins je pense. Mais en quelque sorte, cela m'a conduit à une réponse :) Voir ma question mise à jour.
x-yuri
@ x-yuri Vous pouvez toujours mettre un document ici au milieu d'un pipeline. faire écho à quelque chose | {su 'faire quelques trucs> /record.here'; } << ICI | écho en bout de pipe \ n $ (cat) \ n ICI \ n
mikeserv
En effet, je n'ai pas pensé à utiliser cat à l'intérieur de ce document. De toute façon, vous n'avez pas besoin de vous y regrouper.
x-yuri
@ x-yuri - cela dépend de ce que vous voulez en faire. Vous pouvez utiliser l'un ou les deux. J'essayais seulement de démontrer que vous aviez des options. La réponse de Patrick est la bonne ici, c'est juste une autre façon plus compliquée. Ce document-ci regroupe cependant - il regroupe le chat en sous-coquille.
mikeserv
Par regroupement, je voulais dire des accolades .
x-yuri