sudo echo "algo" >> / etc / privilegedFile no funciona


586

Esta es una pregunta bastante simple, al menos parece que debería ser, sobre los permisos de sudo en Linux.

Hay un montón de veces cuando sólo quiero añadir algo a /etc/hostso un archivo similar, pero terminan por no poder porque ambos >y >>no se les permite, incluso con raíz.

¿Hay alguna manera de hacer que esto funcione sin tener que hacerlo suo sudo suen la raíz?

Respuestas:


855

Use tee --appendo tee -a.

echo 'deb blah ... blah' | sudo tee -a /etc/apt/sources.list

Asegúrese de evitar las comillas dentro de las comillas.

Para evitar volver a imprimir datos en la consola, redirija la salida a / dev / null.

echo 'deb blah ... blah' | sudo tee -a /etc/apt/sources.list > /dev/null

¡Recuerda la bandera ( -a/ --append)! Simplemente teefunciona como >y sobrescribirá su archivo. tee -afunciona como >>y escribirá al final del archivo.


3
Absolutamente prefiero este. Es simplemente el más simple (y me pareció sobre tee, que también es útil en otros escenarios).
Joachim Sauer

55
Estoy de acuerdo. Parece más limpio que se inicia un nuevo sh también, especialmente con potencial para hacer cosas con el medio ambiente, etc.
Sam Brightman

39
Una cosa importante a tener en cuenta: ¡NUNCA olvide el -a! Imagínese lo echo 'tmpfs /tmp tmpfs defaults 0 0' | sudo tee /etc/fstabque haría
mic_e

21
Bajo OS X, esto debería ser en tee -alugar de tee --append.
Knite

26
Para aquellos que no entienden lo que @mic_e dijo: sin la-a--append bandera ( ), el comando sobrescribiría todo el archivo con la cadena dada en lugar de agregarlo al final.
totymedli

314

El problema es que el shell realiza la redirección de salida, no sudo o echo, por lo que esto se hace como su usuario habitual.

Pruebe el siguiente fragmento de código:

sudo sh -c "echo 'something' >> /etc/privilegedfile"

¿Qué son los "límites de permisos de sudo"? Es solo el shell que analiza el operador de redireccionamiento con mayor precedencia que un comando por razones obvias
Vinko Vrsalovic

1
Dependiendo de su sh, echo puede interpretar secuencias de escape como \tdentro de comillas simples. Podrías usar printf %s 'something'en su lugar.
Lri

Usar tee es más popular y más compatible con las nuevas distribuciones.
Eduardo B.

1
Este es el único que funciona tal cual como un comando SSH que se puede ejecutar en un nodo remoto.
Duncan Lock

Estoy de acuerdo con otras publicaciones aquí. Esto usa un shell y solo un shell, por lo que aquí no se requiere otro programa como tee. Sí, sé que tee ya está instalado, pero tal vez no dependa de la microdistro que esté utilizando como huesos alpinos. Me gusta que también tengas una opción de shell: sudo /bin/bash -c "echo 'fs.inotify.max_user_watches = 524288' > /etc/sysctl.d/60-golang-inotify.conf"por ejemplo.
Ligemer

35

El problema es que es su shell el que maneja la redirección; está tratando de abrir el archivo con sus permisos, no los del proceso que está ejecutando bajo sudo.

Use algo como esto, tal vez:

sudo sh -c "echo 'something' >> /etc/privilegedFile"

@GordonSun esto se debe a que sudo(por razones de seguridad) no propaga el entorno al subproceso. Puede usar sudo -Epara evitar esta restricción.
arielf

1
@GordonSun sí, no entiendo por qué sigues repitiendo esta declaración. Si lo hace sudo sh -c "echo 'something' >> $FILENAME", con comillas dobles, esto va a trabajar - la sustitución de variables se realiza por la capa exterior, no la cáscara sudoed.
Nadav Har'El


13

Haciendo

sudo sh -c "echo >> somefile"

Deberia trabajar. El problema es que> y >> son manejados por su shell, no por el comando "sudoed", por lo que los permisos son los suyos, no los del usuario al que está "sudoing".


9

Quisiera señalar, para los curiosos, que también puede citar un heredoc (para bloques grandes):

sudo bash -c "cat <<EOIPFW >> /etc/ipfw.conf
<?xml version=\"1.0\" encoding=\"UTF-8\"?>

<plist version=\"1.0\">
  <dict>
    <key>Label</key>
    <string>com.company.ipfw</string>
    <key>Program</key>
    <string>/sbin/ipfw</string>
    <key>ProgramArguments</key>
    <array>
      <string>/sbin/ipfw</string>
      <string>-q</string>
      <string>/etc/ipfw.conf</string>
    </array>
    <key>RunAtLoad</key>
    <true></true>
  </dict>
</plist>
EOIPFW"

1
Esto funciona muy bien, excepto que las comillas incrustadas pueden necesitar escapar con un \
N Jones

Muy bien @NJones! Editaré mi respuesta. (Tenga en cuenta, sin embargo, que no hacer esto "elimina lo interno pero no hace que el comando falle.)
msanford

8

En bash puedes usarlo teeen combinación con > /dev/nullpara mantener limpio el stdout.

 echo "# comment" |  sudo tee -a /etc/hosts > /dev/null

4

Usando la respuesta de Yoo , pon esto en tu ~/.bashrc:

sudoe() {
    [[ "$#" -ne 2 ]] && echo "Usage: sudoe <text> <file>" && return 1
    echo "$1" | sudo tee --append "$2" > /dev/null
}

Ahora puedes correr sudoe 'deb blah # blah' /etc/apt/sources.list


Editar:

Una versión más completa que le permite canalizar la entrada o redirigir desde un archivo e incluye un -ainterruptor para desactivar los anexos (que está activado de forma predeterminada):

sudoe() {
  if ([[ "$1" == "-a" ]] || [[ "$1" == "--no-append" ]]); then
    shift &>/dev/null || local failed=1
  else
    local append="--append"
  fi

  while [[ $failed -ne 1 ]]; do
    if [[ -t 0 ]]; then
      text="$1"; shift &>/dev/null || break
    else
      text="$(cat <&0)"
    fi

    [[ -z "$1" ]] && break
    echo "$text" | sudo tee $append "$1" >/dev/null; return $?
  done

  echo "Usage: $0 [-a|--no-append] [text] <file>"; return 1
}

2

También puede usar spongedesde el moreutilspaquete y no es necesario redirigir la salida (es decir, sin teeruido para ocultar):

echo 'Add this line' | sudo sponge -a privfile

0

Mediante el uso de sed -i con $ a , puede agregar texto, que contiene variables y caracteres especiales, después de la última línea.

Por ejemplo, agregando $ NEW_HOST con $ NEW_IP a / etc / hosts:

sudo sed -i "\$ a $NEW_IP\t\t$NEW_HOST.domain.local\t$NEW_HOST" /etc/hosts

Opciones de sed explicadas:

  • -i para en el lugar
  • $ para la última línea
  • una para agregar


0

¿Qué tal:
echo text | sudo dd status = none of = privilegedfile
Quiero cambiar / proc / sys / net / ipv4 / tcp_rmem.
Hice:
sudo dd status = none of = / proc / sys / net / ipv4 / tcp_rmem <<< "4096 131072 1024000"
elimina el eco con un solo documento de línea


1
Tómese un momento para leer la ayuda de edición en el centro de ayuda . El formateo en Stack Overflow es diferente al de otros sitios.
Dharman el

-1

Esto funcionó para mí: comando original

echo "export CATALINA_HOME="/opt/tomcat9"" >> /etc/environment

Comando de trabajo

echo "export CATALINA_HOME="/opt/tomcat9"" |sudo tee /etc/environment

1
Debe ser tee -a. ¡Solo teesobrescribirá el archivo!
codeforester

-6

¿Puedes cambiar la propiedad del archivo y luego volver a cambiarlo después de usarlo cat >>para agregar?

sudo chown youruser /etc/hosts  
sudo cat /downloaded/hostsadditions >> /etc/hosts  
sudo chown root /etc/hosts  

¿Algo como esto funciona para ti?


44
Chown es un comando destructivo para usar. Si un administrador de configuración lo usó para actualizar / etc / hosts, de repente / etc / hosts pertenece al usuario de configuración y no a la raíz. lo que potencialmente conduce a otros procesos que no tienen acceso a / etc / hosts. El objetivo de sudo es evitar que algo inicie sesión en la raíz y, a través de sudoers, también se pueden acumular más restricciones.
David
Al usar nuestro sitio, usted reconoce que ha leído y comprende nuestra Política de Cookies y Política de Privacidad.
Licensed under cc by-sa 3.0 with attribution required.