Como uso o sudo para redirecionar a saída para um local no qual não tenho permissão para escrever?
-
09-06-2019 - |
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?
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 usotee -a
outee --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