bash - quitar - ¿Por qué sudo cat otorga un Permiso denegado pero sudo vim funciona bien?
permiso denegado linux mint (5)
Como @geekosaur explicó, el shell realiza la redirección antes de ejecutar el comando. Cuando escribes esto:
sudo foo >/some/file
El proceso de shell actual hace una copia de sí mismo que primero intenta abrir /some/file
para escritura, luego convierte ese descriptor de archivo en su salida estándar, y solo luego ejecuta sudo
.
Si está permitido (las configuraciones de sudoer a menudo impiden ejecutar shells), puede hacer algo como esto:
sudo bash -c ''foo >/some/file''
Pero creo que una buena solución en general es usar | sudo tee
| sudo tee
lugar de >
y | sudo tee -a
| sudo tee -a
lugar de >>
. Eso es especialmente útil si, en primer lugar, la redirección es la única razón por la que necesito sudo
; después de todo, ejecutar innecesariamente procesos como root es precisamente lo que sudo
fue creado para evitar. Y ejecutar echo
como root es tonto.
echo ''[archlinuxfr]'' | sudo tee -a /etc/pacman.conf >/dev/null
echo ''Server = http://repo.archlinux.fr/$arch'' | sudo tee -a /etc/pacman.conf >/dev/null
echo '' '' | sudo tee -a /etc/pacman.conf >/dev/null
Agregué > /dev/null
al final porque tee
envía su salida tanto al archivo nombrado como a su propia salida estándar, y no necesito verlo en mi terminal. (El comando tee
actúa como un conector "T" en una tubería física, que es donde recibe su nombre.) Y cambié a comillas simples ( ''
... ''
) en vez de dobles ( ''
''
... ''
) para que todo es literal y no tuve que poner una barra invertida frente al $
in $arch
.
Entonces eso se encarga de escribir en los archivos como root usando sudo
. Ahora, para una larga digresión sobre formas de mostrar texto que contiene nueva línea en un script de shell. :)
Primero, puedes agrupar todos los echo
en una subshell, por lo que solo tienes que hacer la redirección una vez:
(echo ''[archlinuxfr]
echo ''Server = http://repo.archlinux.fr/$arch''
echo '' '') | sudo tee -a /etc/pacman.conf >/dev/null
O use printf
lugar de echo
, para que pueda incrustar nuevas líneas directamente en la cadena usando /n
:
printf ''[archlinuxfr]/nServer = http://repo.archlinux.fr/$arch/n '' |
sudo tee -a /etc/pacman.conf >/dev/null
En bash
, puedes obtener el mismo resultado con echo -e
:
# BASH ONLY - NOT RECOMMENDED
echo -e ''[archlinuxfr]/nServer = http://repo.archlinux.fr/$arch/n '' |
sudo tee -a /etc/pacman.conf >/dev/null
Pero la mayoría de las shells generarán el -e
cuando lo intentes, por lo que no es recomendable.
Con printf
y echo -e
, lo que obtiene el comando como argumento contiene una barra invertida literal seguida de una N literal donde sea que escriba /n
, y depende del programa de comando en sí (el código dentro de printf
o echo
) traducir eso en una nueva línea. En muchas shells modernas, tiene la opción de utilizar cotizaciones ANSI $''
... ''
, que traducirá secuencias como /n
en nuevas líneas literales antes de que el programa de comando alguna vez vea la cadena, lo que significa que dichas cadenas funcionan con cualquier comando:
echo $''[archlinuxfr]/nServer = http://repo.archlinux.fr/$arch/n '' |
sudo tee -a /etc/pacman.conf >/dev/null
Pero, aunque son más portátiles que echo -e
, las cotizaciones ANSI siguen siendo una extensión que no es POSIX.
Mi forma preferida de hacer esto sería usar un documento aquí y evitar la necesidad de echo
o printf
completo:
sudo tee -a /etc/pacman.conf >/dev/null <<''EOF''
[archlinuxfr]
Server = http://repo.archlinux.fr/$arch
EOF
Intento automatizar la incorporación de una fuente de repositorio en el archivo pacman.conf de mi arch pero utilizando el comando echo
en mi script de shell. Sin embargo, falla así: -
sudo echo "[archlinuxfr]" >> /etc/pacman.conf
sudo echo "Server = http://repo.archlinux.fr//$arch" >> /etc/pacman.conf
sudo echo " " >> /etc/pacman.conf
-bash: /etc/pacman.conf: Permission denied
Si realizo cambios en /etc/pacman.conf manualmente usando vim, haciendo
sudo vim /etc/pacman.conf
y renunciando a vim con :wq
, todo funciona bien y mi pacman.conf se ha actualizado manualmente sin quejas de "Permiso denegado".
¿Por qué esto es tan? ¿Y cómo hago que sudo echo
funcione? (Por cierto, traté de usar sudo cat
también, pero eso falló con el permiso denegado también)
El problema es que la redirección está siendo procesada por su shell original, no por sudo
. Las conchas no son capaces de leer las mentes y no saben que ese particular >>
es para sudo
y no para eso.
Necesitas:
- citar la redirección (por lo que se pasa a
sudo)
- y use
sudo -s
(para quesudo
use un shell para procesar la redirección citada).
http://www.innovationsts.com/blog/?p=2758
Como las instrucciones no son claras anteriormente, estoy usando las instrucciones de esa publicación de blog. Con ejemplos para que sea más fácil ver lo que necesita hacer.
$ sudo cat /root/example.txt | gzip> /root/example.gz
-bash: /root/example.gz: Permiso denegado
Tenga en cuenta que es el segundo comando (el comando gzip) en la tubería que causa el error. Ahí es donde entra nuestra técnica de usar bash con la opción -c.
$ sudo bash -c ''cat /root/example.txt | gzip> /root/example.gz ''
$ sudo ls /root/example.gz
/root/example.gz
Podemos ver desde la salida del comando ls que la creación del archivo comprimido tuvo éxito.
El segundo método es similar al primero en que estamos pasando una cadena de comandos a bash, pero lo estamos haciendo en una canalización a través de sudo.
$ sudo rm /root/example.gz
$ echo "cat /root/example.txt | gzip> /root/example.gz" | sudo bash
$ sudo ls /root/example.gz
/root/example.gz
PASO 1 crea una función en un archivo bash
## write_pacman.sh
write_pacman(){
sudo tee -a /etc/pacman.conf > /dev/null << ''EOF''
[archlinuxfr]
Server = http://repo.archlinux.fr//$arch
EOF
}
''EOF''
no interpretará la variable $arch
.
Archivo bash fuente STE2
$ source write_pacman.sh
PASO 3 ejecutar la función
$ write_pacman
sudo bash -c ''echo "[archlinuxfr]" >> /etc/pacman.conf''