Я не думаю, что это полностью проблема 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на другой аккаунт или выполнении чего-либо подобного; если вы просто войдете в учетную запись, разрешения будут правильными.
ls -l /dev/stdout /dev/stderrиls -lL /dev/stdout /dev/stderr?