Cara pipa stderr tanpa pipa stdout

24

Bagaimana cara menyalurkan aliran kesalahan standar tanpa memompa aliran keluar standar?

Saya tahu perintah ini berfungsi, tetapi juga menuliskan standarnya.

Command 2>&1 | tee -a $LOG

Bagaimana saya mendapatkan kesalahan standar saja?

Catatan: Apa yang saya inginkan dari ini adalah hanya menulis stream stderr ke log dan menulis stderr dan stdout ke konsol.

C. Ross
sumber

Jawaban:

26

Untuk melakukan itu, gunakan satu file deskriptor tambahan untuk beralih stderr dan stdout:

find /var/log 3>&1 1>&2 2>&3 | tee foo.file

Pada dasarnya, ini bekerja, atau setidaknya saya pikir itu berfungsi, sebagai berikut:
Arahan ulang dievaluasi dari kiri ke kanan.

3>&1 Membuat deskriptor file baru, 3 duplikat (salinan) dari fd 1 (stdout).

1>&2 Jadikan stdout (1) duplikat dari fd 2 (stderr)

2>&3 Jadikan fd 2, duplikat (salinan) dari 3, yang sebelumnya membuat salinan stdout.

Jadi sekarang stderr dan stdout diaktifkan.

| tee foo.file tee duplikat file descriptor 1 yang dibuat menjadi stderr.

Kyle Brandt
sumber
Oh, tidak diuji dengan ksh, bekerja dengan pesta meskipun ...
Kyle Brandt
Terima kasih, bekerja di ksh juga. Saya pikir sebagian besar pipa dan aliran adalah standar posix.
C. Ross
"Salin" tidak benar - Lihat Jawaban @ Guasqueño.
Kyle Brandt
Ini juga bekerja di Windows dengan tee.exediinstal :)
Acorn
13

Perintah Kyle's Unix / Linux melakukan tugas mengganti STDERR dengan STDOUT; Namun penjelasannya kurang tepat. Operator pengarah ulang tidak melakukan penyalinan atau penggandaan, mereka hanya mengarahkan aliran ke arah yang berbeda.

Menulis ulang perintah Kyle dengan memindahkan sementara 3> & 1 ke akhir, akan membuatnya lebih mudah untuk memahami konsep:

find /var/log  1>&2  2>&3  3>&1  

Ditulis dengan cara ini, Linux akan menampilkan kesalahan karena & 3 belum ada karena terletak sebelum 3> & 1. 3> sesuatu adalah cara untuk menyatakan (menetapkan) bahwa kita akan menggunakan pipa ketiga, jadi itu harus ditempatkan sebelum kita mengalirkan air ke pipa itu, misalnya cara Kyle menulisnya. Coba cara lain ini hanya untuk bersenang-senang:

((echo "STD1";  anyerror "bbbb"; echo "STD2" ) 3>&1 4>&2 1>&4 2>&3) > newSTDOUT 2> newSTDERR

Tidak memiliki cara untuk melakukan salinan adalah memalukan. Anda tidak dapat melakukan hal-hal seperti "3> & 1 3> & 2" dalam perintah yang sama, karena Linux hanya akan menggunakan yang pertama ditemukan dan menolak yang kedua.

Saya belum (belum) menemukan cara untuk mengirim kesalahan dan output reguler ke file dan juga mengirim salinan kesalahan ke output standar dengan satu perintah. Untuk instace, saya memiliki tugas cron yang saya inginkan baik output (kesalahan dan standar) pergi ke file log dan biarkan kesalahan juga keluar untuk membuat pesan email yang dikirim ke blackBerry saya. Saya bisa melakukannya dengan dua perintah menggunakan "tee" tetapi kesalahan tidak muncul dalam urutan yang benar di antara garis keluaran reguler dalam file. Ini adalah cara jelek saya menyelesaikan masalah:

((echo "STD1"; sdfr "bbbb"; echo "STD2" ) 3>&1 1>&2 2>&3 | tee -a log1 ) 2>> log1

Perhatikan bahwa saya harus menggunakan log1 dua kali dan saya harus menambahkan dalam kedua kasus, yang pertama menggunakan opsi "-a" untuk perintah "tee" dan yang kedua menggunakan ">>".

Melakukan cat log1 Anda mendapatkan yang berikut:

STD1
STD2
-bash: sdfr: command not found

Perhatikan bahwa kesalahan tidak muncul di baris kedua sebagaimana mestinya.

Guasqueño
sumber
Mengagumkan koreksi!
Kyle Brandt
Lihat zsh dan mult_iosopsi (diaktifkan secara default) untuk dapat mengarahkan FD beberapa kali.
Tom Hale
2

menurut halaman manual untuk ksh (pdksh), Anda bisa melakukan:

Perintah 2> & 1> / dev / null | kucing -n

yaitu dup stderr ke stdout, redirect stdout ke / dev / null, lalu pipa ke 'cat -n'

bekerja pada pdksh di sistem saya:

$ errorecho () {echo "$ @"> & 2;}

$ errorecho foo
foo

$ errorecho foo> / dev / null # akan tetap ditampilkan walaupun dengan stdout dialihkan
foo

$ errorecho foo 2> & 1> / dev / null | kucing -n
     1 foo
$   
cas
sumber
Bekerja dengan BusyBox juga
Udo G
1

Saya menjalankannya seperti yang Anda inginkan karena saya juga membutuhkannya dan memperbaiki perintah Anda. sekarang bagi saya ini berfungsi dengan benar menggunakan bash 3.2 pada debian squeeze menggunakan ini

(echo "foo" 3>&1 1>&2 2>&3 | tee -a log1 ) 2>> log1 >> log2

sedangkan log1 log stdout dan stderr dan log2 hanya log stderr dan tidak ada lagi yang dimasukkan ke layar.

martinseener
sumber