Redirecionando o stdout para um arquivo no qual você não tem permissão de escrita

102

Quando você tenta modificar um arquivo sem ter permissões de gravação nele, você recebe um erro:

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

Sudoing não ajuda, porque ele executa o comando como root, mas o shell manipula o redirecionamento de stdout e abre o arquivo da mesma forma que você:

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

Existe uma maneira fácil de redirecionar o stdout para um arquivo que você não tem permissão para gravar, além de abrir um shell como root e manipular o arquivo dessa maneira?

> sudo su
# echo test > /tmp/foo
    
por Michael Mrozek 31.08.2010 / 08:18

7 respostas

105

Sim, usando tee . Então, echo test > /tmp/foo torna-se

echo test | sudo tee /tmp/foo

Você também pode acrescentar ( >> )

echo test | sudo tee -a /tmp/foo
    
por 31.08.2010 / 08:47
26

Para substituir o conteúdo do arquivo pela saída de echo (como o operador de redirecionamento de > ).

echo test | sudo dd of=/tmp/foo

Para gravar no arquivo (no início, embora você possa usar seek para produzir em diferentes deslocamentos) sem truncar (como o operador shell 1<> Bourne):

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

Para anexar ao arquivo (como >> ), com GNU dd :

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

Veja também dd do conv=excl do GNU para evitar a supressão de um arquivo existente (como com set -o noclobber em shells POSIX) e conv=nocreat para o oposto (apenas atualize um arquivo existente).

    
por 03.09.2010 / 06:19
12

tee é provavelmente a melhor escolha, mas dependendo da sua situação, algo assim pode ser suficiente:

sudo sh -c 'echo test > /tmp/foo'
    
por 31.08.2010 / 09:28
5

Embora eu concorde, | sudo tee é o caminho canônico, às vezes sed (assumindo aqui o GNU sed ) pode 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 o arquivo no lugar. 1i significa inserir antes da linha 1. $a significa acrescentar após a última linha.

Ou copie para o xclipboard:

somecommand | xclip
sudo gedit sudotest
move cursor to desired place, click middle mouse button to insert, save
    
por 19.07.2011 / 04:11
2

Eu tenho chutado as ideias para um problema semelhante e descobri as seguintes soluções:

  • sudo uncat onde uncat é um programa que lê a entrada padrão e a grava no arquivo chamado na linha de comando, mas ainda não escrevi uncat .

  • sudocat da variante de sudoedit que ainda não escrevi que limpa sudo cat ou sudo uncat .

  • ou este pequeno truque de usar sudoedit com um EDITOR que é um script de shell

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

    que pode ser invocado como |sudo ./uncat file ou | EDITOR=./uncat sudoedit , mas que tem efeitos colaterais interessantes.

por 20.11.2013 / 03:16
1

Use esponja do pacote moreutils. Tem a vantagem de não gravar no stdout.

echo test | sudo sponge /tmp/foo

Use a opção -a para anexar a um arquivo em vez de substituí-lo.

    
por 17.12.2016 / 22:46
0

O erro vem da ordem em que o shell faz as coisas.

O redirecionamento é tratado antes mesmo de o shell executar sudo e, portanto, ser feito com as permissões do usuário com o qual você está trabalhando atualmente. Como você não tem permissões de gravação para criar / truncar o alvo do redirecionamento, você recebe um erro permission denied do shell.

A solução é garantir que o arquivo de saída seja criado com a identidade fornecida por sudo , por exemplo, com tee :

$ generate_output | sudo tee target_file
    
por 04.02.2017 / 10:36