Pertanyaan Di shell, apa arti "2> & 1"?


Dalam shell Unix, jika saya ingin menggabungkan stderr dan stdout ke dalam stdout streaming untuk manipulasi lebih lanjut, saya dapat menambahkan yang berikut di akhir perintah saya:

2>&1

Jadi, jika saya ingin menggunakannya head pada output dari g++, Saya bisa melakukan sesuatu seperti ini:

g++ lots_of_errors 2>&1 | head

jadi saya hanya bisa melihat beberapa kesalahan pertama.

Saya selalu mengalami kesulitan mengingat ini, dan saya terus-menerus harus mencarinya, dan itu terutama karena saya tidak sepenuhnya memahami sintaks trik khusus ini.

Dapatkah seseorang memecahkan ini dan menjelaskan karakter demi karakter apa 2>&1  cara?


1734
2018-05-03 22:57


asal


Jawaban:


File descriptor 1 adalah output standar (stdout).
File descriptor 2 adalah kesalahan standar (stderr).

Berikut ini satu cara untuk mengingat konstruk ini (meskipun tidak sepenuhnya akurat): pada awalnya, 2>1 mungkin terlihat seperti cara yang bagus untuk mengalihkan stderr untuk stdout. Namun, itu sebenarnya akan ditafsirkan sebagai "redirect stderr ke sebuah file bernama 1". & menunjukkan bahwa apa yang berikut adalah file descriptor dan bukan nama file. Jadi konstruksinya menjadi: 2>&1.


1942
2018-05-03 23:04



echo test > afile.txt

redirect ke stdout afile.txt. Ini sama dengan melakukan

echo test 1> afile.txt

Untuk mengalihkan stderr, Anda harus:

echo test 2> afile.txt

>& adalah sintaks untuk mengarahkan aliran ke deskriptor file lain - 0 stdin, 1 stdout, dan 2 stderr.

Anda dapat mengarahkan ulang stdout ke stderr dengan melakukan:

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

Atau sebaliknya:

echo test 2>&1

Jadi, singkatnya ... 2> mengalihkan stderr ke file (tidak ditentukan), menambahkan &1 redirect stderr ke stdout.


481
2018-05-03 22:59



Beberapa trik tentang pengalihan

Beberapa kekhususan sintaks tentang ini mungkin memiliki perilaku yang penting. Ada beberapa contoh kecil tentang pengalihan, STDERR, STDOUT, dan argumen pemesanan.

1 - Timpa atau menambahkan?

Simbol > berarti pengalihan.

  • > berarti kirim ke sebagai file lengkap secara keseluruhan, timpa target jika ada (lihat noclobber fitur bash di # 3 kemudian).
  • >> berarti kirim sebagai tambahan akan menambahkan target jika ada.

Dalam kasus apa pun, file akan dibuat jika tidak ada.

2 - The baris perintah shell tergantung pesanan !!

Untuk menguji ini, kami membutuhkan perintah sederhana yang akan mengirim sesuatu pada kedua output:

$ 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

(Mengharapkan Anda tidak memiliki direktori bernama /tnt, tentu saja ;). Yah, kita memilikinya !!

Jadi, mari kita lihat:

$ 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

Baris perintah terakhir yang dibuang STDERR ke konsol, dan tampaknya tidak menjadi perilaku yang diharapkan ... Tapi ...

Jika Anda ingin membuatnya posting penyaringan sekitar satu output, yang lain atau keduanya:

$ 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 --->

Perhatikan bahwa baris perintah terakhir dalam paragraf ini sama persis dengan paragraf sebelumnya, di mana saya menulis tampaknya tidak menjadi perilaku yang diharapkan (jadi, ini bahkan bisa menjadi perilaku yang diharapkan).

Nah, ada sedikit trik tentang pengalihan, untuk melakukan operasi yang berbeda pada kedua output:

$ ( 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

Tidak a: &9pendeskripsi akan terjadi secara spontan karena ) 9>&2.

Tambahan: nota! Dengan versi baru  (>4.0) ada fitur baru dan sintaksis yang lebih seksi untuk melakukan hal-hal seperti ini:

$ 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

Dan akhirnya untuk format keluaran berjenjang:

$ ((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

Tambahan: nota! Sintaks baru yang sama, dalam dua cara:

$ 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

Dimana STDOUT melalui filter tertentu, STDERR ke yang lain dan akhirnya kedua output digabungkan melalui filter perintah ketiga.

3 - Sepatah kata tentang noclobber opsi dan >| sintaksis

Itu tentang menimpa:

Sementara set -o noclobber menginstruksikan bash ke tidak menimpa file yang ada, file >| sintaks membiarkan Anda melewati batasan ini:

$ 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

File ini ditimpa setiap kali, nah sekarang:

$ 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

Lewati dengan >|:

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

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

Membatalkan opsi ini dan / atau bertanya jika sudah disetel.

$ 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 - Trik terakhir dan lainnya ...

Untuk mengalihkan kedua output dari perintah yang diberikan, kita melihat bahwa sintaks yang benar bisa:

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

untuk ini khusus huruf besar, ada sintaks pintas: &> ... atau >&

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

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

Nota: jika 2>&1 ada, 1>&2 adalah sintaks yang benar juga:

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

4b- Sekarang, saya akan membiarkan Anda berpikir tentang:

$ 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- Jika Anda tertarik lebih informasi

Anda dapat membaca manual halus dengan menekan:

man -Len -Pless\ +/^REDIRECTION bash

di sebuah  konsol ;-)


256
2018-04-29 16:33



Angka-angka mengacu pada deskriptor file (fd).

  • Zero adalah stdin 
  • Satu adalah stdout 
  • Dua adalah stderr

2>&1 mengarahkan kembali fd 2 ke 1.

Ini berfungsi untuk sejumlah deskriptor file jika program menggunakannya.

Anda bisa melihat /usr/include/unistd.h jika Anda melupakannya:

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

Yang mengatakan saya telah menulis alat C yang menggunakan deskriptor file non-standar untuk custom logging sehingga Anda tidak melihatnya kecuali Anda mengarahkan ke file atau sesuatu.


67
2018-05-03 22:58



Membangun itu mengirimkan aliran kesalahan standar (stderr) ke arus lokasi keluaran standar (stdout) - masalah mata uang ini tampaknya telah diabaikan oleh jawaban lainnya.

Anda dapat mengarahkan setiap gagang keluaran ke yang lain dengan menggunakan metode ini tetapi ini paling sering digunakan untuk menyalurkan stdout dan stderr streaming menjadi satu aliran tunggal untuk diproses.

Beberapa contoh adalah:

# 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

Perhatikan bahwa yang terakhir akan tidak langsung stderr untuk outfile2 - itu mengarahkannya ke apa stdout adalah ketika argumen itu ditemui (outfile1) dan kemudian pengalihan stdout untuk outfile2.

Ini memungkinkan tipuan yang cukup canggih.


49
2018-05-03 23:54



Saya menemukan posting brilian ini di redirection: Semua tentang pengarahan ulang

Alihkan kedua output standar dan kesalahan standar ke file

$ command &> file

Garis satu ini menggunakan &> operator untuk mengarahkan kedua aliran output - stdout dan stderr - dari perintah ke file. Ini adalah cara pintas Bash untuk dengan cepat mengarahkan kedua aliran ke tujuan yang sama.

Berikut adalah bagaimana tabel deskriptor file terlihat setelah Bash mengalihkan dua aliran:

Enter image description here

Seperti yang Anda lihat, baik stdout dan stderr sekarang mengarah ke file. Jadi apa pun yang ditulis ke stdout dan stderr ditulis file.

Ada beberapa cara untuk mengarahkan kedua aliran ke tujuan yang sama. Anda dapat mengalihkan setiap aliran satu demi satu:

$ command> file 2> & 1

Ini adalah cara yang lebih umum untuk mengalihkan kedua aliran ke file. Pertama stdout dialihkan ke file, dan kemudian stderr diduplikasi menjadi sama dengan stdout. Jadi kedua aliran akhirnya menunjuk ke file.

Ketika Bash melihat beberapa pengalihan, ia memprosesnya dari kiri ke kanan. Mari kita lihat langkah-langkahnya dan lihat bagaimana itu terjadi. Sebelum menjalankan perintah apa pun, tabel deskriptor file Bash terlihat seperti ini:

Enter image description here

Sekarang Bash memproses file redirection> pertama. Kami telah melihat ini sebelumnya dan itu membuat titik stdout ke file:

Enter image description here

Selanjutnya Bash melihat pengalihan kedua 2> & 1. Kami belum melihat pengalihan ini sebelumnya. Ini duplikat file deskriptor 2 untuk menjadi salinan deskriptor file 1 dan kita mendapatkan:

Enter image description here

Kedua streaming telah dialihkan ke file.

Namun hati-hati di sini! Penulisan

perintah> file 2> & 1

tidak sama dengan menulis:

$ command 2> & 1> file

Urutan pengalihan penting di Bash! Perintah ini hanya mengarahkan keluaran standar ke file. Stderr akan tetap mencetak ke terminal. Untuk memahami mengapa itu terjadi, mari kita lakukan lagi langkah-langkahnya. Jadi sebelum menjalankan perintah, tabel deskriptor file terlihat seperti ini:

Enter image description here

Sekarang Bash memproses pengalihan dari kiri ke kanan. Pertama kali melihat 2> & 1 sehingga duplikat stderr ke stdout. Tabel deskriptor file menjadi:

Enter image description here

Sekarang Bash melihat pengalihan kedua, >file, dan itu mengarahkan ulang stdout ke file:

Enter image description here

Apakah Anda melihat apa yang terjadi di sini? Stdout sekarang menunjuk ke file, tetapi stderr masih menunjuk ke terminal! Segala sesuatu yang ditulis ke stderr masih akan dicetak ke layar! Jadi sangat, sangat berhati-hati dengan urutan pengalihan!

Juga perhatikan bahwa di Bash, menulis

$ command &> file

persis sama dengan:

$ command> & file


47
2017-10-29 13:04



2>&1 adalah konstruksi shell POSIX. Berikut ini rinciannya, token by token:


2: "Kesalahan standar"deskripsi file keluaran.

>&: Gandakan Descriptor File Output operator (varian dari Output Redirection operator >). Diberikan [x]>&[y], deskriptor file dilambangkan oleh x dibuat menjadi salinan deskriptor file keluaran y.

1 "Keluaran standar"deskripsi file keluaran.

Ekspresi 2>&1 salinan file deskriptor 1 ke lokasi 2, jadi setiap keluaran ditulis ke 2 ("standard error") dalam lingkungan eksekusi pergi ke file yang sama yang awalnya dijelaskan oleh 1 ("keluaran standar").


Penjelasan lebih lanjut:

File Descriptor: "Sebuah bilangan bulat unik, non-proses yang unik yang digunakan untuk mengidentifikasi file terbuka untuk tujuan akses file."

Keluaran / kesalahan standar: Lihat catatan berikut di Redirection bagian dari dokumentasi shell:

Buka file diwakili oleh angka desimal dimulai dengan nol. Nilai terbesar yang mungkin adalah implementasi yang ditentukan; namun, semua implementasi harus mendukung setidaknya 0 hingga 9, inklusif, untuk digunakan oleh aplikasi. Angka-angka ini disebut "deskriptor file". Nilai-nilai 0, 1, dan 2 memiliki arti khusus dan penggunaan konvensional dan tersirat oleh operasi redirection tertentu; mereka disebut sebagai input standar, output standar, dan kesalahan standar, masing-masing. Program biasanya mengambil input mereka dari input standar, dan menulis output pada output standar. Pesan kesalahan biasanya ditulis pada kesalahan standar. Operator redirection dapat didahului oleh satu atau lebih digit (tanpa karakter intervening diperbolehkan) untuk menunjuk nomor deskriptor file.


13
2017-12-25 06:43



Untuk menjawab pertanyaan Anda: Diperlukan output kesalahan apa pun (biasanya dikirim ke stderr) dan menulisnya ke output standar (stdout).

Ini membantu dengan, misalnya 'lebih banyak' ketika Anda membutuhkan paging untuk semua output. Beberapa program seperti pencetakan informasi penggunaan ke stderr.

Untuk membantu Anda mengingat

  • 1 = output standar (di mana program mencetak output normal)
  • 2 = standard error (di mana program mencetak kesalahan)

"2> & 1" hanya menunjukkan semua yang dikirim ke stderr, ke stdout sebagai gantinya.

Saya juga merekomendasikan membaca posting ini tentang kesalahan mengarahkan di mana subjek ini dibahas secara lengkap.


12
2018-05-03 23:24



2 adalah kesalahan standar konsol.

1 adalah keluaran standar konsol.

Ini adalah standar Unix, dan Windows juga mengikuti POSIX.

Misalnya. ketika kamu berlari

perl test.pl 2>&1

kesalahan standar dialihkan ke output standar, sehingga Anda dapat melihat kedua output bersama:

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

Setelah eksekusi, Anda dapat melihat semua output, termasuk kesalahan, di debug.log.

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

Lalu keluaran standar pergi ke out.log, dan kesalahan standar ke err.log.

Saya menyarankan Anda untuk mencoba memahami ini.


12
2017-07-19 03:23



Dari sudut pandang programmer, itu artinya ini:

dup2(1, 2);

Lihat halaman manual.

Memahami itu 2>&1 adalah salinan juga menjelaskan mengapa ...

command >file 2>&1

... tidak sama dengan ...

command 2>&1 >file

Yang pertama akan mengirim kedua streaming ke file, sedangkan yang kedua akan mengirim kesalahan ke stdout, dan output biasa menjadi file.


10
2017-12-03 10:20



Orang-orang, selalu ingat paxdiablopetunjuk tentang arus lokasi target pengarahan ... Itu aku s penting.

Mnemonic pribadi saya untuk 2>&1 operator adalah ini:

  • Pikirkan & sebagai makna 'and' atau 'add' (karakternya adalah ampers-dan, bukan?)
  • Jadi itu menjadi: 'mengalihkan 2 (stderr) ke tempat 1 (stdout) sudah / saat ini adalah dan menambahkan kedua aliran '.

Pekerjaan mnemonik yang sama untuk pengalihan lain yang sering digunakan juga, 1>&2:

  • Pikirkan & berarti and atau add... (kamu mendapatkan ide tentang ampersand, ya?)
  • Jadi itu menjadi: 'mengalihkan 1 (stdout) ke tempat 2 (stderr) sudah / saat ini adalah dan menambahkan kedua aliran '.

Dan selalu ingat: Anda harus membaca rantai pengalihan 'dari akhir', dari kanan ke kiri (tidak dari kiri ke kanan).


4
2017-07-01 10:47