bash: / dev / stderr: Дозвіл відхилено


19

Після оновлення до нової версії мої bashсценарії починають виплювати помилки:

bash: /dev/stderr: Permission denied

у попередніх версіях Bash внутрішньо розпізнавав ці імена файлів (саме тому це питання не є дублікатом цього ) і зробить правильно (tm) , однак це зараз перестало працювати. Що я можу зробити, щоб знову запустити сценарії успішно?

Я намагався додати користувача до сценарію до групи 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: див. Моє відредаговане запитання. Чи означає це, що Баш повністю відмовився від внутрішнього вирішення цього питання? У старих системах цих посилань не існувало, але код працював без проблем. Зауважте, це працює під назвою через sudo su username2 -...
0xC0000022L

Яку версію bash ви використовуєте? echo $BASH_VERSION
джиппі

1
Які старі та нові версії (до і після вашої ОС та баш?
Кіт Томпсон

Відповіді:


41

Я не думаю, що це суто питання.

У коментарі ви сказали, що побачили цю помилку після вчинення

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дозвіл писати на будь-які тти, що, мабуть, небажано.

Іншим вирішенням проблеми буде вхід до 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 документ ( 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" не працює
Luciano

Зачекайте ... можливо, пошук Bash обробляє декілька імен файлів спеціально, коли вони використовуються для переадресації на сторінці чоловіка Bash.
0xC0000022L

0

Нещодавно користувач Linux я нещодавно створив нову систему Ubuntu 64 біт 12.04 LTS і містифікував, чому мої bash-скрипти не працюють - дозвіл відхилено - і згодом я знайшов цю тему. Я думав, що проблема може бути пов’язана з чимось новою ОС.

Зрештою виявляється, що я тупо використовував інструмент користувальницького інтерфейсу для встановлення дозволів у моєму /homeкаталозі, і проблема була пов'язана з диском . Напевно, я створив tempкаталог /optі знайшов, що мої сценарії звідти будуть працювати нормально. Після того, як я виправила /homeдозволи на диск, все повернулося до норми.

Одна маленька таємниця вирішена. зітхати


2
Це, мабуть, була різною помилкою. Змінення чогось у / вдома не впливає на / dev.
ott--

-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.