bash: / dev / stderr: autorisation refusée

19

Après la mise à niveau vers une nouvelle version, mes bashscripts commencent à cracher des erreurs:

bash: /dev/stderr: Permission denied

dans les versions précédentes, Bash reconnaîtrait en interne ces noms de fichiers (c'est pourquoi cette question n'est pas un doublon de celui-ci ) et ferait ce qu'il fallait (tm) , cependant, cela n'a plus fonctionné maintenant. Que puis-je faire pour pouvoir réexécuter mes scripts avec succès?

J'ai essayé d'ajouter l'utilisateur exécutant le script au groupe tty, mais cela ne fait aucune différence (même après la déconnexion et la reconnexion).

Je peux reproduire cela sur la ligne de commande sans problème:

$ 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

Sur un système plus ancien (Ubuntu 10.04):

$ echo $BASH_VERSION
4.1.5(1)-release
0xC0000022L
la source
1
Quelle est la sortie de ls -l /dev/stdout /dev/stderret ls -lL /dev/stdout /dev/stderr?
Keith Thompson
@Keith: voir ma question modifiée. Est-ce à dire que Bash a complètement abandonné la gestion interne de cela? Sur les anciens systèmes, ces liens symboliques n'existaient pas et pourtant le code fonctionnait sans problème. Remarque, cela fonctionne sous l'identité de sudo su username2 -...
0xC0000022L
Quelle version bash utilisez-vous? echo $BASH_VERSION
jippie
1
Quelles sont les anciennes et nouvelles versions (avant et après votre OS et bash?
Keith Thompson

Réponses:

41

Je ne pense pas que ce soit entièrement un problème bash.

Dans un commentaire, vous avez dit avoir vu cette erreur après avoir fait

sudo su username2

une fois connecté en tant que username. C'est ce suqui déclenche le problème.

/dev/stdoutest un lien symbolique /proc/self/fd/1, qui est un lien symbolique, par exemple, /dev/pts/1. /dev/pts/1, qui est un pseudoterminal, appartient et est accessible en écriture par username; cette propriété a été accordée lors de la usernameconnexion. Lorsque vous sudo su username2, la propriété de /dev/pts/1ne change pas et username2n'a pas la permission d'écriture.

Je dirais que c'est un bug. /dev/stdout devrait être, en effet, un alias pour le flux de sortie standard, mais ici nous voyons une situation où echo hellofonctionne mais echo hello > /dev/stdoutéchoue.

Une solution de contournement serait de faire username2un membre du groupe tty, mais cela donnerait la username2permission d'écrire à n'importe quel terminal, ce qui n'est probablement pas souhaitable.

Une autre solution de contournement consisterait à se connecter au username2compte plutôt qu'à utiliser su, de sorte que /dev/stdoutpointe vers un pseudoterminal nouvellement alloué appartenant à username2. Cela pourrait ne pas être pratique.

Une autre solution consiste à modifier vos scripts afin qu'ils ne se réfèrent pas à /dev/stdoutet /dev/stderr; par exemple, remplacez ceci:

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

par ça:

echo OUT
echo ERR 1>&2

Je vois cela sur mon propre système, Ubuntu 12.04, avec bash 4.2.24 - même si le document bash ( info bash) sur mon système le dit /dev/stdoutet /dev/stderrest traité spécialement lorsqu'il est utilisé dans les redirections. Mais même si bash ne traite pas ces noms spécialement, ils devraient quand même agir comme des équivalents pour les flux d'E / S standard. (POSIX ne le mentionne pas /dev/std{in,out,err}, il peut donc être difficile de prétendre qu'il s'agit d'un bogue.)

En regardant les anciennes versions de bash, la documentation implique que /dev/stdoutet al sont traités spécialement, que les fichiers existent ou non. La fonctionnalité a été introduite dans bash 2.04, et le NEWSfichier de cette version indique:

Le code de redirection gère désormais plusieurs noms de fichiers spécialement: / dev / fd / N, / dev / stdin, / dev / stdout et / dev / stderr, qu'ils soient ou non présents dans le système de fichiers.

Mais si vous examinez le code source ( redir.c), vous verrez que cette gestion spéciale n'est activée que si le symbole HAVE_DEV_STDINest défini (ceci est déterminé lorsque bash est construit à partir de la source).

Pour autant que je sache, aucune version publiée de bash n'a rendu /dev/stdoutinconditionnelle la gestion spéciale de et al - à moins qu'une distribution ne l'ait corrigé.

Une autre solution (que je n'ai pas essayée) serait donc de récupérer les sources bash , de les modifier redir.cpour rendre /dev/*inconditionnelle la gestion spéciale et d'utiliser votre version reconstruite plutôt que celle fournie avec votre système. C'est probablement exagéré, cependant.

SOMMAIRE :

Votre système d' exploitation, comme le mien, gère pas la propriété et les autorisations de /dev/stdoutet /dev/stderrcorrectement. bash est censé traiter ces noms spécialement dans les redirections, mais en fait il ne le fait que si les fichiers n'existent pas. Ce ne serait pas grave si /dev/stdoutet /dev/stderrfonctionnait correctement. Ce problème sun'apparaît que lorsque vous accédez à un autre compte ou faites quelque chose de similaire; si vous vous connectez simplement à un compte, les autorisations sont correctes.

Keith Thompson
la source
La propriété du téléscripteur devrait changer. C'est à cela que sert ConsoleKit (alias pam_ck_connector.so).
Mikel
En fait, je peux me tromper. Faudra creuser plus.
Mikel
Sur mes systèmes, /proc/self/fd/1ses autorisations sont mises à jour, mais cela est inutile, car il s'agit d'un lien symbolique. Cela se produit également sur Fedora, ce qui semble exclure ConsoleKit.
Mikel
1

En fait, la raison en est que udev définit spécifiquement les autorisations sur 0620 sur les périphériques tty et que su ne change ni la propriété ni les autorisations. À mon avis, cela nous place dans une situation qui rend / dev / std * non portable.

La solution simple est de mettre "mesg y" dans / etc / profile (ou quel que soit le profil de premier niveau que vous souhaitez utiliser) car cela change les autorisations de votre périphérique tty en 0622. Je n'aime pas vraiment ça mais c'est probablement mieux que de changer les règles udev.

Wheely
la source
"msg y" ne fonctionne pas
Luciano
Attendez ... peut-être que la recherche de Bash gère plusieurs noms de fichiers spécialement lorsqu'ils sont utilisés dans des redirections dans la page de manuel de Bash.
0xC0000022L
0

En tant qu'utilisateur Linux de longue date, j'ai récemment mis en place un nouveau système Ubuntu 64 bits 12.04 LTS et je ne savais pas pourquoi mes scripts bash ne fonctionnaient pas - autorisation refusée - et j'ai par la suite trouvé ce fil. J'ai pensé que le problème pourrait être dû à quelque chose dans le nouveau système d'exploitation.

En fin de compte, il s'est avéré que j'avais stupidement utilisé un outil d'interface utilisateur pour définir des autorisations sur mon /homerépertoire, et le problème était lié au lecteur . Pour être sûr, j'ai créé un temprépertoire /optet trouvé que mes scripts fonctionneraient très bien à partir de là. Une fois que j'ai corrigé les /homeautorisations de lecteur, tout était redevenu normal.

Un petit mystère résolu. soupir

Ichiro Furusato
la source
2
Ce devait être une erreur différente. La modification de quelque chose dans / home n'affecte pas / dev.
ott--
-1

C'est une vieille question, mais je pense toujours très pertinente, donc voici une solution que j'ai trouvée qui n'est pas mentionnée ici.

Je suis tombé sur cette question car j'ai également vu des problèmes dans une commande d'exécution de compte commuté «su» comme celle-ci dans bash:

echo test > /dev/stderr

Étant donné que tout ce que j'essaie de faire est de rediriger stdout vers stderr, ce qui suit obtient le même résultat, et cela fonctionne même dans le compte commuté «su»:

echo test 1>&2
Marcin K
la source