Note that the order of redirections is significant. For example, the command
ls > dirlist 2>&1
directs both standard output and standard error to the file dirlist,
while the command
ls 2>&1 > dirlist
directs only the standard output to file dirlist, because the
standard error was duplicated from the standard output before the standard
output was redirected to dirlist.
Ta ostatnia część jest dla mnie myląca. W takim przypadku każdy błąd standardowy zostanie wydrukowany na terminalu, a każdy STDOUT przejdzie do pliku dirlist. Tak by się stało, ale nie tak rozumiem instrukcję.
Wygląda na to, że powinien powiedzieć „ponieważ błąd standardowy został zduplikowany ze standardowego wyjścia PO, gdy standardowe wyjście zostało przekierowane do dirlist”. Jeśli STDERR został wysłany do STDOUT zanim STDOUT został skierowany do pliku, to czy plik nie zawiera STDOUT I STDERR?
Czy ktoś może mi to wyjaśnić? Czy to z mojej strony słabe rozumienie czytania? W tym kontekście użycie duplikacji słów wydaje mi się trochę dziwne. Być może to mnie rzuca.
bash
shell
io-redirection
Gregg Leventhal
źródło
źródło
a = 1; b = a; a = 2
spodziewasza == 2 && b == 1
się prawdy. Przekierowanie2>&1
jest podobne dob = a
przypisania - odbywa się według wartości, a nie przez odniesienie.2>&1
nie łączy deskryptora pliku 2 z deskryptorem pliku 1 na całą wieczność - wciąż są 2 odrębnymi deskryptorami plików, które przypadkiem wskazują ten sam plik.Odpowiedzi:
Powielanie jest tutaj naprawdę ważną częścią.
Zobaczmy, dokąd zmierzają deskryptory plików przed przekierowaniem. Zwykle jest to aktualny terminal, np .:
Teraz, jeśli dzwonimy
ls -l
bez przekierowania, komunikaty wyjściowe i komunikaty o błędach trafiają do mojego terminala pod/dev/pts/1
.Jeśli najpierw przekierujemy
STDOUT
do pliku (ls -l > dirlist
), wygląda to tak:Kiedy następnie przekierować
STDERR
do dwóch egzemplarzach zSTDOUT
„s deskryptorze pliku (ls -l > dirlist 2>&1
),STDERR
przechodzi do duplikat/home/bon/dirlist
:Jeśli najpierw przekierowalibyśmy
STDERR
do duplikatuSTDOUT
deskryptora pliku (ls -l 2>&1
):a następnie
STDOUT
do file (ls -l 2>&1 > dirlist
), otrzymalibyśmy to:Tutaj
STDERR
nadal jedzie do terminala.Widzisz, kolejność na stronie podręcznika jest poprawna.
Testowanie przekierowania
Teraz możesz to sprawdzić samodzielnie. Używając
ls -l /proc/$$/fd/
, zobaczysz, gdzieSTDOUT
(z fd 1) iSTDERR
(z fd 2) idą do bieżącego procesu:Utwórzmy mały skrypt powłoki, który pokazuje, gdzie są skierowane deskryptory plików. W ten sposób zawsze otrzymujemy stan podczas połączenia
ls
, w tym wszelkie przekierowania z powłoki wywołującej.(Za pomocą CtrlDwysyłasz plik na końcu pliku, a więc przerywasz
cat
czytanie komendy odSTDIN
.)Teraz wywołaj ten skrypt z różnymi kombinacjami przekierowań:
Widać, że deskryptory plików 1 (dla
STDOUT
) i 2 (dlaSTDERR
) różnią się. Dla zabawy możesz również przekierowaćSTDIN
i zobaczyć wynik:(Pytanie do czytelnika: Gdzie wskazuje deskryptor pliku 255? ;-))
źródło
Nie, instrukcja ma rację.
Jeśli na początku 1 wskazuje na terminal, a 2 także na terminal, to:
ocena przekierowania nastąpi od lewej do prawej.
Więc PIERWSZA oceni
2>&1
, a zatem PIERWSZA skopiuje to, na co1
wskazywał fd (tj. Deskryptor plikuthe terminal
, zwykle / dev / tty) do fd2
.W tym momencie fd
2
wskazuje teraz, gdzie fd1
wskazywał na (the terminal
)A następnie ocenia
1>somewhere
część, a zatem skopiuje deskryptor pliku zsomewhere
fd1
(więc w tym momencie fd1
wskazuje terazsomewhere
, a fd2
nadal wskazujethe terminal
)Tak więc rzeczywiście wypisuje 1 do „gdzieś” i 2 do terminala, ponieważ 2 zostało zduplikowane z 1 PRZED 1 zmieniono.
Drugie zamówienie:
najpierw przekieruje fd
1
dosomewhere
, a następnie skopiuje to samo odwołanie do fd 2, więc na końcu 2 również wskazujesomewhere
. Ale odtąd nie są one „powiązane”. Każdą z nich nadal można przekierować osobno.dawny:
Na końcu tego, fd
1
wskazuje nasomewhere
, a fd2
jest skierowane na/dev/null
Zwykłe nazwy dla fd
1
to STDOUT (standardowe wyjście), a zwykła nazwa dla fd2
to STDERR (błąd standardowy, ponieważ jest powszechnie używany do wyświetlania błędów bez zakłócania STDOUT)źródło
cmd 1>somewhere 2>&1 ; exec 2>/dev/null
: po exec, tylko 2 zostało przekierowane do / dev / null (1 nadal będzie „gdzieś”). Potrzebuję pomocy, aby wymyślić sposób, aby powiedzieć „co wskazuje 1” zamiast „fd 1”, jednak… ponieważ to też jest mylące…Myślę, że mylącą częścią tutaj jest nieporozumienie, że przekierowanie stderr na stdout faktycznie łączy oba strumienie.
Zupełnie rozsądnym pomysłem, ale to, co się dzieje, gdy piszesz,
2>&1
to stderr bierze peekaboo na to, co stdout pisze i pisze w tym samym miejscu. Dlatego jeśli później powiesz stdout, aby poszedł napisać gdzie indziej, nie będzie to miało wpływu na miejsce docelowe stderr, które zostało już przeniesione.Myślę, że sam jest to trochę sprzeczne z intuicją, ale tak to działa. Skonfiguruj najpierw, gdzie chcesz pisać, a następnie powiedz wszystkim „skopiuj mnie”. Nadzieja, która wyjaśnia ...
źródło
POWIELANIE...
jest ważne, ale raczej w tym sensie, że jest źródłem wielu nieporozumień . To jest naprawdę bardzo proste. Ta odpowiedź jest tylko „radykalną” ilustracją.
Przyjęta odpowiedź jest dobra, ale zbyt długa i podkreśla „powielanie”.
Q mądrze kończy się na:
Używam notacji bash i definiuję zmienne „one” i „two” jako uchwyty plików „1” i „2”. Operator przekierowania (wyjściowy)
>
jest przypisaniem=
.&
i$
oznacza „wartość” z.Przykłady man bash (z dodaną domyślną „1”)
stają się:
i
I nawet to nie jest dla mnie automatyczne i, jak sądzę, niektóre inne. Pierwszy wiersz zostawia cię
$one
i$two
oba zawierają „dirlist”. Oczywiście.Druga linia zaczyna się od niepotrzebnego przypisania. Oba zaczynają się od definicji z „TTY” (nieco symbolicznym) jako ich kierunkiem ; to przypisanie nie zmienia żadnej wartości, a przy zmiennych jak w uchwytach plików nic nie jest magicznie powiązane. Na zmienne
two
nie mają wpływu następujące elementyone=dirlist
. Oczywiście nie.Sombody tutaj (6 lat temu) zasugerował „wskaż” zamiast „kopiuj” lub „duplikuj”, a potem zdał sobie sprawę: to też byłoby mylące.
To semantyczne powielanie lub wskaźnik nie jest nawet potrzebne. Może to ampersand wymaga więcej uwagi. „Wartość” operatora / tokena / cokolwiek.
Jeśli - i tylko jeśli - szukasz sposobu na uzyskanie zaskakującego numeru zadania na konsoli , wtedy komunikat „gotowe” plus jako bonus plik o nazwie „2”, to:
Odczytuje naturalnie jako „ kopiuj” / „duplikuj” 1 do 2, a następnie oba razem do wartości null . Ale pomysł jest zły, a także składnia. (ale nie ma błędu składniowego, jest poprawny)
Właściwy sposób na jego zaplanowanie to przekierowanie dowolnego z dwóch na zero, a następnie przekierowanie INNEGO do SAMEGO miejsca:
(początkowe „1” można pominąć)
(OK, acc. A nie jest zbyt długi, ale to zbyt duża lista - lub: bardzo dobra wizualizacja, niezbyt dobre wyjaśnienie)
źródło