bash: / dev / stderr: permissão negada

19

Após a atualização para uma nova versão, meus bashscripts começam a cuspir erros:

bash: /dev/stderr: Permission denied

nas versões anteriores Bash iria reconhecer internamente esses nomes de arquivo (que é por isso que esta questão não é uma duplicata de um presente ) e fazer a coisa certa (tm) , no entanto, isso parou de funcionar agora. O que posso fazer para poder executar meus scripts novamente com sucesso?

Tentei adicionar o usuário executando o script ao grupo tty, mas isso não faz diferença (mesmo após o logout e o login novamente).

Eu posso reproduzir isso na linha de comando sem problemas:

$ echo test > /dev/stdout
bash: /dev/stdout: Permission denied
$ echo test > /dev/stderr
bash: /dev/stderr: Permission denied
$ ls -l /dev/stdout /dev/stderr
lrwxrwxrwx 1 root root 15 May 13 02:04 /dev/stderr -> /proc/self/fd/2
lrwxrwxrwx 1 root root 15 May 13 02:04 /dev/stdout -> /proc/self/fd/1
$ ls -lL /dev/stdout /dev/stderr
crw--w---- 1 username tty 136, 1 May 13 05:01 /dev/stderr
crw--w---- 1 username tty 136, 1 May 13 05:01 /dev/stdout
$ echo $BASH_VERSION
4.2.24(1)-release

Em um sistema mais antigo (Ubuntu 10.04):

$ echo $BASH_VERSION
4.1.5(1)-release
0xC0000022L
fonte
11
Qual é a saída de ls -l /dev/stdout /dev/stderre ls -lL /dev/stdout /dev/stderr?
Keith Thompson
@ Keith: veja minha pergunta editada. Isso significa que o Bash abandonou completamente o tratamento interno disso? Em sistemas mais antigos, esses links simbólicos não existiam e ainda assim o código funcionava sem problemas. Observe que isso está sendo executado via sudo su username2 -...
0xC0000022L
Qual versão do bash você está usando? echo $BASH_VERSION
Jippie
11
Quais são as antigas e novas versões (antes e depois de seu sistema operacional e de bash?
Keith Thompson

Respostas:

41

Eu não acho que isso seja inteiramente um problema de festa.

Em um comentário, você disse que viu esse erro depois de fazer

sudo su username2

quando logado como username. É suisso que está desencadeando o problema.

/dev/stdouté um link simbólico para /proc/self/fd/1, que é um link simbólico para, por exemplo /dev/pts/1,. /dev/pts/1, que é um pseudoterminal, pertence e é gravável por username; essa propriedade foi concedida ao usernameefetuar login. Quando você sudo su username2, a propriedade de /dev/pts/1não é alterada e username2não tem permissão de gravação.

Eu diria que isso é um bug. /dev/stdout deve ser, com efeito, um alias para o fluxo de saída padrão, mas aqui vemos uma situação em que echo hellofunciona mas echo hello > /dev/stdoutfalha.

Uma solução alternativa seria tornar username2um membro do grupo tty, mas isso daria username2permissão para gravar em qualquer tty, o que provavelmente é indesejável.

Outra solução alternativa seria fazer login na username2conta em vez de usar su, de modo que /dev/stdoutaponte para um pseudoterminal recém-alocado pertencente a username2. Isso pode não ser prático.

Outra solução alternativa seria modificar seus scripts para que eles não se refiram /dev/stdoute /dev/stderr; por exemplo, substitua isto:

echo OUT > /dev/stdout
echo ERR > /dev/stderr

por este:

echo OUT
echo ERR 1>&2

Eu vejo isso no meu próprio sistema, Ubuntu 12.04, com o bash 4.2.24 - mesmo que o documento do bash ( info bash) no meu sistema diga isso /dev/stdoute /dev/stderrseja tratado especialmente quando usado em redirecionamentos. Mas mesmo que o bash não trate esses nomes especialmente, eles ainda devem atuar como equivalentes para os fluxos de E / S padrão. (O POSIX não menciona /dev/std{in,out,err}, portanto, pode ser difícil argumentar que isso é um bug.)

Observando versões antigas do bash, a documentação implica que /dev/stdoutet al sejam tratados especialmente se os arquivos existem ou não. O recurso foi introduzido no bash 2.04, e o NEWSarquivo para essa versão diz:

O código de redirecionamento agora lida com vários nomes de arquivos especialmente: / dev / fd / N, / dev / stdin, / dev / stdout e / dev / stderr, estejam eles presentes ou não no sistema de arquivos.

Mas se você examinar o código fonte ( redir.c), verá que esse tratamento especial será ativado apenas se o símbolo HAVE_DEV_STDINestiver definido (isso é determinado quando o bash é criado a partir da fonte).

Até onde eu sei, nenhuma versão lançada do bash tornou /dev/stdoutincondicional o tratamento especial de et al - a menos que alguma distribuição o tenha corrigido.

Portanto, outra solução alternativa (que eu não tentei) seria pegar as fontes do bash , modificar redir.cpara tornar o /dev/*tratamento especial incondicional e usar sua versão reconstruída em vez da versão que acompanha o seu sistema. Isso provavelmente é um exagero, no entanto.

RESUMO:

Seu sistema operacional, como o meu, não está lidando com a propriedade e as permissões de /dev/stdoute /dev/stderrcorretamente. O bash supostamente trata esses nomes especialmente em redirecionamentos, mas na verdade o faz apenas se os arquivos não existirem. Isso não importa se /dev/stdoute /dev/stderrfuncionou corretamente. Esse problema só aparece quando você suusa outra conta ou faz algo semelhante; se você simplesmente fizer login em uma conta, as permissões estão corretas.

Keith Thompson
fonte
A propriedade do TTY deve mudar. É para isso que serve o ConsoleKit pam_ck_connector.so.
Mikel
Na verdade, eu posso estar errado. Terá que cavar mais.
Mikel
Nos meus sistemas, /proc/self/fd/1as permissões estão atualizadas, mas isso não faz sentido, pois é um link simbólico. Também acontece no Fedora, que parece descartar o ConsoleKit.
Mikel
1

Na verdade, a razão disso é que o udev define especificamente as permissões para 0620 em dispositivos tty e su não altera nem a propriedade nem as permissões. Na minha opinião, isso nos deixa em uma situação que torna / dev / std * não portátil.

A solução simples é colocar "mesg y" em / etc / profile (ou qualquer outro perfil de nível superior que você queira usar), pois isso altera as permissões do seu dispositivo tty para 0622. Eu realmente não gosto disso, mas provavelmente é melhor do que alterar as regras do udev.

Wheely
fonte
"msg y" não funciona
Luciano
Espere ... talvez a pesquisa por Bash lide com vários nomes de arquivos, especialmente quando eles são usados ​​em redirecionamentos na página de manual do Bash.
0xC0000022L
0

Como usuário Linux há muito tempo, configurei recentemente um novo sistema Ubuntu 64 bits 12.04 LTS e fiquei confuso com o motivo pelo qual meus scripts bash não estavam funcionando - permissão negada - e, posteriormente, encontrei esse tópico. Eu pensei que o problema poderia ser devido a algo no novo sistema operacional.

No final, descobri que eu tinha estupidamente usado uma ferramenta de interface do usuário para definir permissões no meu /homediretório, e o problema estava relacionado à unidade . Para ter certeza, criei um tempdiretório /opte descobri que meus scripts funcionariam muito bem a partir daí. Depois de corrigir as /homepermissões da unidade, tudo voltou ao normal.

Um pequeno mistério resolvido. suspiro

Ichiro Furusato
fonte
2
Este deve ter sido um erro diferente. Modificar algo em / home não afeta / dev.
#
-1

Esta é uma pergunta antiga, mas acho que ainda é muito relevante, portanto, aqui está uma solução que achei que não é mencionada aqui.

Me deparei com essa pergunta, pois também vi problemas em um comando de execução de conta comutada 'su' como este no bash:

echo test > /dev/stderr

Como tudo o que estou tentando fazer é redirecionar o stdout para o stderr, o seguinte alcança o mesmo e funciona mesmo na conta alternada 'su':

echo test 1>&2
Marcin K
fonte