Pergunta

Recebi acesso sudo em uma de nossas caixas Linux RedHat de desenvolvimento e parece que muitas vezes preciso redirecionar a saída para um local ao qual normalmente não tenho acesso de gravação.

O problema é que este exemplo inventado não funciona:

sudo ls -hal /root/ > /root/test.out

Acabei de receber a resposta:

-bash: /root/test.out: Permission denied

Como posso fazer isso funcionar?

Foi útil?

Solução

O comando não funciona porque o redirecionamento é executado pelo shell que não tem a permissão para gravar /root/test.out. O redirecionamento da saída não é realizada por sudo.

Existem várias soluções:

  • Executar um shell com o sudo e dar o comando a ele usando a opção -c:

    sudo sh -c 'ls -hal /root/ > /root/test.out'
    
  • Crie um script com os seus comandos e executar esse script com sudo:

    #!/bin/sh
    ls -hal /root/ > /root/test.out
    

    Executar sudo ls.sh. Veja Steve Bennett resposta se você não quiser criar um arquivo temporário.

  • Lançamento de um shell com sudo -s em seguida, executar os comandos:

    [nobody@so]$ sudo -s
    [root@so]# ls -hal /root/ > /root/test.out
    [root@so]# ^D
    [nobody@so]$
    
  • Use sudo tee (se você tem que fugir de um lote ao usar a opção -c):

    sudo ls -hal /root/ | sudo tee /root/test.out > /dev/null
    

    O redirecionamento para /dev/null é necessário para parar T de saída para a tela. Para append em vez de substituir o arquivo de saída (>>), o uso tee -a ou tee --append (o último é específico para GNU coreutils ).

Os agradecimentos vão para Jd , Adam J. Forster e Johnathan para a segunda, terceira e quarta soluções.

Outras dicas

Alguém aqui tem apenas sugeriu tee sudoing:

sudo ls -hal /root/ | sudo tee /root/test.out > /dev/null

Esta também poderia ser usado para redirecionar qualquer comando, para um diretório que você não tem acesso. Ele funciona porque o programa tee é efetivamente um "echo para um arquivo" do programa, eo redirecionamento para / dev / null é parar também a saída para a tela para mantê-lo o mesmo que o exemplo inventado originais acima.

Um truque que eu descobri me era

sudo ls -hal /root/ | sudo dd of=/root/test.out

O problema é que o comando é executado sob sudo, mas o redirecionamento é executado sob o seu usuário. Isso é feito pelo shell e há muito pouco que você pode fazer sobre isso.

sudo command > /some/file.log
`-----v-----'`-------v-------'
   command       redirection

As formas usuais de contornar isso são:

  • Enrole os comandos em um script que você ligar em sudo.

    Se os comandos e / ou alterações de arquivo de log, você pode fazer o script de tomá-los como argumentos. Por exemplo:

    sudo log_script command /log/file.txt
    
  • Chamar um shell e passar a linha de comando como um parâmetro com -c

    Isto é especialmente útil para um fora comandos compostos. Por exemplo:

    sudo bash -c "{ command1 arg; command2 arg; } > /log/file.txt"
    

Ainda outra variação sobre o tema:

sudo bash <<EOF
ls -hal /root/ > /root/test.out
EOF

Ou é claro:

echo 'ls -hal /root/ > /root/test.out' | sudo bash

Eles têm a (pequena) vantagem de que você não precisa se lembrar de quaisquer argumentos para sudo ou sh / bash

Esclarecendo um pouco sobre por que a opção tee é preferível

Assumindo que você tem permissão adequada para executar o comando que cria a saída, se você canalizar a saída do seu comando para tee, você só precisa privledges do tee elevar com sudo e tee direta para escrever (ou acrescentar) para o arquivo em questão.

no exemplo dado na questão que significaria:

ls -hal /root/ | sudo tee /root/test.out

Para um par exemplos mais práticos:

# kill off one source of annoying advertisements
echo 127.0.0.1 ad.doubleclick.net | sudo tee -a /etc/hosts

# configure eth4 to come up on boot, set IP and netmask (centos 6.4)
echo -e "ONBOOT=\"YES\"\nIPADDR=10.42.84.168\nPREFIX=24" | sudo tee -a /etc/sysconfig/network-scripts/ifcfg-eth4

Em cada um destes exemplos que você está tomando a saída de um comando não privilegiado e escrevendo para um arquivo que é normalmente só gravável por raiz, que é a origem da sua pergunta.

É uma boa idéia para fazê-lo desta maneira, porque o comando que gera a saída não é executado com privilégios elevados. Ele não parece importar aqui com echo mas quando o comando source é um script que você não confiar completamente, é crucial.

Note que você pode usar a opção -a para tee para acrescentar append (como >>) para o arquivo de destino, em vez de substituí-lo (como >).

Faça sudo executar um shell, como este:

sudo sh -c "echo foo > ~root/out"

A forma como eu iria sobre esta questão é:

Se você precisa escrever / substituir o arquivo:

echo "some text" | sudo tee /path/to/file

Se você precisa de acréscimo para o arquivo:

echo "some text" | sudo tee -a /path/to/file

Como sobre como escrever um script?

Nome do arquivo: myscript

#!/bin/sh

/bin/ls -lah /root > /root/test.out

# end script

Em seguida, use sudo para executar o script:

sudo ./myscript

Gostaria de fazê-lo desta maneira:

sudo su -c 'ls -hal /root/ > /root/test.out'

Sempre que eu tenho que fazer algo assim eu raiz apenas tornar-se:

# sudo -s
# ls -hal /root/ > /root/test.out
# exit

Provavelmente não é o melhor caminho, mas funciona.

Não quero bater um cavalo morto, mas há muitas respostas aqui que o uso tee, o que significa que você tem que redirecionar stdout para /dev/null menos que você queira ver uma cópia na tela. A solução mais simples é cat uso como esta:

sudo ls -hal /root/ | sudo bash -c "cat > /root/test.out"

Observe como o redirecionamento é colocado dentro de aspas para que seja avaliada por um escudo começou por sudo em vez do executá-lo.

Esta é baseada na resposta envolvendo tee. Para facilitar as coisas que eu escrevi um pequeno script (eu chamo de suwrite) e colocá-lo em /usr/local/bin/ com permissão +x:

#! /bin/sh
if [ $# = 0 ] ; then
    echo "USAGE: <command writing to stdout> | suwrite [-a] <output file 1> ..." >&2
    exit 1
fi
for arg in "$@" ; do
    if [ ${arg#/dev/} != ${arg} ] ; then
        echo "Found dangerous argument ‘$arg’. Will exit."
        exit 2
    fi
done
sudo tee "$@" > /dev/null

Como mostrado na Utilização no código, tudo que você tem a fazer é canalizar a saída para esse script seguido pelo nome do arquivo superusuário acessível desejado e ele será automaticamente solicitará sua senha em caso necessário (desde que inclui sudo).

echo test | suwrite /root/test.txt

Note que uma vez que este é um wrapper simples para tee, que também irá aceitar opção -a do tee para acrescentar, e também suporta escrevendo para vários arquivos ao mesmo tempo.

echo test2 | suwrite -a /root/test.txt
echo test-multi | suwrite /root/test-a.txt /root/test-b.txt

Ele também tem alguma proteção simplista contra escrevendo para dispositivos /dev/ que foi uma preocupação mencionado em um dos comentários nesta página.

Talvez você foi dado acesso ao sudo para apenas alguns programas / caminhos? Então não há nenhuma maneira de fazer o que quiser. (A menos que você vai cortá-lo de alguma forma)

Se não for o caso, então talvez você pode escrever um script bash:

cat > myscript.sh
#!/bin/sh
ls -hal /root/ > /root/test.out 

Pressione Ctrl + d :

chmod a+x myscript.sh
sudo myscript.sh

Hope isso ajuda.

sudo at now  
at> echo test > /tmp/test.out  
at> <EOT>  
job 1 at Thu Sep 21 10:49:00 2017  
Licenciado em: CC-BY-SA com atribuição
Não afiliado a StackOverflow
scroll top