Estoy tratando de automatizar la adición de una fuente de repositorio en el archivo pacman.conf de mi arco, pero usando el echocomando 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 salir de 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 llego sudo echoal trabajo? (por cierto, intenté usar sudo cattambién pero falló con el permiso denegado también)

Respuestas:
El problema es que la redirección está siendo procesada por su shell original, no por
sudo. Los shells no son capaces de leer la mente y no saben que ese particular>>está destinado a élsudoy no a él.Necesitas:
sudo)sudo -s(de modo quesudouse un shell para procesar la redirección citada).fuente
sudo -s(2) echo "# test" >> /etc/pacman.conf funciona. Pero, ¿es posible ejecutar esto en una sola línea?sudo -s 'echo "# test" >>/etc/pacman.conf'es lo que estaba tratando de transmitirles.sudo -s 'echo "# test" >> /etc/pacman.conf' /bin/bash: echo "# test" >> /etc/pacman.conf: No such file or directorypor eso probé posteriormente el proceso manual de 2 pasos.echo 'echo "# test" >> /etc/pacman.conf' | sudo -ssudodesactivación de la configuración-s? visudo?Como explicó @geekosaur, el shell realiza la redirección antes de ejecutar el comando. Cuando escribe esto:
Su proceso de shell actual hace una copia de sí mismo que primero intenta abrirse
/some/filepara escritura, luego hace que ese descriptor de archivo sea su salida estándar y solo entonces se ejecutasudo.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 que una buena solución en general es usar en
| sudo teelugar de>y en| sudo tee -alugar de>>. Eso es especialmente útil si la redirección es la única razón que necesitosudoen primer lugar; después de todo, ejecutar procesos innecesariamente como root es precisamente lo quesudose creó para evitar. Y correrechocomo 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/nullAgregué
> /dev/nullal final porqueteeenvía su salida tanto al archivo con nombre como a su propia salida estándar, y no necesito verlo en mi terminal. (Elteecomando actúa como un conector "T" en una tubería 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 tener que poner una barra invertida delante de la$en$arch. (Sin las comillas o la barra invertida,$archsería reemplazado por el valor del parámetro de shellarch, que probablemente no existe, en cuyo caso$archse reemplaza 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 introducir un documento aquí en el
sudo teecomando anterior ; entonces no hay necesidad decatoechooprintfo cualquier otro comando en absoluto. 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$archse deja solo:sudo tee -a /etc/pacman.conf >/dev/null <<'EOF' [archlinuxfr] Server = http://repo.archlinux.fr/$arch EOFPero aunque así es como lo haría, hay alternativas. A continuación, presentamos algunos:
Puede quedarse con uno
echopor línea, pero agruparlos todos en una subcapa, por lo que solo tiene que agregar al archivo una vez:(echo '[archlinuxfr]' echo 'Server = http://repo.archlinux.fr/$arch' echo ' ') | sudo tee -a /etc/pacman.conf >/dev/nullSi agrega
-eaecho(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/$arch\n ' | sudo tee -a /etc/pacman.conf >/dev/nullPero como dice arriba, ese no es un comportamiento especificado por POSIX; su shell podría simplemente repetir un literal
-eseguido de una cadena con un montón de literales en\nsu lugar. La forma POSIX de hacerlo es usar enprintflugar deecho; trata automáticamente su argumento como loecho -ehace, pero no agrega automáticamente una nueva línea al final, por lo que también debe agregar un extra\nallí:printf '[archlinuxfr]\nServer = http://repo.archlinux.fr/$arch\n \n' | sudo tee -a /etc/pacman.conf >/dev/nullCon cualquiera de esas soluciones, lo que el comando obtiene como una cadena de argumento contiene la secuencia de dos caracteres
\n, y depende del programa de comando en sí (el código dentro deprintfoecho) traducir eso en una nueva línea. En muchos shells modernos, tiene la opción de usar comillas ANSI$'...', que traducirán secuencias como\nen líneas nuevas literales antes de que el programa de comando vea la cadena. Eso significa que este tipo de cadenas funcionan con cualquier comando que sea, incluyendo a secas-e-menosecho:echo $'[archlinuxfr]\nServer = http://repo.archlinux.fr/$arch\n ' | sudo tee -a /etc/pacman.conf >/dev/nullPero, aunque son más portátiles que
echo -e, las citas ANSI siguen siendo una extensión que no es POSIX.Y nuevamente, si bien esas son todas las opciones, prefiero la
tee <<EOFsolución directa anterior.fuente
sudo bash -c 'foo >/some/file'funciona para mí en osx :-)cat <<EOF | sudo tee -a /some/file > /dev/null ...catproceso extraño . :)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.
Observe que es el segundo comando (el comando gzip) en la canalización el que causa el error. Ahí es donde entra en juego nuestra técnica de usar bash con la opción -c.
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.
fuente
sudo bash -c 'echo "[archlinuxfr]" >> /etc/pacman.conf'fuente
PASO 1 crea una función en un archivo bash (
write_pacman.sh)#!/bin/bash function write_pacman { tee -a /etc/pacman.conf > /dev/null << 'EOF' [archlinuxfr] Server = http://repo.archlinux.fr/\$arch EOF }'EOF'no interpretará la$archvariable.Archivo bash fuente STE2
$ source write_pacman.shPASO 3 ejecutar la función
fuente
añadir archivos (sudo cat):
añadir eco al archivo (sudo echo):
echo <origin> | sudo tee -a <target-file>(EXTRA) ignore la salida:
echo >origin> | sudo tee -a <target-file> >/dev/nullfuente