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?

David
fuente

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.

Yoo
fuente
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"
Matt P
fuente
¿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"
Incidente
fuente
@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
19
sudo sh -c "echo 127.0.0.1 localhost >> /etc/hosts"
Vinko Vrsalovic
fuente
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".

agnul
fuente
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"
msanford
fuente
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
Vytenis Bivainis
fuente
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
}
hololeap
fuente
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
Michael Goldshteyn
fuente
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
Noam Manos
fuente
0

echo 'Hola mundo' | (sudo tee -a /etc/apt/sources.list)

Sudev Shetty
fuente
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

Marcelo Pacheco
fuente
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
Fthi.a.Abadi
fuente
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?

pixistix
fuente
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