ti-enxame.com

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

Ao tentar modificar um arquivo sem ter permissões de gravação, 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 executa o comando como root, mas o Shell lida com o redirecionamento de stdout e abre o arquivo da mesma maneira:

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

Existe uma maneira fácil de redirecionar o stdout para um arquivo no qual 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
115
Michael Mrozek

Sim, usando tee. Assim echo test > /tmp/foo torna-se

echo test | Sudo tee /tmp/foo

Você também pode acrescentar (>>)

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

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

echo test | Sudo dd of=/tmp/foo

Para gravar no arquivo (no começo, embora você possa usar seek para gerar diferentes compensações) sem truncar (como o 1<> Operador Bourne Shell):

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 GNU dd 's conv=excl para evitar atropelar um arquivo existente (como com set -o noclobber em shells POSIX) e conv=nocreat pelo contrário (atualize apenas um arquivo existente).

27
Chris Jepeway

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

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

Enquanto eu concordo, que | Sudo tee é o caminho canônico, às vezes sed (assumindo aqui 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
5
user unknown

Tenho pensado no fundo de minha mente por 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 nomeado na linha de comando, mas ainda não escrevi uncat.

  • sudocat a variante de sudoedit que ainda não escrevi que faz um limpador Sudo cat ou Sudo uncat.

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

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

    que pode ser chamado como |Sudo ./uncat file ou | EDITOR=./uncat sudoedit mas isso tem efeitos colaterais interessantes.

2
hildred

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.

1
Hontvári Levente

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

O redirecionamento é tratado antes mesmo que o Shell execute Sudo e, portanto, é feito com as permissões do usuário em que você está trabalhando no momento. Como você não tem permissões de gravação para criar/truncar o destino do redirecionamento, você recebe um permission denied erro do Shell.

A solução é garantir que o arquivo de saída seja criado sob a identidade que lhe foi dada por Sudo, por exemplo com tee:

$ generate_output | Sudo tee target_file
0
Kusalananda