Jakie są różnice między &> i 2> i 1

30

Istnieją dwie formy przekierowania standardowego wyjścia i standardowy błąd na standardowe wyjście . Ale który jest lepszy? i dlaczego &>jest uważany za idealny?

Nie mogę znaleźć różnic, więc wiele samouczków, a nawet bash manualny stan &>jest lepszy!

Dlaczego więc mam korzystać, &>a nie korzystać?2>&1

Głównie za pomocą bashpowłoki


EDYCJA: Dzięki za komentatorów

Tylko> i działa w csh lub tcsh

W ksh działa tylko 2> i 1.

użyj myślnika> tylko plik 2> i 1 przekierowanie

Więc którego użyć, aby upewnić się, że mój skrypt jest kompatybilny z innymi systemami, niezależnie od używanych powłok!

Maythux
źródło
tym lepsze jest to, co musisz zrobić. robią bardzo różne rzeczy. jakiej powłoki używasz?
Skaperen
@Skaperen za pomocą bash
Maythux
1
co ty chcesz osiągnąć?
Skaperen
Chcę tylko wiedzieć, jakie są różnice. To, czego chcę, nie pasuje do obu, ale muszę tylko wiedzieć, czy jest to różnica, aby kiedyś była preferowana w stosunku do innych
Maythux
2
&> somewherejest po prostu skrótem > somewhere 2>&1: w słowach instrukcji bash są one „symantycznie równoważne”
steeldriver,

Odpowiedzi:

23

Strona podręcznika Bash wspomina, że ​​istnieją dwa sposoby przekierowania stderr i stdout : &> file i >& file. Teraz zauważ, że mówi zarówno stderr, jak i stdout.

W takim przypadku >file 2>&1robimy przekierowanie stdout (1) do pliku, ale także informujemy stderr (2), aby został przekierowany w to samo miejsce co stdout! Cel może być taki sam, ale pomysł nieco inny. Innymi słowy „John, idź do szkoły; Suzzie idź tam, gdzie John”.

Co z preferencjami? &>jest bashrzeczą. Więc jeśli przenosisz skrypt, to tego nie zrobi. Ale jeśli masz 100% pewności, że twój skrypt będzie działał tylko na systemie z bash - nie ma preferencji

Oto przykład z dashDebian Amquist Shell, która jest domyślną wersją Ubuntu.

$ grep "YOLO" * &> /dev/null
$ grep: Desktop: Is a directory
grep: Documents: Is a directory
grep: Downloads: Is a directory
grep: Music: Is a directory
grep: Pictures: Is a directory
grep: Public: Is a directory
grep: Templates: Is a directory
grep: Videos: Is a directory
grep: YOLO: Is a directory
grep: bin: Is a directory

Jak widać, stderr nie jest przekierowywany

Aby uwzględnić zmiany wprowadzone w pytaniu, możesz użyć instrukcji if, aby sprawdzić zmienną $ SHELL i odpowiednio zmienić przekierowania

Ale w większości przypadków > file 2>&1powinno działać


Mówiąc bardziej technicznie, formularz [integer]>&wordnazywa się Duplikowaniem deskryptora pliku wyjściowego i jest funkcją określoną przez standard POSIX Shell Command Language, który jest obsługiwany przez większość powłok zgodnych z POSIX i podobnych do Brourne'a.

Zobacz także Co dokładnie oznacza i oznacza przekierowanie danych wyjściowych?

Sergiy Kolodyazhnyy
źródło
Co się dzieje, gdy używasz innych powłok?
Maythux,
zsh obsługuje &>.... @Maythux W powłokach, które nie obsługują &>np. dashmusisz użyć trywialnego >file 2>&1przekierowania ..
heemayl
Którego użyć, jeśli chcę mieć pewność, że mój skrypt będzie kompatybilny z różnymi powłokami
Maythux
3
@Maythux Use >file 2>&1. Ta praca na wszystkich skorupach
Sergiy Kolodyazhnyy
1
@ Powłoki TSJNachos117 ustawione /etc/passwddla każdego użytkownika są powłokami interaktywnymi. Skrypty systemowe są zwykle używane, dash chyba że określono inaczej. Jeśli chodzi o to, co jest domyślne, zależy to od tego, co jest dowiązane symbolicznie /bin/shw przypadku Ubuntu dash. W RHEL jest bash, w FreeBSD jest to tcsh źródło i inne źródło
Sergiy Kolodyazhnyy
6

Zasadniczo poleciłbym postępowanie Bourne'a ponownie , ponieważ bash jest prawdopodobnie najpopularniejszą powłoką uniksową. Bash zwykle używa albo &>albo 2>&1. IMHO, żadne nie jest „idealne”, więc polecam zapomnieć o tych bzdurach. Realistycznie, który powinieneś użyć, zależy od tego, co próbujesz zrobić.

2>&1łączy stderr z stdout, co może być przydatne, jeśli na przykład chcesz przesłać tekst stderr. Na przykład, jeśli chcesz zobaczyć, czy program drukuje określoną wiadomość stderr, ale nie chcesz, aby twój ekran był wypełniony (prawdopodobnie) nieistotnymi śmieciami, możesz zrobić coś takiego program 2>&1 | grep crashed, co przeszuka stdout i stderr z programu nazywany „programem” dla słowa „rozbił się”.

Z drugiej strony, jeśli nie chcesz, aby jakiś program w ogóle coś drukował, możesz po prostu uruchomić program &> /dev/null, co przekieruje zarówno stderr, jak i stdout do / dev / null, specjalnego pliku, który magicznie znika. Lub, jeśli chcesz zapisać dane wyjściowe programu (być może w celu zgłoszenia błędu lub czegoś), możesz przekierować zarówno stderr, jak i stdout do pliku: program &> log.txtprzekieruje wszystkie dane do pliku o nazwie „log.txt”. Jeśli chcesz, możesz przekierować stdout i stderr przez program 2> log.txt > log.txtlub program 2>&1 | cat > log.txt, z których oba miałyby taki sam efekt jak użycie &>. Jeśli zrobisz coś podobnego program 2>&1 > file, tylko stdout zostanie przekierowany, ale stderr może nadal zostać przekierowany do innego programu, takiego jak cat, który może zostać przekierowany, jak pokazano powyżej. Jednak pisanie&>jest łatwiejszy niż jakikolwiek z powyższych przykładów, ponieważ polega na wpisywaniu mniejszej liczby znaków (i jest nieco łatwiejszy do odczytania przez ludzi). Pamiętaj, program 2> log.txt > log.txtże bardziej prawdopodobne jest, że zadziała na powłokach innych niż bash.

PS: jeśli martwisz się, że ludzie używają innych powłok, możesz dodać coś, co będzie pierwszą linią skryptu, zwaną „magiczną liczbą” lub „shebang”. Jest to zasadniczo sposób na upewnienie się, że inne komputery (szczególnie te z systemem operacyjnym Unix-podobnym) wiedzą, jakiego programu użyć do wykonania skryptu. Różne skrypty używają różnych shebangów. Shebang dla skryptu bash wygląda następująco:

#!/bin/bash

Jeśli użyjesz powyższego jako pierwszego wiersza danego skryptu, bash będzie ogólnie używany do wykonania tego skryptu. To znacznie utrudni komuś przypadkowe wykonanie skryptu z niewłaściwą powłoką.

PS: Nie będę kłamał: do tej pory nie wiedziałem, że można go użyć >&, ale jeśli chodzi o bash, wydaje się, że działa tak samo jak &>. Codziennie uczysz się czegoś nowego.

TSJNachos117
źródło
Chociaż zgadzam się z tobą w sprawie użycia #!linii do jawnego żądania bash, nie zawsze jest ona dostępna w innych systemach. Bardzo często programiści / sysadmins muszą pisać przenośne skrypty dla systemów, w których instalacja bashmoże być niedostępna i może nie być pod ich kontrolą bash. >file 2>&1Jest po prostu znacznie przenośne.
Sergiy Kolodyazhnyy 17.07.16
Popełniłeś błąd odwracania powyżej, który nie daje rezultatu, który chcesz lub chcesz uzyskać. Przekieruj stderr na stdout, a następnie przekieruj stdout pozostawia stderr na oryginalnym stdout.
ubfan1 17.07.16
Serg: Nie chciałem sugerować, że bash jest uniwersalny. Myślę jednak, że używa go więcej osób niż mówi (t) csh. Jeśli nie wiesz, czego używa ktoś inny, i musisz zgadywać w ciemno, bash jest prawdopodobnie najlepszym wyborem. Poza tym generalnie nie wiem o przenośności, ponieważ używam tylko bash. Warto >file 2>&1wiedzieć , że jest bardziej przenośny. Dokonam edycji, aby to odzwierciedlić.
TSJNachos117
Ubfan1, dzięki za informację. Nigdy bym nie zgadł, że bash nie przekieruje stderr do pliku w takim przypadku. Właśnie zredagowałem swoją odpowiedź, aby inni nie popełnili tego samego błędu.
TSJNachos117
4

Z podręcznika użytkownika Bash -> 3.6.4 Przekierowanie standardowego wyjścia i standardowego błędu :

Ta konstrukcja umożliwia przekierowanie zarówno standardowego wyjścia (deskryptor pliku 1), jak i standardowego wyjścia błędu (deskryptor pliku 2) do pliku o nazwie rozszerzającej słowo.

Istnieją dwa formaty przekierowywania standardowego wyjścia i standardowego błędu:

&>word

i

>&word

Spośród dwóch form preferowana jest pierwsza. Jest to semantycznie równoważne z

>word 2>&1

Podczas korzystania z drugiego formularza słowo nie może rozwinąć się do liczby lub „-”. Jeśli tak jest, zastosowanie mają inne operatory przekierowania (patrz Powielanie deskryptorów plików poniżej) ze względu na kompatybilność.

Również dobrze jest odnieść się do wiki Grega na temat danych wejściowych i wyjściowych -> 4.2. Manipulacja deskryptorem pliku :

Dla wygody Bash udostępnia również kolejną formę przekierowania. Operator przekierowania &> jest w rzeczywistości krótszą wersją tego, co tutaj zrobiliśmy [ 2>&1]; przekierowanie zarówno stdout, jak i stderr do pliku.

fedorqui
źródło
4

Dlaczego więc mam używać &> a nie 2> i 1

2>&1 jest standardową powłoką Bourne / POSIX.

&>jest rozszerzeniem bash i nie jest standardem de jure .

Jeśli piszesz skrypty przy użyciu rozszerzeń bash, prędzej czy później napotkasz zawroty głowy z komunikatami o błędach składni, ponieważ są one uruchamiane w standardowej powłoce.

Stephen M. Webb
źródło