Di shell Unix, jika saya ingin menggabungkan stderr
dan stdout
masuk ke stdout
stream untuk manipulasi lebih lanjut, saya bisa menambahkan berikut ini di akhir perintah saya:
2>&1
Jadi, jika saya ingin menggunakan 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 kesulitan mengingat ini, dan saya harus terus mencarinya, dan itu terutama karena saya tidak sepenuhnya mengerti sintaks dari trik khusus ini.
Dapatkah seseorang memecah ini dan menjelaskan karakter demi karakter apa 2>&1
artinya?
2>&1
daripada 2> / dev / null ;-)|&
itu singkatan untuk2>&1 |
jika Anda menggunakan zsh. Saya tidak dapat berbicara apakah itu berlaku untuk cangkang mirip bourne lain atau jika itu hanya fitur zsh.Jawaban:
Deskriptor file 1 adalah output standar (
stdout
).Deskriptor file 2 adalah kesalahan standar (
stderr
).Berikut adalah salah satu cara untuk mengingat konstruksi ini (meskipun tidak sepenuhnya akurat): pada awalnya,
2>1
mungkin terlihat seperti cara yang baik untuk mengarahkanstderr
kestdout
. Namun, itu sebenarnya akan ditafsirkan sebagai "redirectstderr
ke file yang bernama1
".&
menunjukkan bahwa yang berikut adalah deskriptor file dan bukan nama file. Jadi membangun menjadi:2>&1
.sumber
&2>&1
?&
hanya diartikan sebagai "file descriptor" dalam konteks pengalihan. Menuliscommand &2>&
diuraikan sebagaicommand &
dan2>&1
, yaitu "jalankancommand
di latar belakang, lalu jalankan perintah2
dan arahkan stdout ke stdout".2>'&1'
mengarahkan ulang stdout ke
afile.txt
. Ini sama dengan melakukanUntuk mengarahkan ulang stderr, Anda harus:
>&
adalah sintaks untuk mengalihkan aliran ke deskriptor file lain - 0 adalah stdin, 1 adalah stdout, dan 2 adalah stderr.Anda dapat mengarahkan stdout ke stderr dengan melakukan:
Atau sebaliknya:
Jadi, singkatnya ...
2>
mengarahkan ulang stderr ke file (tidak ditentukan), menambahkan&1
pengalihan stderr ke stdout.sumber
java ... 2&1 >> data.log
,, saya melihat salah satu rekan saya melakukan ini?cmd 2>&1 >> somefile.log
akan menambahkan stdout / stderr ke file - pada dasarnya sama seperti di atas, dengan>> file
menambahkancmd 2>&1 >>file
tidak mengarahkan stderr ke file, tetapicmd >> file 2>&1
melakukan. Urutan penting. Dalam kasus pertama, stderr diarahkan ke stdout shell (mungkin tty jika perintah dimasukkan secara interaktif), dan kemudian stdout diarahkan ke file. Dalam kasus kedua, stdout diarahkan ke file, dan kemudian stderr diarahkan ke tempat yang sama.0(or 1,2)>&0(or 1,2)
seperti opsi untuk mengontrol output? Apakahecho test >test.log 2>&1
samaecho test 2>&1 >test.log
?Beberapa trik tentang pengalihan
Beberapa sintaksis tertentu tentang hal ini mungkin memiliki perilaku penting. Ada beberapa sampel sedikit tentang pengalihan,
STDERR
,STDOUT
, dan argumen pemesanan .1 - Menimpa atau menambahkan?
Simbol
>
berarti pengalihan .>
berarti kirim ke sebagai keseluruhan file yang sudah selesai , timpa target jika ada (lihatnoclobber
fitur bash di # 3 nanti).>>
berarti mengirim dan menambahkan akan menargetkan jika ada.Bagaimanapun, file akan dibuat jika tidak ada.
2 - Baris perintah shell tergantung pesanan !!
Untuk menguji ini, kita memerlukan perintah sederhana yang akan mengirim sesuatu pada kedua output :
(Mengharapkan Anda tidak memiliki direktori bernama
/tnt
, tentu saja;). Baiklah, kita memilikinya !!Jadi, mari kita lihat:
Baris perintah terakhir kesedihan
STDERR
ke konsol, dan tampaknya bukan perilaku yang diharapkan ... Tapi ...Jika Anda ingin membuat beberapa pemfilteran posting tentang satu output, yang lain atau keduanya:
Perhatikan bahwa baris perintah terakhir dalam paragraf ini persis sama dengan paragraf sebelumnya, di mana saya menulis tampaknya bukan 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 :
Catatan:
&9
deskriptor akan terjadi secara spontan karena) 9>&2
.Tambahan: nota! Dengan versi barupesta(
>4.0
) ada fitur baru dan sintaksis yang lebih seksi untuk melakukan hal-hal semacam ini:Dan akhirnya untuk format output berjenjang:
Tambahan: nota! Sintaks baru yang sama, dalam dua hal:
Di mana
STDOUT
pergi melalui filter tertentu,STDERR
ke yang lain dan akhirnya kedua output digabungkan melalui filter perintah ketiga.3 - Sepatah kata tentang
noclobber
opsi dan>|
sintaksisItu tentang menimpa :
Meskipun
set -o noclobber
menginstruksikan bash untuk tidak menimpa file yang ada,>|
sintaksnya membiarkan Anda melewati batasan ini:File ditimpa setiap kali, nah sekarang:
Lewati dengan
>|
:Membatalkan pilihan ini dan / atau bertanya apakah sudah disetel.
4 - Trik terakhir dan banyak lagi ...
Untuk mengarahkan ulang kedua output dari perintah yang diberikan, kita melihat bahwa sintaks yang tepat adalah:
untuk kasus khusus ini, ada sintaks pintasan:
&>
... atau>&
Nota: jika
2>&1
ada,1>&2
adalah sintaks yang benar juga:4b- Sekarang, saya akan membiarkan Anda berpikir tentang:
4c- Jika Anda tertarik pada informasi lebih lanjut
Anda dapat membaca manual yang bagus dengan menekan:
di sebuah pesta konsol ;-)
sumber
Saya menemukan pos brilian tentang pengalihan: Semua tentang pengalihan
Mengarahkan output standar dan kesalahan standar ke file
One-liner ini menggunakan
&>
operator untuk mengalihkan aliran output - stdout dan stderr - dari perintah ke file. Ini adalah jalan pintas Bash untuk dengan cepat mengarahkan ulang kedua aliran ke tujuan yang sama.Berikut adalah tampilan tabel deskriptor file setelah Bash mengalihkan kedua stream:
Seperti yang Anda lihat, stdout dan stderr sekarang menunjuk ke
file
. Jadi apa pun yang ditulis untuk stdout dan stderr akan ditulisfile
.Ada beberapa cara untuk mengarahkan kedua aliran ke tujuan yang sama. Anda dapat mengarahkan setiap aliran satu demi satu:
Ini adalah cara yang jauh lebih umum untuk mengarahkan kedua aliran ke file. Stdout pertama diarahkan ke file, dan kemudian stderr diduplikasi sama dengan stdout. Jadi kedua aliran akhirnya menunjuk ke
file
.Ketika Bash melihat beberapa pengalihan, ia memprosesnya dari kiri ke kanan. Mari kita melalui langkah-langkah dan melihat bagaimana itu terjadi. Sebelum menjalankan perintah apa pun, tabel deskriptor file Bash terlihat seperti ini:
Sekarang Bash memproses pengalihan> file pertama. Kami telah melihat ini sebelumnya dan itu membuat stdout menunjuk ke file:
Bash Selanjutnya melihat pengalihan kedua 2> & 1. Kami belum pernah melihat pengalihan ini sebelumnya. Ini duplikat file deskriptor 2 menjadi salinan file deskriptor 1 dan kami mendapatkan:
Kedua aliran telah dialihkan ke file.
Namun hati-hati di sini! Penulisan
tidak sama dengan menulis:
Urutan pengalihan penting di Bash! Perintah ini hanya mengarahkan keluaran standar ke file. Stderr masih akan mencetak ke terminal. Untuk memahami mengapa itu terjadi, mari kita kembali ke langkah-langkahnya. Jadi sebelum menjalankan perintah, tabel deskriptor file terlihat seperti ini:
Sekarang Bash memproses pengalihan dari kiri ke kanan. Pertama melihat 2 & 1 sehingga duplikat stderr ke stdout. Tabel deskriptor file menjadi:
Sekarang Bash melihat pengalihan kedua
>file
,, dan pengalihan stdout ke file:Apakah Anda melihat apa yang terjadi di sini? Stdout sekarang menunjuk ke file, tetapi stderr masih menunjuk ke terminal! Semua yang ditulis ke stderr masih dicetak ke layar! Jadi berhati-hatilah dengan urutan pengalihan!
Perhatikan juga bahwa dalam Bash, menulis
persis sama dengan:
sumber
>&
/dev/tty0
?Angka-angka mengacu pada deskriptor file (fd).
stdin
stdout
stderr
2>&1
arahan ulang fd 2 ke 1.Ini berfungsi untuk sejumlah deskriptor file jika program menggunakannya.
Anda dapat melihat
/usr/include/unistd.h
jika Anda melupakannya:Yang mengatakan saya telah menulis alat C yang menggunakan deskriptor file non-standar untuk log kustom sehingga Anda tidak melihatnya kecuali Anda mengarahkannya ke file atau sesuatu.
sumber
Konstruk itu mengirimkan aliran kesalahan standar (
stderr
) ke lokasi saat ini dari keluaran standar (stdout
) - masalah mata uang ini tampaknya telah diabaikan oleh jawaban lain.Anda dapat mengalihkan penanganan keluaran ke yang lain dengan menggunakan metode ini, tetapi ini paling sering digunakan untuk menyalurkan
stdout
danstderr
stream ke satu aliran untuk diproses.Beberapa contoh adalah:
Perhatikan bahwa yang terakhir tidak akan mengarahkan
stderr
keoutfile2
- itu mengarahkan kembali ke apastdout
ketika argumen itu ditemui (outfile1
) dan kemudian dialihkanstdout
keoutfile2
.Ini memungkinkan beberapa tipuan yang cukup canggih.
sumber
some_program 2>&1 > /dev/null
tidak bekerja seperti ini:some_program > /dev/null 2>&1
.2>&1
adalah konstruksi shell POSIX. Berikut ini rincian, token dengan token:2
: Deskriptor file output " Standard error ".>&
: Gandakan operator Penjelasan File Keluaran (varian dari operator Pengalihan Keluaran>
). Diberikan[x]>&[y]
, deskriptor file yang dilambangkan denganx
dibuat menjadi salinan deskriptor file outputy
.1
" Standar keluaran " file output descriptor.Ekspresi
2>&1
menyalin deskriptor file1
ke lokasi2
, sehingga output apa pun ditulis ke2
("kesalahan standar") di lingkungan eksekusi pergi ke file yang sama yang awalnya dijelaskan oleh1
("output standar").Penjelasan lebih lanjut:
File Descriptor : "Integer unik non-negatif per proses yang digunakan untuk mengidentifikasi file terbuka untuk tujuan akses file."
Output / kesalahan standar : Lihat catatan berikut di bagian Redirection dari dokumentasi shell:
sumber
2 adalah kesalahan standar konsol.
1 adalah output standar konsol.
Ini adalah Unix standar, dan Windows juga mengikuti POSIX.
Misal saat Anda berlari
kesalahan standar dialihkan ke output standar, sehingga Anda dapat melihat kedua output secara bersamaan:
Setelah eksekusi, Anda dapat melihat semua output, termasuk kesalahan, di debug.log.
Kemudian output standar pergi ke out.log, dan standar error ke err.log.
Saya sarankan Anda untuk mencoba memahami ini.
sumber
perl test.pl > debug.log 2>&1
Untuk menjawab pertanyaan Anda: Dibutuhkan output kesalahan (biasanya dikirim ke stderr) dan tulis ke output standar (stdout).
Ini sangat membantu dengan, misalnya 'lebih' ketika Anda membutuhkan halaman untuk semua output. Beberapa program seperti mencetak informasi penggunaan ke dalam stderr.
Untuk membantumu mengingat
"2> & 1" hanya menunjukkan semua yang dikirim ke stderr, sebagai ganti stdout.
Saya juga merekomendasikan membaca posting ini tentang kesalahan redirect di mana subjek ini dibahas secara detail lengkap.
sumber
Dari sudut pandang seorang programmer, ini berarti persis seperti ini:
Lihat halaman manual .
Memahami itu
2>&1
adalah salinan juga menjelaskan mengapa ...... tidak sama dengan ...
Yang pertama akan mengirim kedua aliran ke
file
, sedangkan yang kedua akan mengirim kesalahanstdout
, dan output biasa kefile
.sumber
Saya menemukan ini sangat membantu jika Anda seorang pemula membaca ini
Pembaruan:
Di Linux atau Sistem Unix ada dua tempat program mengirim output ke: Output standar (stdout) dan Kesalahan Standar (stderr) . Anda dapat mengarahkan output ini ke file apa pun.
Seperti jika Anda melakukan ini, tidak
ls -a > output.txt
ada yang akan dicetak di konsol semua output (stdout) diarahkan ke file output.
Dan jika Anda mencoba mencetak konten file apa pun yang tidak keluar berarti output akan menjadi kesalahan seperti jika Anda mencetak test.txt yang tidak ada dalam direktori saat ini.
cat test.txt > error.txt
Output akan menjadi
Tetapi file error.txt akan kosong karena kami mengarahkan stdout ke file bukan stderr.
jadi kita memerlukan deskriptor file (deskriptor file tidak lebih dari bilangan bulat positif yang mewakili file terbuka. Anda dapat mengatakan deskriptor adalah id file unik) untuk memberi tahu shell jenis output yang kita kirim ke file. Di sistem Unix / Linux 1 untuk stdout dan 2 untuk stderr .
jadi sekarang jika Anda melakukan ini
ls -a 1> output.txt
berarti Anda mengirim output standar (stdout) ke output.txt.dan jika Anda melakukan ini
cat test.txt 2> error.txt
berarti Anda mengirim Standard Error (stderr) ke error.txt.&1
digunakan untuk referensi nilai deskriptor file 1 (stdout). Sekarang kamu bisa melakukan iniSekarang ke titik
2>&1
berarti "Redirect stderr ke tempat yang sama kita mengarahkan stdout"cat maybefile.txt > output.txt 2>&1
Output standar (stdout) dan Kesalahan Standar (stderr) akan dialihkan ke output.txt.
Terima kasih kepada Ondrej K. yang telah menunjukkan
sumber
Orang, selalu ingat paxdiablo petunjuk 's tentang saat lokasi target pengalihan ... Ini adalah penting.
Mnemonik pribadi saya untuk
2>&1
operator adalah ini:&
sebagai makna'and'
atau'add'
(karakternya adalah sebuah amper - dan , bukan?)2
(stderr) ke tempat1
(stdout) sudah / saat ini dan tambahkan kedua aliran' .Karya-karya mnemonic yang sama untuk pengalihan lainnya yang sering digunakan juga,
1>&2
:&
maknaand
atauadd
... (Anda mendapatkan ide tentang ampersand, ya?)1
(stdout) ke tempat2
(stderr) sudah / saat ini dan tambahkan kedua aliran' .Dan selalu ingat: Anda harus membaca rantai pengalihan 'dari akhir', dari kanan ke kiri ( bukan dari kiri ke kanan).
sumber
Ref:
Ketik
/^REDIRECT
untuk mencari keredirection
bagian tersebut, dan pelajari lebih lanjut ...Versi online ada di sini: 3.6 Pengalihan
PS:
Banyak waktu,
man
adalah alat yang ampuh untuk belajar Linux.sumber
Asalkan
/foo
tidak ada di sistem Anda dan/tmp
tidak ...akan mencetak konten
/tmp
dan mencetak pesan kesalahan untuk/foo
akan mengirim konten
/tmp
ke/dev/null
dan mencetak pesan kesalahan untuk/foo
akan melakukan hal yang persis sama (perhatikan 1 )
akan mencetak konten
/tmp
dan mengirim pesan kesalahan ke/dev/null
akan mengirim daftar dan pesan kesalahan ke
/dev/null
adalah singkatan
sumber
Ini seperti melewatkan kesalahan ke stdout atau terminal.
Artinya,
cmd
bukan perintah:Kesalahan dikirim ke file seperti ini:
Kesalahan standar dikirim ke terminal.
sumber
0 untuk input, 1 untuk stdout dan 2 untuk stderr.
One Tip :
somecmd >1.txt 2>&1
benar, sementarasomecmd 2>&1 >1.txt
benar-benar salah tanpa efek!sumber
unix_commands 2>&1
Ini digunakan untuk mencetak kesalahan ke terminal.
Berikut ini menggambarkan prosesnya
&2
"buffer" alamat memori kesalahan standar , dari mana2
referensi aliran kesalahan standar .&1
"buffer" alamat memori output output standar , dari mana1
referensi aliran output standar .Jadi ambil
unix_commands
aliran kesalahan standar2
, dan redirect>
aliran (kesalahan) ke alamat memori keluaran standar&1
, sehingga aliran tersebut akan dialirkan ke terminal dan dicetak.sumber