it-swarm-es.tech

Redirigir stdout a un archivo en el que no tiene permiso de escritura

Cuando intentas modificar un archivo sin tener permisos de escritura, obtienes un error:

> touch /tmp/foo && Sudo chown root /tmp/foo
> echo test > /tmp/foo
zsh: permission denied: /tmp/foo

Sudoing no ayuda, porque ejecuta el comando como root, pero el Shell maneja la redirección stdout y abre el archivo como usted de todos modos:

> Sudo echo test > /tmp/foo
zsh: permission denied: /tmp/foo

¿Hay una manera fácil de redirigir stdout a un archivo en el que no tiene permiso para escribir, además de abrir un Shell como root y manipular el archivo de esa manera?

> Sudo su
# echo test > /tmp/foo
115
Michael Mrozek

Sí, usando tee. Entonces echo test > /tmp/foo se convierte

echo test | Sudo tee /tmp/foo

También puedes agregar (>>)

echo test | Sudo tee -a /tmp/foo
119
Gert

Para reemplazar el contenido del archivo con la salida de echo (como el > Operador de redireccionamiento de shell).

echo test | Sudo dd of=/tmp/foo

Para escribir en el archivo (al principio, aunque puede usar seek para generar en diferentes desplazamientos) sin truncar (como el 1<> Operador Bourne Shell):

echo test | Sudo dd of=/tmp/foo conv=notrunc

Para adjuntar al archivo (como >>), con GNU dd:

echo test | Sudo dd of=/tmp/foo oflag=append conv=notrunc

Ver también GNU dd 's conv=excl para evitar tropezar con un archivo existente (como con set -o noclobber en shells POSIX) y conv=nocreat para lo contrario (solo actualiza un archivo existente).

27
Chris Jepeway

tee es probablemente la mejor opción, pero dependiendo de su situación, algo como esto puede ser suficiente:

Sudo sh -c 'echo test > /tmp/foo'
14
phunehehe

Si bien estoy de acuerdo, que | Sudo tee es la forma canónica, a veces sed (aquí suponiendo que GNU sed) puede funcionar:

cat sudotest 
line 1

Sudo sed -i '1iitest' sudotest && cat sudotest 
itest
line 1

Sudo sed -i '$aatest' sudotest && cat sudotest 
itest
line 1
atest

-i modifica el archivo en su lugar. 1i significa insertar antes de la línea 1. $a significa agregar después de la última línea.

O copiar a xclipboard:

somecommand | xclip
Sudo gedit sudotest
move cursor to desired place, click middle mouse button to insert, save
5
user unknown

He estado dando vueltas en el fondo de mis ideas para un problema similar, y se me ocurrieron las siguientes soluciones:

  • Sudo uncat donde uncat es un programa que lee la entrada estándar y la escribe en el archivo nombrado en la línea de comando, pero todavía no he escrito uncat.

  • sudocat la variante de sudoedit que aún no he escrito que hace un limpiador Sudo cat o Sudo uncat.

  • o este pequeño truco de usar sudoedit con un EDITOR que es un script de Shell

    #!/bin/sh
    # uncat
    cat > "$1"
    

    que se puede invocar como |Sudo ./uncat file o | EDITOR=./uncat sudoedit pero eso tiene efectos secundarios interesantes.

2
hildred

Use esponja del paquete moreutils. Tiene la ventaja de que no escribe en stdout.

echo test | Sudo sponge /tmp/foo

Use la opción -a para agregar a un archivo en lugar de sobrescribirlo.

1
Hontvári Levente

El error proviene del orden en que Shell hace las cosas.

La redirección se maneja antes de que el Shell incluso ejecute Sudo, y por lo tanto se realiza con los permisos del usuario con el que está trabajando actualmente. Dado que no tiene permisos de escritura para crear/truncar el objetivo de la redirección, obtiene un permission denied error del Shell.

La solución es garantizar que el archivo de salida se cree con la identidad que Sudo le proporcionó, p. con tee:

$ generate_output | Sudo tee target_file
0
Kusalananda