Saltar al contenido

¿Por qué sudo cat da un permiso denegado pero sudo vim funciona bien?

Solución:

Como explicó @geekosaur, el shell realiza la redirección antes de ejecutar el comando. Cuando escribe esto:

sudo foo >/some/file

Su proceso de shell actual hace una copia de sí mismo que primero intenta abrir /some/file para escribir, entonces, si tiene éxito, hace que el descriptor de archivo sea su salida estándar, y solo si tiene éxito, se ejecuta sudo. Esto está fallando en el primer paso.

Si está permitido (las configuraciones de sudoer a menudo impiden ejecutar shells), puede hacer algo como esto:

sudo bash -c 'foo >/some/file'

Pero encuentro una buena solución en general es usar | sudo tee en lugar de > y | sudo tee -a en lugar de >>. Eso es especialmente útil si la redirección es la única razón por la que necesito sudo en primer lugar; después de todo, ejecutar procesos innecesariamente como root es precisamente lo que sudo fue creado para evitar. Y corriendo echo como root es una tontería.

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

yo añadí > /dev/null al final porque tee envía su salida a ambos el archivo nombrado y su propia salida estándar, y no necesito verla en mi terminal. (Los tee El comando actúa como un conector “T” en una canalización física, que es de donde obtiene su nombre). Y cambié a comillas simples ('') en lugar de dobles ("") para que todo sea literal y no tuve que poner una barra invertida delante de la $ en $arch. (Sin las comillas ni la barra invertida, $arch sería reemplazado por el valor del parámetro de shell arch, que probablemente no existe, en cuyo caso el $arch es reemplazado por nada y simplemente desaparece.)

Entonces eso se encarga de escribir en archivos como root usando sudo. Ahora, para una larga digresión sobre las formas de generar texto que contiene una nueva línea en un script de shell. 🙂

Para BLUF, como dicen, mi solución preferida sería simplemente alimentar un documento aquí en el anterior sudo tee mando; entonces no hay necesidad de cat o echo o printf o cualquier otro comando. Las comillas simples se han trasladado a la introducción centinela <<'EOF', pero tienen el mismo efecto allí: el cuerpo se trata como texto literal, por lo que $arch se queda solo:

sudo tee -a /etc/pacman.conf >/dev/null <<'EOF'
[archlinuxfr]
Server = http://repo.archlinux.fr/$arch

EOF

Pero aunque así es como lo haría, hay alternativas. A continuación, presentamos algunos:

Puedes quedarte con uno echo por línea, pero agrúpelos todos juntos en una subcapa, por lo que solo tiene que agregarlos al archivo una vez:

(echo '[archlinuxfr]'
 echo 'Server = http://repo.archlinux.fr/$arch'
 echo ' ') | sudo tee -a /etc/pacman.conf >/dev/null

Si agrega -e al echo (y está usando un shell que admite esa extensión que no es POSIX), puede incrustar nuevas líneas directamente en la cadena usando n:

# NON-POSIX - NOT RECOMMENDED
echo -e '[archlinuxfr]nServer = http://repo.archlinux.fr/$archn ' | 
  sudo tee -a /etc/pacman.conf >/dev/null

Pero como dice arriba, ese no es un comportamiento especificado por POSIX; tu caparazón podría simplemente hacer eco de un literal -e seguido de una cadena con un montón de literal ns en su lugar. La forma POSIX de hacerlo es usar printf en lugar de echo; trata automáticamente su argumento como echo -e lo hace, pero no agrega automáticamente una nueva línea al final, por lo que debe agregar un n ahí también:

printf '[archlinuxfr]nServer = http://repo.archlinux.fr/$archn n' | 
  sudo tee -a /etc/pacman.conf >/dev/null

Con cualquiera de esas soluciones, lo que obtiene el comando como una cadena de argumentos contiene la secuencia de dos caracteres n, y depende del programa de comando en sí (el código dentro printf o echo) para traducir eso en una nueva línea. En muchos shells modernos, tiene la opción de usar comillas ANSI $'', que traducirá secuencias como n dentro literal nuevas líneas antes de que el programa de comando vea la cadena. Eso significa que tales cadenas funcionan con cualquier comando, incluido el antiguo -e-menos echo:

echo $'[archlinuxfr]nServer = http://repo.archlinux.fr/$archn ' | 
  sudo tee -a /etc/pacman.conf >/dev/null

Pero, aunque es más portátil que echo -e, Las cotizaciones ANSI siguen siendo una extensión que no es POSIX.

Y de nuevo, si bien esas son todas las opciones, prefiero la recta tee <<EOF solución anterior.

El problema es que la redirección está siendo procesada por su shell original, no por sudo. Los caparazones no son capaces de leer la mente y no saben que ese particular >> está destinado a la sudo y no por eso.

Necesitas:

  1. cite la redirección (por lo que se pasa a sudo)
  2. y usar sudo -s (así que eso sudo usa un shell para procesar la redirección entre comillas).

http://www.innovationsts.com/blog/?p=2758

Como las instrucciones no son tan claras arriba, 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 canalización el 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 en la salida del comando ls que la creación del archivo comprimido tuvo éxito.

El segundo método es similar al primero en que le estamos pasando una cadena de comando 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

¡Haz clic para puntuar esta entrada!
(Votos: 0 Promedio: 0)



Utiliza Nuestro Buscador

Deja una respuesta

Tu dirección de correo electrónico no será publicada. Los campos obligatorios están marcados con *