bash: / dev / stderr: Odmowa dostępu

19

Po aktualizacji do nowej wersji moje bashskrypty zaczynają wyrzucać błędy:

bash: /dev/stderr: Permission denied

w poprzednich wersjach Bash wewnętrznie rozpoznawał te nazwy plików (dlatego to pytanie nie jest duplikatem tego ) i robił właściwą rzecz (tm) , jednak to przestało działać. Co mogę zrobić, aby móc ponownie uruchomić moje skrypty?

Próbowałem dodać użytkownika uruchamiającego skrypt do grupy tty, ale to nie robi różnicy (nawet po wylogowaniu i ponownym zalogowaniu).

Mogę bez problemu odtworzyć to w wierszu poleceń:

$ 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

W starszym systemie (Ubuntu 10.04):

$ echo $BASH_VERSION
4.1.5(1)-release
0xC0000022L
źródło
1
Jaka jest wydajność ls -l /dev/stdout /dev/stderri ls -lL /dev/stdout /dev/stderr?
Keith Thompson
@ Keith: zobacz moje edytowane pytanie. Czy to oznacza, że ​​Bash całkowicie zrezygnował z wewnętrznej obsługi tego? W starszych systemach te dowiązania symboliczne nie istniały, a mimo to kod działał bez problemu. Uwaga: działa to podszywanie się pod sudo su username2 -...
0xC0000022L
Jakiej wersji bash używasz? echo $BASH_VERSION
jippie
1
Jakie są stare i nowe wersje (przed i po twoim systemie operacyjnym i bash?
Keith Thompson

Odpowiedzi:

41

Nie sądzę, że jest to całkowicie problem bash.

W komentarzu powiedziałeś, że zobaczyłeś ten błąd po zrobieniu

sudo su username2

po zalogowaniu jako username. To właśnie supowoduje problem.

/dev/stdoutjest dowiązaniem symbolicznym do /proc/self/fd/1, które jest na przykład dowiązaniem symbolicznym /dev/pts/1. /dev/pts/1, który jest pseudoterminalem, jest własnością i jest do zapisu przez username; ta własność została przyznana po usernamezalogowaniu. Kiedy Ty sudo su username2, własność /dev/pts/1nie zmienia się i username2nie masz uprawnień do zapisu.

Twierdziłbym, że to błąd. /dev/stdout powinien być w rzeczywistości aliasem dla standardowego strumienia wyjściowego, ale tutaj widzimy sytuację, w której echo hellodziała, ale echo hello > /dev/stdoutkończy się niepowodzeniem.

Jednym z obejść byłoby utworzenie username2członka grupy tty, ale dałoby to username2pozwolenie na pisanie do dowolnego tty, co prawdopodobnie jest niepożądane.

Innym obejściem byłoby zalogowanie się na username2konto zamiast korzystania z niego su, co /dev/stdoutwskazuje na nowo przydzielony pseudoterminal, którego właścicielem jest username2. To może nie być praktyczne.

Innym obejściem byłoby zmodyfikowanie skryptów, aby nie odnosiły się do /dev/stdouti /dev/stderr; na przykład zamień to:

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

przez to:

echo OUT
echo ERR 1>&2

Widzę to w moim systemie Ubuntu 12.04 z wersją bash 4.2.24 - nawet jeśli bash document ( info bash) w moim systemie to mówi /dev/stdouti /dev/stderrsą traktowane specjalnie, gdy są używane w przekierowaniach. Ale nawet jeśli bash nie traktuje tych nazw specjalnie, powinny one nadal działać jako odpowiedniki standardowych strumieni we / wy. (POSIX nie wspomina /dev/std{in,out,err}, więc może być trudno argumentować, że jest to błąd).

Patrząc na stare wersje bash, dokumentacja sugeruje, że /dev/stdoutet al są traktowani specjalnie niezależnie od tego, czy pliki istnieją, czy nie. Funkcja została wprowadzona w bash 2.04, a NEWSplik dla tej wersji mówi:

Kod przekierowania obsługuje teraz kilka nazw plików specjalnie: / dev / fd / N, / dev / stdin, / dev / stdout i / dev / stderr, niezależnie od tego, czy są one obecne w systemie plików.

Ale jeśli przyjrzysz się kodowi źródłowemu ( redir.c), zobaczysz, że ta specjalna obsługa jest włączona tylko wtedy, gdy HAVE_DEV_STDINzdefiniowany jest symbol (jest to określane, gdy bash jest budowany ze źródła).

O ile mi wiadomo, żadna wydana wersja bash nie spowodowała, że ​​specjalne traktowanie /dev/stdoutet al jest bezwarunkowe - chyba że jakaś dystrybucja go załatała.

Tak więc innym obejściem (którego jeszcze nie próbowałem) byłoby przechwycenie źródeł bash , zmodyfikowanie redir.ctak, aby specjalna /dev/*obsługa była bezwarunkowa, i użycie zrekonstruowanej wersji zamiast tej dostarczonej z systemem. Jest to jednak prawdopodobnie przesada.

STRESZCZENIE :

System operacyjny, jak moja, nie jest obsługa własności i uprawnień /dev/stdoutoraz /dev/stderrpoprawnie. bash rzekomo traktuje te nazwy specjalnie w przekierowaniach, ale w rzeczywistości robi to tylko wtedy, gdy pliki nie istnieją. To nie ma znaczenia, czy /dev/stdouti /dev/stderrdziałało poprawnie. Ten problem pojawia się tylko wtedy, gdy przechodzisz suna inne konto lub robisz coś podobnego; jeśli po prostu zalogujesz się na konto, uprawnienia są prawidłowe.

Keith Thompson
źródło
Własność TTY powinna ulec zmianie. Po to jest ConsoleKit (aka pam_ck_connector.so).
Mikel
Właściwie mogę się mylić. Będę musiał kopać więcej.
Mikel
W moich systemach /proc/self/fd/1aktualizuje swoje uprawnienia, ale to nie ma sensu, ponieważ jest to dowiązanie symboliczne. Zdarza się również w Fedorze, co wydaje się wykluczać ConsoleKit.
Mikel
1

W rzeczywistości powodem tego jest to, że udev specjalnie ustawia uprawnienia na 0620 na urządzeniach tty, a su nie zmienia ani własności, ani uprawnień, ani też nie powinno. Moim zdaniem pozostawia nas to w sytuacji, w której / dev / std * jest nieprzenośny.

Prostym rozwiązaniem jest umieszczenie „mesg y” w / etc / profile (lub dowolnym innym profilu najwyższego poziomu, którego chcesz użyć), ponieważ zmienia to uprawnienia twojego urządzenia tty na 0622. Nie podoba mi się to, ale prawdopodobnie jest lepiej niż zmiana reguł udev.

Wheely
źródło
„msg y” nie działa
Luciano
Poczekaj ... może wyszukiwanie Bash obsługuje kilka nazw plików, zwłaszcza gdy są one używane w przekierowaniach na stronie podręcznika Bash.
0xC0000022L
0

Jako długoletni użytkownik Linuksa niedawno zainstalowałem nowy 64-bitowy system LTS Ubuntu 12.04 i byłem zaskoczony, dlaczego moje skrypty bash nie działają - odmowa dostępu - i później znalazłem ten wątek. Myślałem, że problem może wynikać z czegoś w nowym systemie operacyjnym.

W końcu okazuje się, że głupio użyłem narzędzia interfejsu użytkownika do ustawienia uprawnień w moim /homekatalogu, a problem był związany z napędem . Dla pewności utworzyłem tempkatalog /opti stwierdziłem, że moje skrypty będą działać dobrze. Po poprawieniu /homeuprawnień do napędu wszystko wróciło do normy.

Jedna mała zagadka rozwiązana. westchnienie

Ichiro Furusato
źródło
2
To musiał być inny błąd. Modyfikacja czegoś w / home nie wpływa na / dev.
ott--
-1

To stare pytanie, ale myślę, że nadal jest bardzo aktualne, dlatego znalazłem rozwiązanie, o którym tu nie wspomniano.

Natknąłem się na to pytanie, ponieważ widziałem również problemy z komendą przełączania kont „su” wykonującą takie polecenie w bash:

echo test > /dev/stderr

Ponieważ wszystko, co próbuję zrobić, to przekierować stdout do stderr, następujące osiąga to samo i działa nawet na przełączonym koncie „su”:

echo test 1>&2
Marcin K
źródło