Jak mogę pamiętać, jak korzystać z przekierowania?

40

wiem co

  program > /dev/null 2>&1 

robi. Przekierowuje wyjście do /dev/nulli 2>&1oznacza przekierowanie wyjścia błędu w tym samym miejscu, w którym wysyłane jest wyjście.

Mój problem polega na tym, że zawsze muszę go wyszukiwać w Google, ponieważ nigdy tego nie pamiętam.

Więc staram &2>1, 1>2&, 1>&2... Staram każdą kombinację aż google ...

Jak łatwo jest to zapamiętać?

Luc M.
źródło
Mam ten sam problem, więc robię to „na długo” - przekierowuję oba program 1> /dev/null 2>/dev/null. Czasami jednak trzeba wymieszać stdouti stderrrazem, aby zobaczyć, co się naprawdę dzieje - na przykład przekierowanie wyjścia do złożonego procesu kompilacji do pliku. W takim razie
skończę googlować

Odpowiedzi:

20

Wyjście jest lepsze niż błąd, więc jest pierwsze (1 vs 2).

>jest skrótem od „idzie do”. Po lewej stronie jest to, co chcę wysłać, a po prawej to miejsce, w którym chcę to wysłać. Ponieważ „gdzie” jest (prawie) zawsze plikiem, coś w rodzaju

program > /dev/null 2>1

przekieruje do pliku o nazwie 1. Zatem znak ampersand (&)modyfikuje plik do deskryptora pliku.

Niestety nie spotkałem się ani nie opracowałem własnego mnemonika, ale kiedy uczyłem się * nix, znalazłem ten logiczny sposób, aby dobrze działać. Po kilku przejściach staje się drugą naturą.

gvkv
źródło
Twoje pierwsze zdanie nie ma dla mnie sensu. stdoutjest deskryptorem pliku 1, stderrma 2. Zatem „błąd” występuje przed „wyjściem”.
Warren Young,
To zdanie jest mnemonikiem do zapamiętania, który deskryptor pliku stdouti do którego stderrodnosi się.
gvkv,
Okej, ale nadal wydaje się to mylące, ponieważ pierwotne pytanie dotyczy próby zapamiętania kolejności znaków w inkantacji „2> i 1”.
Warren Young,
9

Jedną sztuczką jest, aby pamiętać, że 1 = standardowe wyjście, 2 = standardowy błąd. Więc:

2>&1= standardowy strumień błędów przechodzi do standardowego strumienia wyjściowego.
1>&2= vice versa.

Jeśli kiedykolwiek programowałeś w języku podobnym do C, łatwo jest zapamiętać ampersand ( &). Wybieram myślenie o nim jako o „adresie” istniejącego deskryptora pliku, abyś nie zmienił samego pliku ani nie utworzył nowego.

Thronic
źródło
7

Uznanie &za węzeł może pomóc: pomyśl o tym, co chcesz zrobić, biorąc wynik 2, więc 2>i wiążąc go z 1, więc2>&1

Bertrand Lorentz
źródło
2
Właśnie zapamiętałem wyrażenie „dwa wyjścia i jeden”. Niezależnie od tego, czy Twój mnemonik jest frazą czy węzłem, posiadanie takiego naprawdę pomoże.
Tim Kennedy,
5

W rzeczywistości zależy to od używanej powłoki. Bash jest zwykle bardzo wybaczający i możesz po prostu zrobić:

program &> file
Kevin Cantu
źródło
5

Rozważmy te trzy opcje:

program  2>1
program  2>1& 
program  2>&1

Pierwszy wysyła stderr do nazw plików „1”: w końcu bash oczekuje przekierowania do pliku.

Drugi również przekierowuje do tego samego pliku, ale działa programw tle: to właśnie &powinien oznaczać końcowy .

To pozostawia trzecią możliwość jako jedyną, która ma sens we wszechświecie bash do przekierowywania do uchwytu pliku.

Jak zapamiętać, który z nich jest 0, 1, 2? Pomyśl o uruchomieniu komputera z konsoli. Najpierw musisz coś wpisać (0 = stdin). Następnie zobaczysz wynik (1 = standardowe wyjście). Wreszcie, tylko jeśli coś pójdzie nie tak, zobaczysz stderr (2).

John1024
źródło
1

Narysuj to na tapecie.

Poważnie, o tym i innych podstawowych rzeczach zapomniałem, dlatego dodałem szybkie menu wskazówek do opracowanej przeze mnie aplikacji, z której korzystam codziennie. Możesz spróbować i użyć czegoś takiego jak gnote, aby zachować notatkę.

Ubersoldat
źródło
1

Jeśli chodzi o powłokę bash, najlepszym sposobem na zapamiętanie jest zrozumienie tego, co się dzieje.
Jeśli wszystko, co chcesz zrobić, to pamiętać, jak poprawnie wykonać polecenie, możesz spróbować

program > /results 2> /results

To miłe i oczywiste, co się dzieje i łatwe do zapamiętania. to znaczy

  • 1 STDOUT zamierza /results
  • 2STDERR również idzie bezpośrednio do/results

problem polega na tym, że to nie działa tak, jak można się spodziewać. rozważ następujące:

plik: /tmp/poem.txt

the quick brown fox jumped over the lazy dog

i uruchom polecenie

grep "brown" /tmp/poem.txt NOT_A_FILE > /tmp/results 2> /tmp/results

następnie

$ cat /tmp/results
grep: NOT_A_FILE: No such file or directory
 lazy dog

Co tu się stało?
Rozumiem, że bash konfiguruje przekierowanie kierujące STDERR bezpośrednio do pliku /tmp/resultsi ze względu na naturę, >która robi 2 rzeczy

  1. zwykle tworzy nowy plik - w tym przypadku okazja minęła, ponieważ bash przeszedł obok tej procedury w momencie generowania danych wyjściowych.
  2. wstaw prosto na początek pliku. i nie dołączaj tak jak >>robi.

Tak więc w tym przypadku STDERR, wstawia bezpośrednio na początku /tmp/resultsprzesłaniania wyjścia STDOUT.
Uwaga: jeśli >>używałeś dołączania, prawdopodobnie mógłbyś uniknąć tej składni.
Jednak, aby rozwiązać problem, którego potrzebujesz - nie przekierowywać STDERR - bezpośrednio do pliku, ale raczej połączyć dane wyjściowe STDERR ze strumieniem STDOUT, aby uniknąć kolizji.
Korzystanie z operatora 2>&1operatora osiąga to

grep "brown" poem.txt NOT_A_FILE > /tmp/results 2>&1

&Umożliwia bash do odróżnienia od pliku o nazwie 1i 1deskryptora pliku.
Dla mnie 2>&1samo stwierdzenie dokładnie wyjaśnia, co się dzieje - STDERR jest przekierowywany do samego STDOUT - i kończy się na tym, /tmp/resultsponieważ właśnie tam jest wskazany STDOUT (prawie jako efekt uboczny).
W przeciwieństwie do tego, co twierdzą wiele przewodników, 2>&1wysyła STDERR tam, gdzie jest zawsze wskazywany STDOUT. Gdyby tak było - nadal występowałby problem z nadpisywaniem.

Aby uzyskać więcej informacji, zobacz - http://mywiki.wooledge.org/BashGuide/InputAndOutput#File_Redirection

the_velour_fog
źródło