Soru Kabukta, “2> & 1” ne anlama geliyor?


Bir Unix kabuğunda, birleştirmek istersem stderr ve stdout içine stdout Daha fazla manipülasyon için akışım, komutumun sonuna aşağıdakileri ekleyebilirim:

2>&1

Eğer kullanmak istersem head çıkışından g++Böyle bir şey yapabilirim:

g++ lots_of_errors 2>&1 | head

bu yüzden sadece ilk birkaç hatayı görebiliyorum.

Bunu hatırlamakta her zaman sorun yaşıyorum, ve sürekli bakmak zorundayım, ve temel olarak bu özel oyunun sözdizimini tam olarak anlamadığım için.

Birisi bunu kırabilir ve karaktere göre karakterini açıklayabilir mi 2>&1  anlamına geliyor?


1738
2018-05-03 22:57


Menşei


@dbr Ben sadece bash olduğunu sanmıyorum - bourne kabuk şey inanıyorum; dolayısıyla sh, bash, ksh, kül, tire vb. - guns
Bu, POSIX uyumlu kabukları veya POSIX kabuğunu açıklayan yeniden yönlendirme paragrafının bir parçasıdır. ksh örneğin bir POSIX kabuğudur. Görmek:pubs.opengroup.org/onlinepubs/009695399/utilities/... - jim mcnamara
Bu yapı ayrıca Windows üzerinde çalışır. - Vadzim
Genelde daha iyi 2>&1 göre 2> / dev / null ;-) - F. Hauri
Bundan bahsetmeyi düşündüm. |&  için kısa 2>&1 | eğer zsh kullanıyorsan. Bunun diğer bourne benzeri kabuklar için mi yoksa sadece bir zsh özelliği mi olduğunu anlayamıyorum. - chrixian


Cevaplar:


Dosya tanıtıcısı 1 standart çıktıdır (stdout).
Dosya tanıtıcısı 2 standart hatadırstderr).

İşte bu yapıyı hatırlamanın bir yolu (tamamen doğru olmasa da): ilk başta, 2>1 yönlendirme için iyi bir yol gibi görünebilir stderr için stdout. Ancak, aslında "yönlendirme" olarak yorumlanacaktır stderr adlı bir dosyaya 1". & Aşağıdaki, bir dosya adı değil, bir dosya adı olduğunu gösterir. Böylece yapı şöyle olur: 2>&1.


1943
2018-05-03 23:04



ama daha sonra olmamalı &2>&1? - dokaspar
@Dominik: Hayır, & yalnızca yönlendirme bağlamında "dosya tanıtıcı" anlamına gelmek üzere yorumlanır. yazı command &2>& olarak ayrıştırıldı command & ve 2>&1"koş" command arka planda, sonra komutu çalıştırın 2 ve stdout'unu stdout'una yönlendirin ". - Adam Rosenfield
Burada ilginç bilgiler: mywiki.wooledge.org/BashFAQ/055 - Halil Özgür
Fakat stderr'i '& 1' adlı bir dosyaya nasıl yönlendirirsiniz? - Martín Fixman
@Martin: 2>'&1' - rogual


echo test > afile.txt

stdout'u yeniden yönlendirir afile.txt. Bu yapmakla aynı şey

echo test 1> afile.txt

Stderr'i yönlendirmek için şunları yaparsınız:

echo test 2> afile.txt

>& akışı başka bir dosya tanıtıcısına yeniden yönlendiren sözdizimi - 0 stdin, 1 stdout ve 2 stderr.

Yaparak stdout'u stderr'e yönlendirebilirsiniz:

echo test 1>&2 # or echo test >&2

Ya da tam tersi:

echo test 2>&1

Yani, kısacası ... 2> stderr'i (belirtilmemiş) bir dosyaya yeniden yönlendirir &1 stderr'i stdout'a yönlendirir.


481
2018-05-03 22:59



Bu sizin için bir anlam ifade ediyor mu, java ... 2&1 >> data.logBir meslektaşımın bunu yaptığını gördün mü? - Thang Pham
@Harry, ya bash olmayan bir kabuk ya da yazım hatası gibi görünüyor. cmd 2>&1 >> somefile.log bir dosyaya stdout / stderr ekleyecektir - temelde yukarıdakiyle aynıdır >> file eklemek - dbr
@dbr cmd 2>&1 >>file stderr dosyasını dosyaya yönlendirmez, ancak cmd >> file 2>&1 yapar. Sipariş önemlidir. İlk durumda, stderr kabuğun stdout'una yeniden yönlendirilir (komut, etkileşimli olarak girilirse muhtemelen bir tty olur) ve sonra stdout dosyaya yönlendirilir. İkinci durumda, stdout dosyaya yönlendirilir ve stderr aynı yere yönlendirilir. - William Pursell
Yukarıdaki cevabı beğeniyorum, ancak daha net bir dokunuş olabilir. "2> & 1", stderr'i stdout hedefine yönlendiriyor. Yani "ls -l >> directoryContents 2> & 1" gibi bir şeye sahipseniz, sonuç directoryContents adlı bir dosyaya eklenmiş çalışma dizininin içeriğine sahip olacaktır. Yürütme sırasında herhangi bir hata varsa: hata iletileri de bunlar gerçekleştikçe directoryContents dosyasına eklenir. - Max West
mı 0(or 1,2)>&0(or 1,2) Çıkışı kontrol etmek için bir seçenek gibi mi? mı echo test >test.log 2>&1 ile aynı echo test 2>&1 >test.log? - Simin Jie


Yönlendirme hakkında bazı hileler

Bununla ilgili bazı sözdizimi özellikleri önemli davranışlara sahip olabilir. Yönlendirmeler hakkında bazı küçük örnekler var. STDERR, STDOUTve argümanlar sipariş.

1 - Üzerine yazma veya ekleme?

sembol > anlamına gelmek yönlendirme.

  • > anlamına gelmek tamamlanmış bir dosya olarak gönderVarsa, üzerine yazma hedefi (bkz. noclobber bash özelliği 3. sonra).
  • >> anlamına gelmek ek olarak göndermek Varsa hedefe eklenir.

Her halükarda, dosya mevcut değilse oluşturulacaktır.

2 - kabuk komut satırı sipariş bağımlıdır!

Bunu test etmek için ihtiyacımız var. her iki çıkışta da bir şey gönderecek basit bir komut:

$ ls -ld /tmp /tnt
ls: cannot access /tnt: No such file or directory
drwxrwxrwt 118 root root 196608 Jan  7 11:49 /tmp

$ ls -ld /tmp /tnt >/dev/null
ls: cannot access /tnt: No such file or directory

$ ls -ld /tmp /tnt 2>/dev/null
drwxrwxrwt 118 root root 196608 Jan  7 11:49 /tmp

(Adında bir dizinin bulunmadığını tahmin etme /tnt, tabii ki ;). Eh, biz var !!

Yani, görelim:

$ ls -ld /tmp /tnt >/dev/null
ls: cannot access /tnt: No such file or directory

$ ls -ld /tmp /tnt >/dev/null 2>&1

$ ls -ld /tmp /tnt 2>&1 >/dev/null
ls: cannot access /tnt: No such file or directory

Son komut satırı dökümleri STDERR konsola ve beklenen davranışa benzemiyor ... Ama ...

Eğer biraz yapmak istersen filtreleme sonrası Bir çıktı, diğeri veya ikisi hakkında:

$ ls -ld /tmp /tnt | sed 's/^.*$/<-- & --->/'
ls: cannot access /tnt: No such file or directory
<-- drwxrwxrwt 118 root root 196608 Jan  7 12:02 /tmp --->

$ ls -ld /tmp /tnt 2>&1 | sed 's/^.*$/<-- & --->/'
<-- ls: cannot access /tnt: No such file or directory --->
<-- drwxrwxrwt 118 root root 196608 Jan  7 12:02 /tmp --->

$ ls -ld /tmp /tnt >/dev/null | sed 's/^.*$/<-- & --->/'
ls: cannot access /tnt: No such file or directory

$ ls -ld /tmp /tnt >/dev/null 2>&1 | sed 's/^.*$/<-- & --->/'

$ ls -ld /tmp /tnt 2>&1 >/dev/null | sed 's/^.*$/<-- & --->/'
<-- ls: cannot access /tnt: No such file or directory --->

Bu paragraftaki son komut satırının, yazdığım yerdeki önceki paragraftakiyle aynı olduğuna dikkat edin. beklenen davranış gibi görünmüyor (Bu, beklenen bir davranış bile olabilir).

Eh, yönlendirme hakkında biraz hile var, her iki çıkışta da farklı işlem yapmak:

$ ( ls -ld /tmp /tnt | sed 's/^/O: /' >&9 ) 9>&2  2>&1  | sed 's/^/E: /'
O: drwxrwxrwt 118 root root 196608 Jan  7 12:13 /tmp
E: ls: cannot access /tnt: No such file or directory

Nota: &9tanımlayıcı kendiliğinden ortaya çıkacaktır ) 9>&2.

Ek: nota! Yeni sürümü ile  (>4.0) Bu tür şeyler yapmak için yeni bir özellik ve daha seksi sözdizimi var:

$ ls -ld /tmp /tnt 2> >(sed 's/^/E: /') > >(sed 's/^/O: /')
O: drwxrwxrwt 17 root root 28672 Nov  5 23:00 /tmp
E: ls: cannot access /tnt: No such file or directory

Ve son olarak böyle bir basamaklı çıkış formatı için:

$ ((ls -ld /tmp /tnt |sed 's/^/O: /' >&9 ) 2>&1 |sed 's/^/E: /') 9>&1| cat -n
     1  O: drwxrwxrwt 118 root root 196608 Jan  7 12:29 /tmp
     2  E: ls: cannot access /tnt: No such file or directory

Ek: nota! Her iki açıdan aynı yeni sözdizimi:

$ cat -n <(ls -ld /tmp /tnt 2> >(sed 's/^/E: /') > >(sed 's/^/O: /'))
     1  O: drwxrwxrwt 17 root root 28672 Nov  5 23:00 /tmp
     2  E: ls: cannot access /tnt: No such file or directory

Nerede STDOUT belirli bir filtreden geçmek STDERR diğerine ve son olarak her iki çıktı birleştirilmiş üçüncü bir komut filtresinden geçer.

3 - hakkında bir kelime noclobber seçenek ve >| sözdizimi

Bu hakkında üzerine yazarak:

Süre set -o noclobber bash yapmak değil herhangi bir dosyanın üzerine yaz >| sözdizimi bu sınırlamayı aşmanızı sağlar:

$ testfile=$(mktemp /tmp/testNoClobberDate-XXXXXX)

$ date > $testfile ; cat $testfile
Mon Jan  7 13:18:15 CET 2013

$ date > $testfile ; cat $testfile
Mon Jan  7 13:18:19 CET 2013

$ date > $testfile ; cat $testfile
Mon Jan  7 13:18:21 CET 2013

Her seferinde dosyanın üzerine yazılıyor:

$ set -o noclobber

$ date > $testfile ; cat $testfile
bash: /tmp/testNoClobberDate-WW1xi9: cannot overwrite existing file
Mon Jan  7 13:18:21 CET 2013

$ date > $testfile ; cat $testfile
bash: /tmp/testNoClobberDate-WW1xi9: cannot overwrite existing file
Mon Jan  7 13:18:21 CET 2013

İle geçmek >|:

$ date >| $testfile ; cat $testfile
Mon Jan  7 13:18:58 CET 2013

$ date >| $testfile ; cat $testfile
Mon Jan  7 13:19:01 CET 2013

Bu seçeneği belirlemek ve / veya önceden ayarlanmışsa sorgulamak.

$ set -o | grep noclobber
noclobber           on

$ set +o noclobber

$ set -o | grep noclobber
noclobber           off

$ date > $testfile ; cat $testfile
Mon Jan  7 13:24:27 CET 2013

$ rm $testfile

4 - Son numara ve daha fazlası ...

Yönlendirme için her ikisi de Verilen bir komuttan çıktı, doğru bir sözdiziminin olabileceğini görüyoruz:

$ ls -ld /tmp /tnt >/dev/null 2>&1

bunun için özel durumda, bir kısayol sözdizimi var: &> ... veya >&

$ ls -ld /tmp /tnt &>/dev/null

$ ls -ld /tmp /tnt >&/dev/null

Not: eğer 2>&1 var olmak, 1>&2 doğru bir sözdizimi de:

$ ls -ld /tmp /tnt 2>/dev/null 1>&2

4b- Şimdi, düşünmene izin vereceğim:

$ ls -ld /tmp /tnt 2>&1 1>&2  | sed -e s/^/++/
++/bin/ls: cannot access /tnt: No such file or directory
++drwxrwxrwt 193 root root 196608 Feb  9 11:08 /tmp/

$ ls -ld /tmp /tnt 1>&2 2>&1  | sed -e s/^/++/
/bin/ls: cannot access /tnt: No such file or directory
drwxrwxrwt 193 root root 196608 Feb  9 11:08 /tmp/

4c-ilgileniyorsanız Daha bilgi

İnce el kitabını okuyarak okuyabilirsiniz:

man -Len -Pless\ +/^REDIRECTION bash

içinde  konsol ;-)


257
2018-04-29 16:33



Daha fazla okuma: Bunu sevdiyseniz, apreciate: Yönlendirme kötüye kullanımı nasıl garip davranışlar verebilir? - F. Hauri
Daha fazla okuma ||: A her iki çıkışı da çıkış değişkenlerine depolamak - F. Hauri


Sayılar dosya tanıtıcılarına (fd) başvurur.

  • Sıfır stdin 
  • Biri stdout 
  • İki stderr

2>&1 fd 2'yi 1'e yönlendirir.

Bu, program bunları kullanırsa, herhangi bir sayıda dosya tanıtıcısı için çalışır.

Bakabilirsiniz /usr/include/unistd.h eğer onları unutursan:

/* Standard file descriptors.  */
#define STDIN_FILENO    0   /* Standard input.  */
#define STDOUT_FILENO   1   /* Standard output.  */
#define STDERR_FILENO   2   /* Standard error output.  */

Bu, standart olmayan dosya tanımlayıcılarını özel günlüğe kaydetme için kullanan C araçlarını yazdığımı, böylece bir dosyaya veya başka bir şeye yönlendirmediğiniz sürece onu görmediğinizi söyledi.


67
2018-05-03 22:58





Bu yapı standart hata akışını gönderir (stderr) şimdiki Standart çıktının yeristdout) - Bu para birimi sorunu diğer cevaplar tarafından ihmal edilmiş gibi görünüyor.

Bu yöntemi kullanarak herhangi bir çıktı tutamaçını diğerine yeniden yönlendirebilirsiniz, ancak çoğunlukla kanalda kullanılır stdout ve stderr İşleme için tek bir akışa akar.

Bazı örnekler:

# Look for ERROR string in both stdout and stderr.
foo 2>&1 | grep ERROR

# Run the less pager without stderr screwing up the output.
foo 2>&1 | less

# Send stdout/err to file (with append) and terminal.
foo 2>&1 |tee /dev/tty >>outfile

# Send stderr to normal location and stdout to file.
foo >outfile1 2>&1 >outfile2

Sonuncunun o olacağını unutmayın değil direkt stderr için outfile2 - neye yönlendiriyor? stdout argüman karşılaştığı zaman oldu (outfile1) ve sonra yönlendirmeleri stdout için outfile2.

Bu oldukça karmaşık bazı hilelere izin verir.


49
2018-05-03 23:54



Bu son örnek her ne kadar daha açık olsa da: foo> outfile2 2> outfile1 - Michael Cramer
Daha açık, evet, ama bu yönlendirme "konumsal" doğasını göstermez. Örnek, genellikle tek bir satırda bunu yapmak için yararlı olmadığından, devam etmektedir. Bu yöntem, yeniden yönlendirmenin farklı bölümlerinden farklı taraflar sorumlu olduğunda gerçekten işe yarar. Örneğin, bir betik bir yönlendirme komutu yaptığında ve bunu başka bir bitle çalıştırdığınızda. - paxdiablo
Sadece son örneğin neden bununla ilgili uzun zamandır devam eden karışıklığı çözdüğünü fark ettim: some_program 2>&1 > /dev/null böyle çalışmıyor: some_program > /dev/null 2>&1. - snapfractalpop
Son örnekle ilgili yorumunuz altın harflerine değiyor :-) Bu yönlendirme argümanlarının konumsal olduğunu hiç düşünmemiştim ... Bunun bence çok önemli olduğunu düşünüyorum. - Nils-o-mat


Yönlendirme konusunda bu harika mesajı buldum: Yönlendirmeler hakkında her şey

Hem standart çıktı hem de standart hatayı bir dosyaya yönlendir

$ komut &> dosya

Bu one-liner kullanır &> Operatör, çıktı akışlarını - stdout ve stderr - komuttan dosyaya yönlendiriyor. Bu, Bash'in her iki akışı da aynı hedefe hızlı bir şekilde yönlendirmek için kısayoludur.

Bash her iki akışı da yönlendirdikten sonra dosya tanımlayıcı tablosu nasıl görünür:

Enter image description here

Gördüğünüz gibi, hem stdout hem de stderr şimdi file. Böylece stdout ve stderr’e yazılan her şey file.

Her iki akışı da aynı hedefe yönlendirmenin birkaç yolu vardır. Her akışı birbiri ardına yeniden yönlendirebilirsiniz:

$ komut> dosya 2> ve 1

Bu, her iki akışı da bir dosyaya yönlendirmenin çok daha yaygın bir yoludur. İlk stdout dosyaya yönlendirilir ve stderr stdout ile aynı olacak şekilde çoğaltılır. Yani her iki akarsu da file.

Bash birkaç yönlendirme gördüğünde, bunları soldan sağa işler. Adımları gözden geçirelim ve bunun nasıl olduğunu görelim. Herhangi bir komutu çalıştırmadan önce, Bash'ın dosya tanıtıcı tablosu şuna benzer:

Enter image description here

Şimdi Bash, ilk yönlendirme> dosyasını işliyor. Bunu daha önce de gördük ve dosyaya stdout noktasını getiriyor:

Enter image description here

Sonraki Bash ikinci yönlendirmeyi 2> & 1 görür. Bu yönlendirmeyi daha önce görmedik. Bu, dosya tanıtıcı 1'in bir kopyası olmak için dosya tanıtıcı 2'yi çoğaltır ve şöyle olur:

Enter image description here

Her iki akış da dosyaya yönlendirildi.

Ancak burada dikkatli olun! yazı

komut> dosya 2> & 1

yazıyla aynı değil:

$ komut 2> & 1> dosya

Bash'de yeniden yönlendirmelerin sırası önemlidir! Bu komut sadece standart çıktıyı dosyaya yönlendirir. Stderr hala terminale yazdıracaktır. Bunun neden olduğunu anlamak için, tekrar adımları atlayalım. Bu nedenle, komutu çalıştırmadan önce dosya tanıtıcı tablosu şuna benzer:

Enter image description here

Şimdi Bash işlemleri yönlendirmeleri soldan sağa doğru. İlk önce 2> & 1 görür, böylece stdout'u stderr ile kopyalar. Dosya tanıtıcı tablosu şöyle olur:

Enter image description here

Bash şimdi ikinci yönlendirmeyi görüyor, >fileve stdout'u dosyaya yönlendirir:

Enter image description here

Burada ne olduğunu görüyor musun? Stdout şimdi dosyaya işaret ediyor, ancak stderr hala terminale işaret ediyor! Stderr'e yazılan her şey hala ekrana yazdırılıyor! Bu yüzden yönlendirmelerin sırasına çok, çok dikkat edin!

Ayrıca Bash’te yazmanın

$ komut &> dosya

tam olarak aynıdır:

$ komut> ve dosya


47
2017-10-29 13:04



Son iki, "komut" bir sayı ile biterse farklıdır, o zaman bu, isteğe bağlı dosya tanıtıcısı olarak alınır. >& - M.M
harika bir açıklama! teşekkür ederim - Vicer


2>&1 POSIX kabuk yapısıdır. İşte bir arıza, belirteci:


2: "Standart hata"çıktı dosya tanıtıcısı.

>&: Bir Çıkış Dosya Tanımlayıcısı çoğaltın operatör (bir varyantı Çıkış Yönlendirme Şebeke >). verilmiş [x]>&[y], belirtilen dosya tanıtıcısı x çıktı dosyası tanımlayıcısının bir kopyası olarak yapılır y.

1 "Standart çıkış"çıktı dosya tanıtıcısı.

İfade 2>&1 dosya tanıtıcısını kopyalar 1 yere 2, böylece herhangi bir çıktı 2 Yürütme ortamında ("standart hata"), başlangıçta tarafından açıklanan aynı dosyaya gider 1 ("standart çıktı").


Daha fazla açıklama:

Dosya Tanımlayıcısı: "Dosya erişimi amacıyla açık bir dosyayı tanımlamak için kullanılan, işlem başına benzersiz, negatif olmayan bir tam sayı."

Standart çıkış / hata: Aşağıdaki nota bakın. Yönlendirme kabuk belgelerinin bölümü:

Açık dosyalar sıfır ile başlayan ondalık sayılar ile temsil edilir. Mümkün olan en büyük değer, uygulama tanımlıdır; Bununla birlikte, tüm uygulamalar, uygulama tarafından kullanılmak üzere en az 0 ila 9 arasında destekleyici olacaktır. Bu sayılara "dosya tanıtıcıları" denir. 0, 1 ve 2 değerleri, özel anlamlara ve konvansiyonel kullanımlara sahiptir ve belirli yönlendirme işlemlerinden geçmektedir; sırasıyla standart girdi, standart çıktı ve standart hata olarak adlandırılır. Programlar genellikle girdilerini standart girişten alır ve çıktıyı standart çıktıya yazar. Hata mesajları genellikle standart hataya yazılır. Yönlendirme işleçleri, dosya tanımlayıcı numarasını belirtmek için bir veya daha fazla sayıdan (araya giren karakterlerin girilmesine izin verilmeden) önce gelebilir.


13
2017-12-25 06:43





Sorunuzu cevaplamak için: Herhangi bir hata çıktısını alır (normalde stderr'e gönderilir) ve standart çıktıya (stdout) yazar.

Tüm çıktılar için çağrı yapmaya ihtiyaç duyduğunuzda, örneğin 'daha fazla' ile yardımcı olabilirsiniz. Kullanım bilgileri stderr'e yazdırmak gibi bazı programlar.

Hatırlamanıza yardımcı olmak için

  • 1 = standart çıktı (programların normal çıktı yazdırdığı)
  • 2 = standart hata (programların yazdırdığı hatalar)

"2> & 1", sadece stderr'e gönderilen her şeyi, bunun yerine stdout'a işaret eder.

Okumayı da tavsiye ederim yönlendirme hatasıyla ilgili bu gönderi bu konunun tamamı ayrıntılı olarak ele alınmıştır.


12
2018-05-03 23:24





2 konsol standart hatasıdır.

1 konsol standart çıktı.

Bu standart Unix ve Windows da POSIX'i takip ediyor.

Örneğin. koştuğunda

perl test.pl 2>&1

standart hata standart çıktıya yönlendirilir, böylece her iki çıkışı da birlikte görebilirsiniz:

perl test.pl > debug.log 2>&1

Çalıştırdıktan sonra, debug.log dosyasında hatalar dahil olmak üzere tüm çıktıları görebilirsiniz.

perl test.pl 1>out.log 2>err.log

Sonra standart çıktı out.log ve err.log'a standart hata gider.

Bunları anlamaya çalışmanı öneririm.


12
2017-07-19 03:23



İkinci örnek yanlış: sipariş önceliği olarak STDERR yönlendirildi STDOUT, sadece varsayılan STDOUT yazılacak hata ayıklama günlüğü (değil STDERR) görmek cevabım (paragraf # 2)! Emin olmak için her ikisi de Aynı dosyaya yönlendirileceksiniz, yönlendirme direktiflerini tersine çevirmelisiniz: perl test.pl > debug.log 2>&1 - F. Hauri


Bir programcının bakış açısından, tam olarak bunun anlamı:

dup2(1, 2);

Bakın adam sayfası.

Bunu anlamak 2>&1 bir kopya ayrıca nedenini açıklıyor ...

command >file 2>&1

... aynı şey değil ...

command 2>&1 >file

İlk, her iki akışı da gönderecek file, ikincisi ise stdoutve sıradan çıktı file.


10
2017-12-03 10:20