Como resolver a "permissão negada" ao usar o sudo com o redirecionamento no Bash?

138

Ao usar o sudo para permitir edições em arquivos, recebo regularmente 'permissão negada'.

Por exemplo, meu mouse está nervoso e lento, então eu quero desativar a pesquisa:

sudo echo "options drm_kms_helper poll=N">/etc/modprobe.d/local.conf

Sou solicitada uma senha e, em seguida, obtenho:

bash: /etc/modprobe.d/local.conf: Permission denied

Então, tentei fazer uma alteração temporária para desativar a pesquisa usando:

sudo echo N> /sys/module/drm_kms_helper/parameters/poll

Mais uma vez, o sistema respondeu com:

bash: /sys/module/drm_kms_helper/parameters/poll: Permission denied

Alguma ideia?

Jack
fonte

Respostas:

157

O redirecionamento de saída (via >operador) é feito pelo shell, não pelo eco . Você precisa fazer login como root

sudo -i

Então você pode usar o redirecionamento

echo N> /sys/module/drm_kms_helper/parameters/poll

Caso contrário, você pode executar o bash string com o sudo

sudo bash -c "echo N> /sys/module/drm_kms_helper/parameters/poll"
shantanu
fonte
11
Você não pode executar eco com sudo? o que sobre o resultado que obtive:saji@laptop:~$ sudo echo "Hi" [sudo] password for saji: Hi
saji89
você pode escrever em arquivo, repetir "algo"> de alguma forma. Está usando cachimbo .. Esse é o problema.
Shantanu
4
Ok, se for esse o caso, atualize sua resposta para refletir que o eco em execução é um problema apenas nesse caso.
saji89
Você não pode simplesmente executar o shell embutido echocomo sudo, a menos que faça algo como sudo bash -c 'echo …'; no entanto, os sistemas POSIX geralmente fornecem um echocomando externo , como /bin/echono OS X, que o sudo pode executar sem o rigamarole. Portanto, o echocomando que você normalmente executa e o echocomando com sudo são provavelmente dois comandos diferentes, mas semelhantes.
Kojiro
Se for esse o caso, por que as respostas a essa pergunta sugerem eco? askubuntu.com/questions/840431/...
Harsha
75

O redirecionamento de saída é feito pelo shell a partir do qual o comando foi chamado . Então, dividindo tudo em bits, aqui está o que está acontecendo *:

  • shell chama sudo echo "options drm_kms_helper poll=N", que executa sudocomando com echo "options drm_kms_helper poll=N"linha de comando

  • sudo pede uma senha, abre o shell do superusuário e chama echo "options drm_kms_helper poll=N", que executa o echocomando passando-o"options drm_kms_helper poll=N"

  • echo, executando com rootprivilégios, imprime a string na saída padrão.

  • echoO comando termina, o shell do superusuário sai, sudotermina

  • o shell do qual o comando foi chamado coleta a saída e tenta redirecioná-la para /etc/modprobe.d/local.conf, que é gravável apenas pela raiz. Ele recebe o erro "permissão negada".

Para formas de corrigir isso, consulte a resposta @shantanu.


(*) - enquanto a sequência acima ajuda a entender por que o comando falha, na realidade as coisas acontecem um pouco fora de ordem: o shell original percebe o redirecionamento e tenta abrir o arquivo para gravação antes de chamar o sudo ...comando. Ao abrir o arquivo falha, o shell nem chama o comando que deveria escrever no arquivo (obrigado a @PanosRontogiannis por apontar isso).

Aqui está um teste rápido:

$ touch ./onlyroot.txt
$ sudo chown root:root ./onlyroot.txt
$ sudo bash -c "whoami | tee who.txt" > onlyroot.txt
bash: onlyroot.txt: Permission denied

No teste acima, whoami | tee who.txtcriaríamos um arquivo chamado who.txtcontendo a palavra "raiz". No entanto, quando o redirecionamento de saída falha no shell de chamada, o arquivo "who.txt" também está ausente porque o comando não foi chamado.

Sergey
fonte
Provavelmente, o shell 'bifurca-se' e tenta abrir o arquivo /etc/modprobe.d/local.conf antes de tentar o 'exec' sudo, o que significa que as primeiras 4 etapas que sua descrição nunca acontecem porque o arquivo não pode ser aberto.
Panos Rontogiannis
11
@PanosRontogiannis: obrigado, eu atualizei a resposta
Sergey
60

Adicionando à resposta de Shantanu:

... Ou você pode usar um teecomando como este:

sudo tee /sys/module/drm_kms_helper/parameters/poll <<<10

ou se for a saída de um comando:

echo 10 | sudo tee /sys/module/drm_kms_helper/parameters/poll
Sem título
fonte
3
+1 logging como root é uma má idéia para o trabalho manual e um realmente má idéia para tarefas de script.
L0b0
2
Além disso, sudo tee /sys/module/drm_kms_helper/parameters/poll > /dev/nullse você não quiser imprimir stdouttambém.
Fabian Tamp
16

Uma abordagem que não vi mencionada aqui é simplesmente executar toda a linha de comando em seu próprio shell. A sudoprópria página de manual fornece um exemplo dessa abordagem:

Para fazer uma lista de uso dos diretórios na partição / home. Observe que isso executa os comandos em um sub-shell para fazer o redirecionamento de CD e arquivo funcionar.

$ sudo sh -c "cd /home ; du -s * | sort -rn > USAGE"
kojiro
fonte
uau obrigado. uma solução simples
Resiliência
4

Outra opção é usar um arquivo temporário. Isso é útil em um script bash.

temp=$(mktemp)
echo "Hello, world!" > $temp
sudo cp $temp /etc/wherever
user545424
fonte
3

sudo dd of=

Para adicionar como quiser:

echo inbytes | sudo dd of=outfile oflag=append conv=notrunc

ou para recriar o arquivo do zero:

echo inbytes | sudo dd of=outfile

Vantagens:

  • melhor do que teedesde nenhum /dev/nullredirecionamento
  • melhor do shque nenhuma sub-camada explícita (mas implícita para o redirecionamento)
  • ddpossui muitas opções poderosas, por exemplo, status=progresspara ver o progresso da transferência

Funciona porque o sudo encaminha o stdin para o comando.

Ciro Santilli adicionou uma nova foto
fonte
11
Isso é bom. Pensamos ddem como substituímos nossos sistemas de arquivos outrora ótimos, e não percebemos que isso também é para tarefas mundanas - e que outros comandos como root também causam grandes danos se usados ​​em arquivos / dispositivos errados. Comosudo tee , sudo ddé claro, também funcionará com as strings here , por exemplo sudo dd of=outfile <<<'hello world',. [Obrigado pela edição. NB com sh -c 'cmd', shé um subprocesso que é uma concha, mas não realmente um subshell exceto no sentido de todos os comandos externos começam como um].
Elias Kagan