it-swarm-es.com

¿Cómo uso Sudo para redirigir la salida a una ubicación en la que no tengo permiso para escribir?

Me dieron acceso a Sudo en una de nuestras cajas RedHat linux de desarrollo, y me parece que a menudo necesito redirigir la salida a una ubicación a la que normalmente no tengo acceso de escritura.

El problema es que este ejemplo artificial no funciona:

Sudo ls -hal /root/ > /root/test.out

Acabo de recibir la respuesta:

-bash: /root/test.out: Permission denied

¿Cómo puedo conseguir que esto funcione?

786
Jonathan

Su comando no funciona porque la redirección la realiza su Shell, que no tiene permiso para escribir en /root/test.out. La redirección de la salida no esrealizada por Sudo.

Hay múltiples soluciones:

  • Ejecuta un Shell con Sudo y dale el comando usando la opción -c:

    Sudo sh -c 'ls -hal /root/ > /root/test.out'
    
  • Cree un script con sus comandos y ejecute ese script con Sudo:

    #!/bin/sh
    ls -hal /root/ > /root/test.out
    

    Ejecuta Sudo ls.sh. Consulte answer de Steve Bennett si no desea crear un archivo temporal.

  • Inicie un Shell con Sudo -s y luego ejecute sus comandos:

    [[email protected]]$ Sudo -s
    [[email protected]]# ls -hal /root/ > /root/test.out
    [[email protected]]# ^D
    [[email protected]]$
    
  • Use Sudo teesi tiene que escapar mucho al usar la opción -c):

    Sudo ls -hal /root/ | Sudo tee /root/test.out > /dev/null
    

    La redirección a /dev/null es necesaria para evitar que _ (tee salga a la pantalla. Para agregar en lugar de sobrescribir el archivo de salida (>>), use tee -a o tee --append (el último es específico para GNU coreutils ).

Gracias a Jd , Adam J. Forster y Johnathan por las soluciones segunda, tercera y cuarta.

1096
Cristian Ciupitu

Alguien aquí acaba de sugerir sudoing tee:

Sudo ls -hal /root/ | Sudo tee /root/test.out > /dev/null

Esto también podría usarse para redirigir cualquier comando a un directorio al que no tiene acceso. Funciona porque el programa tee es efectivamente un programa de "eco a un archivo", y el redireccionamiento a/dev/null es para que se detenga también en la pantalla y se mantenga igual al ejemplo original creado anteriormente.

91
Jonathan

Un truco que me di cuenta era

Sudo ls -hal /root/ | Sudo dd of=/root/test.out
71
rhlee

El problema es que el comandose ejecuta bajo Sudo, pero el redireccionamiento se ejecuta bajo su usuario. Esto lo hace Shell y hay muy poco que puedas hacer al respecto.

Sudo command > /some/file.log
`-----v-----'`-------v-------'
   command       redirection

Las formas habituales de eludir esto son:

  • Envuelve los comandos en una secuencia de comandos que llamas bajo Sudo.

    Si los comandos y/o el archivo de registro cambian, puede hacer que el script los tome como argumentos. Por ejemplo:

    Sudo log_script command /log/file.txt
    
  • Llame a un Shell y pase la línea de comando como un parámetro con -c

    Esto es especialmente útil para comandos compuestos únicos. Por ejemplo:

    Sudo bash -c "{ command1 arg; command2 arg; } > /log/file.txt"
    
41
dsm

Otra variación más sobre el tema:

Sudo bash <<EOF
ls -hal /root/ > /root/test.out
EOF

O por supuesto:

echo 'ls -hal /root/ > /root/test.out' | Sudo bash

Tienen la ventaja (pequeña) de que no es necesario recordar ningún argumento para Sudo o sh/bash

20
Steve Bennett

Aclarando un poco por qué es preferible la opción de tee

Suponiendo que tenga el permiso adecuado para ejecutar el comando que crea la salida, si canaliza la salida de su comando para realizar un tee, solo necesita elevar los privilegios de tee con Sudo y dirigirlo para escribir (o adjuntar) al archivo en cuestión.

en el ejemplo dado en la pregunta que significaría:

ls -hal /root/ | Sudo tee /root/test.out

para un par de ejemplos más prácticos:

# kill off one source of annoying advertisements
echo 127.0.0.1 ad.doubleclick.net | Sudo tee -a /etc/hosts

# configure eth4 to come up on boot, set IP and netmask (centos 6.4)
echo -e "ONBOOT=\"YES\"\nIPADDR=10.42.84.168\nPREFIX=24" | Sudo tee -a /etc/sysconfig/network-scripts/ifcfg-eth4

En cada uno de estos ejemplos, toma la salida de un comando sin privilegios y escribe en un archivo que normalmente solo se puede escribir por root, que es el origen de su pregunta.

Es una buena idea hacerlo de esta manera porque el comando que genera la salida no se ejecuta con privilegios elevados. No parece importar aquí con echo, pero cuando el comando fuente es un script en el que no confías por completo, es crucial.

Tenga en cuenta que puede usar la opción -a para añadir el apéndice (como >>) al archivo de destino en lugar de sobrescribirlo (como >).

18
jg3

Haz que sudo ejecute un shell, como este:

Sudo sh -c "echo foo > ~root/out"
16
Penfold

La forma en que trataría este tema es:

Si necesita escribir/reemplazar el archivo:

echo "some text" | Sudo tee /path/to/file

Si necesita adjuntar al archivo:

echo "some text" | Sudo tee -a /path/to/file
9
Nikola Petkanski

¿Qué hay de escribir un guión?

Nombre de archivo: myscript

#!/bin/sh

/bin/ls -lah /root > /root/test.out

# end script

Luego usa Sudo para ejecutar el script:

Sudo ./myscript
5
Jd

Lo haría de esta manera:

Sudo su -c 'ls -hal /root/ > /root/test.out'
4
fardjad

Cada vez que tengo que hacer algo como esto, simplemente me convierto en root:

# Sudo -s
# ls -hal /root/ > /root/test.out
# exit

Probablemente no sea la mejor manera, pero funciona.

3
Adam J. Forster

No intente vencer a un caballo muerto, pero aquí hay demasiadas respuestas que usan tee, lo que significa que debe redirigir stdout a /dev/null a menos que quiera ver una copia en la pantalla. Una solución más simple es usar cat de esta manera:

Sudo ls -hal /root/ | Sudo bash -c "cat > /root/test.out"

Observe cómo la redirección se coloca entre comillas para que sea evaluada por un Shell iniciado por Sudo en lugar del que lo ejecuta.

3
haridsv

Esto se basa en la respuesta que implica tee. Para facilitar las cosas, escribí un pequeño script (lo llamo suwrite) y lo puse en /usr/local/bin/ con el permiso +x:

#! /bin/sh
if [ $# = 0 ] ; then
    echo "USAGE: <command writing to stdout> | suwrite [-a] <output file 1> ..." >&2
    exit 1
fi
for arg in "[email protected]" ; do
    if [ ${arg#/dev/} != ${arg} ] ; then
        echo "Found dangerous argument ‘$arg’. Will exit."
        exit 2
    fi
done
Sudo tee "[email protected]" > /dev/null

Como se muestra enUSEen el código, todo lo que tiene que hacer es canalizar la salida a este script seguido del nombre de archivo accesible al superusuario deseado y le solicitará automáticamente su contraseña si es necesario (ya que incluye Sudo).

echo test | suwrite /root/test.txt

Tenga en cuenta que, dado que se trata de un envoltorio simple para tee, también aceptará la opción -a de tee para adjuntar, y también admite la escritura en varios archivos al mismo tiempo.

echo test2 | suwrite -a /root/test.txt
echo test-multi | suwrite /root/test-a.txt /root/test-b.txt

También tiene cierta protección simplista contra la escritura en dispositivos /dev/, lo cual fue una preocupación mencionada en uno de los comentarios en esta página.

2
jamadagni

¿Tal vez le han dado acceso a Sudo solo a algunos programas/rutas? Entonces no hay manera de hacer lo que quieres. (A menos que lo hackees de alguna manera)

Si no es el caso, entonces tal vez puedas escribir un script bash:

cat > myscript.sh
#!/bin/sh
ls -hal /root/ > /root/test.out 

Prensa ctrl + d :

chmod a+x myscript.sh
Sudo myscript.sh

Espero que te ayude.

1
user15453
Sudo at now  
at> echo test > /tmp/test.out  
at> <EOT>  
job 1 at Thu Sep 21 10:49:00 2017  
0
user8648126