Ejecuta una línea de comandos con un sudo

21

Por ejemplo, si quiero crear un archivo e ingresar texto en una línea, puedo redirigir la salida a un archivo con el uso del >operador:

echo "something" > /path/foobar

pero si no tengo acceso a la carpeta /path/y necesito privilegios de sudo, ¿cómo puedo lograr este mismo comando que un usuario normal con derechos de sudo?

Lo intenté

sudo echo "something" > /path/foobar

pero eso no funciona, porque el sudo solo cuenta para la editparte correcta
de la parte no>

Claro, podría convertirme en root antes sudo suo usar teeen su lugar:

echo "something" | sudo tee /path/foobar

Pero me gustaría encontrar una solución donde pueda trabajar con la última línea como reemplazo a través de

sudo !!

¿No hay una manera de "reciclar" la última línea y simplemente agregarla sudoal frente?

rubo77
fuente
Esto no es un duplicado. Extraje el Qeustion real y cambié el título. Ahora es lo que realmente estoy buscando
rubo77
Ciertamente era un duplicado, pero ahora es algo diferente. Me parece que reescribiste la pregunta a la luz de la respuesta de Boogy, lo cual está bien, es una buena respuesta. He retirado mi voto cerrado, pero aún es inevitable (las personas a menudo votan automáticamente una vez que una pregunta está en la lista cerrada sin prestar atención al problema): dirija un comentario @goldilocks cuando se cierre y votaré para volver a abrir . También puede defender su caso en el chat una vez que eso suceda.
Ricitos
Ver también ¿Cómo puedo alias sudo !!?
Gilles 'SO- deja de ser malvado'

Respuestas:

13

No puede simplemente quedarse sudodelante de un comando de shell, debe invocar un shell para evaluar ese comando nuevamente (haciendo cosas como expandir variables, abrir archivos para operadores de redirección, etc.). Así que eso es

sudo bash -c !!

excepto que esto no funciona del todo, porque !!interpola el texto del comando anterior, caracteres especiales y todo. Debe recuperar el texto del comando como una cadena y pasarlo como argumento a sh. Afortunadamente, bash fcincorporado de bash te permite hacer eso¹.

sudo bash -c "$(fc -ln -1)"

O incluso, para asegurarse de invocar la misma versión de bash que se está ejecutando actualmente:

sudo "$BASH" -c "$(fc -ln -1)"

Tenga en cuenta que, dado que el comando se ejecuta en un proceso de shell separado, hereda las variables de entorno (solo las que sudoconserva, mind), pero no las variables internas de shell. Las opciones de Shell (por ejemplo kshglob) y otras configuraciones comenzarán desde el valor predeterminado.

El mismo command² trabaja en zsh y ksh, aunque ATT ksh93 requiere tanto el firsty lastnúmero que se pasa a fc³ (que también funciona en bash, zsh y pdksh / mksh):

sudo zsh -c "$(fc -ln -1)"
sudo ksh -c "$(fc -ln -1 -1)"
sudo "$0" -c "$(fc -ln -1 -1)"

El uso $0para designar el ejecutable del shell en ejecución solo funciona si el shell se invocó a través de $ PATH y $ PATH no ha cambiado, o a través de una ruta absoluta.

Aquí hay otro método en zsh que es un poco más claro pero más largo:

sudo zsh -c $history[$[HISTCMD-1]]

Una última palabra de advertencia: sudoes para comandos potencialmente peligrosos. ¡No lo hagas demasiado fácil de usar!

¹ Hay algunos espacios en blanco adicionales al principio y la sustitución de comandos elimina las nuevas líneas al final, pero la sintaxis del shell no se preocupa por eso.
² No creo que zsh o ksh tengan algo como bash $BASH; $0solo funciona cuando es una ruta absoluta, o cuando no contiene una barra inclinada y la ruta de búsqueda de comandos no ha cambiado.
³ es un alias para ATT ksh pero es igual de bueno. fchist

Gilles 'SO- deja de ser malvado'
fuente
9

Si quieres rehacer el mismo comando con sudo !! después de hacer un comando como este:

echo "something">/path/file

Usa la sintaxis de reemplazo global para recuperar el comando:

!!:gs/>/|sudo tee -a /

Use un espacio después del parámetro -a .

Este es el equivalente a sudo !! pero le ayuda a evitar las restricciones de sudo para <y>. Porque sudo no le permite usar [<,>].


Para evitar las restricciones de sudo en general para las redirecciones, puede usarlo así:

echo "something" | sudo tee myfile

El comando tee le permitirá leer desde entradas estándar y escribir en salidas y archivos estándar

Si desea repetir el comando y agregar un texto al archivo, el comando tee tiene la opción -a para agregar. Entonces puedes recordar el comando con

sudo !!

y el texto se agregará en el archivo

ejemplo:

echo "something" | sudo tee -a /path/file
sudo !!
Boogy
fuente
Buena solución, pero un poco difícil de memorizar. ¿Cómo puedo crear un alias para un comando usando !! para recordar el último comando ?
rubo77
¿Es -arealmente necesario? >sobrescribe un archivo, tee -acomo apéndice, lo que sería>>
rubo77
3

Parece ser tan simple como sudo sh -c "!!":

$ cd /
$ echo hello > foo
bash: foo: Permission denied
$ sudo sh -c "!!"
sudo sh -c "echo hello > foo"
$ ls -l foo
-rw-r--r-- 1 root root 6 Jun 20 16:21 foo
deltab
fuente
3
Si el comando usó comillas, esto no es necesariamente equivalente. Considere echo "foo bar"cuál se convertiría en sh -c "echo "foo bar""cuál simplemente se imprimiría en foolugar de foo bar.
godlygeek
En sudo sh -c '!!'cambio, intenté si tu comando, pero eso tampoco funciona
rubo77
Entonces, ¿qué pasa si su comando usaba comillas simples y dobles? ¿O comillas dobles y expansiones variables? Si el usuario lo hizo: a=by luego echo "$a" >filey luego sudo sh -c '!!'se expandiría a sudo sh -c 'echo $a >file'lo que imprimiría una línea vacía en lugar de ben file.
godlygeek
Entonces, ¿tal vez hay una solución aún mejor de alguna manera?
rubo77
1
No creo que haya una solución que funcione el 100% del tiempo sin que sea necesario modificar el comando. Usar sudopara obtener un shell raíz y luego copiar y pegar el comando en él sería lo más cercano, pero falla si se espera que el comando use variables que se establecieron en su shell no root. El uso sudo sh -c "!!"funciona bien para comandos simples, pero es difícil para los complejos. Creo que el mejor consejo es no esperar que haya algún comando que funcione el 100% del tiempo: aprenda algunas posibles soluciones y aplique cada una cuando mejor se adapte.
godlygeek