bash: / dev / stderr: в доступе отказано


19

После обновления до новой версии выпуска мои bashскрипты начинают выдавать ошибки:

bash: /dev/stderr: Permission denied

в предыдущих версиях Bash будет внутренне признать эти имена файлов (именно поэтому этот вопрос не является дубликатом этого одного ) и сделать правильную вещь (тм) , однако, это перестало работать в настоящее время. Что я могу сделать, чтобы снова успешно запускать мои сценарии?

Я попытался добавить пользователя, запускающего сценарий, в группу tty, но это не имеет значения (даже после выхода из системы и повторного входа).

Я могу воспроизвести это в командной строке без проблем:

$ 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

В более старой системе (Ubuntu 10.04):

$ echo $BASH_VERSION
4.1.5(1)-release

1
Что является выходом ls -l /dev/stdout /dev/stderrи ls -lL /dev/stdout /dev/stderr?
Кит Томпсон

@Keith: см. Мой отредактированный вопрос. Означает ли это, что Bash полностью отказался от внутренней обработки этого? В старых системах эти символические ссылки не существовали, и все же код работал без проблем. Обратите внимание, что это работает sudo su username2 -
подражает

Какую версию Bash вы используете? echo $BASH_VERSION
Джиппи

1
Каковы старые и новые версии (до и после вашей ОС и Bash?
Кит Томпсон

Ответы:


41

Я не думаю, что это полностью проблема Bash.

В комментарии вы сказали, что видели эту ошибку после выполнения

sudo su username2

когда залогинен как username. Это suвызывает проблему.

/dev/stdoutявляется символической ссылкой на /proc/self/fd/1, которая является символической ссылкой, например, на /dev/pts/1. /dev/pts/1, который является псевдотерминалом, принадлежит и доступен для записи username; это право собственности было предоставлено при usernameвходе в систему. Когда вы sudo su username2, право собственности /dev/pts/1не меняется и username2не имеет разрешения на запись.

Я бы сказал, что это ошибка. по сути, /dev/stdout должен быть псевдоним для стандартного потока вывода, но здесь мы видим ситуацию, когда echo helloработает, но echo hello > /dev/stdoutне работает .

Одним из обходных путей может стать username2член группы tty, но это даст username2разрешение писать любому tty, что, вероятно, нежелательно.

Другим обходным решением будет вход в username2учетную запись, а не использование su, чтобы указывать на /dev/stdoutвновь выделенный псевдотерминал, принадлежащий username2. Это не может быть практичным.

Другой обходной путь - изменить ваши сценарии, чтобы они не ссылались на /dev/stdoutи /dev/stderr; например, замените это:

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

этим:

echo OUT
echo ERR 1>&2

Я вижу это в моей собственной системе, Ubuntu 12.04, с bash 4.2.24, хотя bash document ( info bash) в моей системе говорит об этом /dev/stdoutи /dev/stderrобрабатывается специально, когда используется при перенаправлениях. Но даже если bash не обрабатывает эти имена специально, они все равно должны действовать как эквиваленты для стандартных потоков ввода-вывода. (POSIX не упоминает /dev/std{in,out,err}, поэтому может быть трудно утверждать, что это ошибка.)

Глядя на старые версии bash, документация подразумевает, что /dev/stdoutи др. Обрабатываются специально, независимо от того, существуют файлы или нет. Эта функция была представлена ​​в bash 2.04, и NEWSфайл для этой версии гласит:

Код перенаправления теперь обрабатывает несколько имен файлов, в частности: / dev / fd / N, / dev / stdin, / dev / stdout и / dev / stderr, независимо от того, присутствуют они в файловой системе или нет.

Но если вы изучите исходный код ( redir.c), вы увидите, что эта специальная обработка включена, только если символ HAVE_DEV_STDINопределен (это определяется, когда bash создается из исходного кода).

Насколько я могу судить, ни одна выпущенная версия bash не сделала специальную обработку /dev/stdoutet al безусловной - если только какой-то дистрибутив не исправил ее.

Таким образом, другой обходной путь (который я не пробовал) заключается в получении исходных текстов bash , изменении, redir.cчтобы сделать специальную /dev/*обработку безусловной, и использовании вашей перестроенной версии, а не той, которая пришла с вашей системой. Это, вероятно, излишне, хотя.

РЕЗЮМЕ :

Ваша ОС, как у меня, не обрабатывают права собственности и право доступа /dev/stdoutи /dev/stderrправильно. Предположительно, bash обрабатывает эти имена специально в перенаправлениях, но на самом деле это происходит только в том случае, если файлы не существуют. Это не имеет значения, если /dev/stdoutи /dev/stderrработает правильно. Эта проблема появляется только при переходе suна другой аккаунт или выполнении чего-либо подобного; если вы просто войдете в учетную запись, разрешения будут правильными.


Право собственности на TTY должно измениться. Это то, что ConsoleKit (он же pam_ck_connector.so) для.
Микель

На самом деле, я могу ошибаться. Копать придется больше.
Микель

В моих системах /proc/self/fd/1обновляются разрешения, но это бессмысленно, так как это символическая ссылка. Бывает и на Fedora, что, похоже, исключает ConsoleKit.
Микель

1

Фактически причина этого заключается в том, что udev специально устанавливает разрешения на 0620 для tty-устройств, и su не меняет ни владельца, ни разрешения, ни это. На мой взгляд, это оставляет нас в ситуации, которая делает / dev / std * непереносимой.

Простое решение - поместить «mesg y» в / etc / profile (или любой другой профиль верхнего уровня, который вы хотите использовать), так как это меняет права доступа вашего устройства tty на 0622. Мне это не очень нравится, но, вероятно, лучше чем изменение правил Udev.


"msg y" не работает
Лучано

Подождите ... может быть, поиск Bash обрабатывает несколько имен файлов, особенно когда они используются в перенаправлениях на странице руководства Bash.
0xC0000022L

0

Как давний пользователь Linux, я недавно установил новую систему Ubuntu 64 bit 12.04 LTS и был озадачен тем, почему мои bash-скрипты не работали - в доступе отказано - и впоследствии я нашел этот поток. Я думал, что проблема может быть из-за чего-то в новой ОС.

В конце концов получается, что я тупо использовал инструмент пользовательского интерфейса для установки разрешений для своего /homeкаталога, и проблема была связана с диском . Чтобы быть уверенным, я создал tempкаталог /optи обнаружил, что мои скрипты будут работать очень хорошо оттуда. Как только я установил /homeправа доступа к диску, все вернулось к норме.

Одна маленькая загадка раскрыта. вздох


2
Это должно быть другая ошибка. Изменение чего-либо в / home не влияет на / dev.
ot--

-1

Это старый вопрос, но я думаю, что он все еще актуален, поэтому я нашел решение, которое здесь не упоминается.

Я столкнулся с этим вопросом, так как я также видел проблемы в коммутируемой учетной записи su, выполняющей такую ​​команду в bash:

echo test > /dev/stderr

Так как все, что я пытаюсь сделать, это перенаправить stdout в stderr, следующее достигает того же самого, и это работает даже в переключенной учетной записи 'su':

echo test 1>&2
Используя наш сайт, вы подтверждаете, что прочитали и поняли нашу Политику в отношении файлов cookie и Политику конфиденциальности.
Licensed under cc by-sa 3.0 with attribution required.