Jaka jest różnica między `>> / dev / stderr` (z białą spacją) a`> & 2`?

11

W bash

Mam problem z ustaleniem, czego powinienem użyć?

wszystkie moje skrypty używają „>> / dev / stderr”

w wierszu polecenia, jeśli spróbuję:
echo test >>/dev/stderrdziała
echo test >> /dev/stderrdziała
echo test >/dev/stderrdziała
echo test > /dev/stderrdziała

echo test >>&2FAILS!
echo test >> &2FAILS!
echo test >&2działa
echo test > &2niepowodzenie!

Jestem gotów zmienić wszystkie moje skrypty na >&2.

Wydaje się, że ma również duży wpływ na ssh (po su SomeUser), gdzie w >>/dev/stderrogóle nie będzie działać (odmowa dostępu), tylko >&2będzie działać.

Moc Wodnika
źródło
czy możesz pokazać przykład błędu ssh? Nie mogę tego odtworzyć.
Jeff Schaller
@JeffSchaller masz rację, dopiero po sutym, jak problem się zdarzy, zaktualizowałem pytanie
Aquarius Power
@AquariusPower, ... tak przy okazji: aby wyjaśnić tę rozbieżność: z su -c 'some command', to polecenie jest uruchamiane przez /bin/sh, a nie bash, więc /dev/stderrnie jest gwarantowane zachowanie specyficzne dla bash (takie jak symulowanie w celu przekierowania, gdy nie jest dostępne).
Charles Duffy,

Odpowiedzi:

22

>& nto składnia powłoki służąca do bezpośredniego kopiowania deskryptora pliku . Deskryptor pliku 2 to stderr; tak to działa. Możesz także powielać inne deskryptory plików, nie tylko stderr. Nie możesz tutaj użyć trybu dołączania, ponieważ duplikowanie deskryptora pliku nigdy nie jest obcinane (nawet jeśli twój stderr jest plikiem) i >&jest jednym tokenem, dlatego nie możesz w nim wstawić spacji - ale >& 2działa.

>> namejest inną dozwoloną składnią, gdzie namejest nazwa pliku (a token to >>). W tym przypadku używasz nazwy pliku /dev/stderr, co przy obsłudze specyficznej dla systemu operacyjnego (w Linuksie jest to dowiązanie symboliczne /proc/self/fd/2) oznacza również standardowy błąd. Tryb dołączania i obcinania kończy się, robiąc to samo, gdy stderr jest terminalem, ponieważ nie można go obciąć. Jeśli Twój błąd standardowy to plik, zostanie on jednak obcięty:

anthony@Zia:~$ bash -c 'echo hi >/dev/stderr; echo bye >/dev/stderr' 2>/tmp/foo
anthony@Zia:~$ cat /tmp/foo
bye

Jeśli widzisz błąd z /dev/stderrover ssh, możliwe, że administrator serwera zastosował pewne środki bezpieczeństwa uniemożliwiające działanie tego dowiązania symbolicznego. (Np. Nie możesz uzyskać dostępu /proclub /dev). O ile spodziewałbym się, że spowoduje to wszelkiego rodzaju dziwne uszkodzenia, użycie składni deskryptora pliku jest całkowicie rozsądnym (i prawdopodobnie nieco bardziej wydajnym) podejściem. Osobiście wolę to.

derobert
źródło
Miałem duży problem z odtworzeniem tego obciętego problemu, który miałem wcześniej (w przeciwnym razie dodałbym to do pytania hehe), powodu, dla którego zmieniłem wszystko, aby użyć >>, dzięki za wskazanie tego! Poza tym przegapiłem krok su SomeUserpo podłączeniu przez ssh.
Aquarius Power,
to bash -c 'echo hi >&2; echo bye >&2' 2>/tmp/foo;cat /tmp/foonie zostanie obcięte! (nawet z 2>&1 |tee /tmp/foo) tym, co jest idealne do logowania, i będzie działać idealnie po zmianie tego wszystkiego na >&2. Sądzę więc, że tylko bezpośrednie użycie pliku /dev/stderrpozwala na obcinanie, a nie duplikat deskryptora, fajne dzięki!
Aquarius Power,
@AquariusPower poprawny, zduplikowany deskryptor pliku nigdy nie jest obcinany. To jest pierwszy akapit, może muszę to jakoś podkreślić?
derobert,
niepotrzebne, czasem jestem powolny ehehe
Wodnik Moc
3
Ta odpowiedź może zostać ulepszona. > & jest jednym żetonem, a nie dwoma, i jest w tym zamieszanie OP.
Jozuego
8

Przypadki niepowodzenia występują, ponieważ składnia bash do użycia &w przekierowaniach określa pojedynczą >i wymaga, aby istniała bezpośrednio przy &znaku:

[n]> i słowo

Jeff Schaller
źródło
2

Służy '>'do przekierowywania (obcina, jeśli istnieje) lub '>>'(dołącza, jeśli istnieje).

Służy '>&'do powielania strumienia, na przykład jeśli chcesz standardowego wyjścia ORAZ standardowego błędu w tym samym pliku, przekierowujesz do pliku, '> output.log'a także błąd z'2>&'

myjob.sh > output.log 2>&
Jose Manuel Gomez Alvarez
źródło