Mengapa output dari beberapa program Linux tidak menuju ke STDOUT atau STDERR?

21

Mengapa output dari beberapa program Linux tidak menuju ke STDOUT atau STDERR?

Sebenarnya, saya ingin tahu cara menangkap semua hasil program dengan andal, apa pun 'aliran' yang digunakannya. Masalah yang saya miliki adalah bahwa beberapa program tampaknya tidak membiarkan keluarannya ditangkap.

Contohnya adalah perintah 'waktu':

time sleep 1 2>&1 > /dev/null

real        0m1.003s
user        0m0.000s
sys         0m0.000s

atau

time sleep 1 &> /dev/null

real        0m1.003s
user        0m0.000s
sys         0m0.000s

Mengapa saya melihat output dua kali? Saya berharap semuanya bisa disalurkan ke / dev / null .

Aliran keluaran apa yang digunakan waktu, dan bagaimana saya bisa mengirimnya ke file?

Salah satu cara untuk mengatasi masalah adalah dengan membuat skrip Bash , misalnya, yang combine.shberisi perintah ini:

$@ 2>&1

Maka output dari 'waktu' dapat ditangkap dengan cara yang benar:

combine.sh time sleep 1 &> /dev/null

(tidak ada output terlihat - benar)

Apakah ada cara untuk mencapai apa yang saya inginkan tanpa menggunakan skrip gabungan terpisah?

Will Sheppard
sumber
3
pertama Anda harus membalik urutan: 2>&1 > /dev/nullberarti "2 sekarang pergi ke tempat 1 pergi (yaitu, terminal, secara default), dan kemudian 1 sekarang pergi ke / dev / null (tetapi 2 masih pergi ke terminal!). digunakan >/dev/null 2>&1untuk mengatakan "1 pergi sekarang ke / dev / null, lalu 2 pergi ke tempat 1 pergi (yaitu, juga ke / dev / null). Ini masih tidak akan berfungsi di sini karena 'waktu' bawaan tidak akan diarahkan, tetapi secara umum lebih benar (misalnya itu akan berfungsi jika Anda menggunakan / usr / bin / waktu). Pikirkan tentang "2> & 1" sebagai menyalin "arah" 1 ke dalam 2, bukan sebagai 2 menuju 1
Olivier Dulac

Jawaban:

38

Pertanyaan ini dibahas di BashFAQ / 032 . Dalam contoh Anda, Anda akan:

{ time sleep 1; } 2> /dev/null

Alasan mengapa

time sleep 1 2>/dev/null

tidak berperilaku seperti yang Anda harapkan karena dengan sintaks itu, Anda akan menginginkan timeperintah sleep 1 2>/dev/null(ya, perintah sleep 1dengan stderr diarahkan ke /dev/null). Builtin timebekerja dengan cara yang memungkinkan hal ini terjadi.

The bash builtin benar-benar dapat melakukan ini karena ... baik, itu builtin a. Perilaku seperti itu tidak mungkin dilakukan dengan perintah eksternal yang timebiasanya berlokasi di /usr/bin. Memang:

$ /usr/bin/time sleep 1 2>/dev/null
$

Sekarang, jawaban atas pertanyaan Anda

Mengapa output dari beberapa program linux tidak menggunakan STDOUT atau STDERR?

adalah: ya, outputnya pergi ke stdout atau stderr .

Semoga ini membantu!

gniourf_gniourf
sumber
2
Anda dapat membuat fd lain dan memiliki perintah dengan jelas pergi ke mereka (mis: dalam skrip bash :) exec 3>/some/file ; ls >&3 ;)
Olivier Dulac
@OlivierDulac Tentu, atau bahkan lebih sederhana dengan coprocbuiltin. Tapi itu tidak berlaku untuk timebuiltin.
gniourf_gniourf
@ gniourf-gniourf: Saya berkomentar karena kalimat Anda "outputnya menjadi stdout atau stderr" ^^
Olivier Dulac
14

Pertanyaan khusus Anda tentang timebuiltin sudah dijawab, tetapi ada yang beberapa perintah yang tidak menulis baik untuk stdoutatau stderr. Contoh klasik adalah perintah Unix crypt. crypttanpa argumen mengenkripsi input standar stdindan menulisnya ke output standar stdout. Ini meminta pengguna untuk menggunakan kata sandi getpass(), yang secara default menampilkan permintaan untuk /dev/tty. /dev/ttyadalah perangkat terminal saat ini. Menulis ke /dev/ttymemiliki efek menulis ke terminal saat ini (jika ada, lihat isatty()).

Alasannya crypttidak bisa menulis stdoutadalah karena ia menulis keluaran terenkripsi stdout. Juga, lebih baik untuk meminta /dev/ttydaripada menulis stderrsehingga jika pengguna mengalihkan stdoutdan stderr, prompt masih terlihat. (Untuk alasan yang sama, crypttidak dapat membaca kata sandi stdin, karena digunakan untuk membaca data yang akan dienkripsi.)

Alok
sumber
2
+1. Kurang relevan untuk OP, tetapi lebih relevan untuk semua orang yang datang di "Mengapa output dari beberapa program linux tidak pergi ke STDOUT atau STDERR?" via Google. :-)
ruakh
0

time sleep 1 > /dev/null 2>&1# mengarahkan ulang output "sleep" do null. Kemudian, "waktu" menulis outputnya sendiri, tanpa pengalihan. Itu seperti " time (sleep 1 > /dev/null 2>&1)".

(time sleep 1) > /dev/null 2>&1 # menjalankan "time sleep 1", lalu mengalihkan outputnya ke nol.

[] s

Márcio
sumber
-1

Masalah dalam kasus Anda adalah bahwa pengalihan berfungsi dengan cara lain. Kau menulis

time sleep 1 2>&1 > /dev/null

Ini mengarahkan ulang output standar ke /dev/nulldan kemudian mengalihkan kesalahan standar ke output standar.

Untuk mengarahkan ulang semua hasil yang Anda harus tulis

time sleep 1 > /dev/null 2>&1 

Kemudian kesalahan standar akan dialihkan ke output standar dan setelah itu semua output standar (berisi kesalahan standar) akan diarahkan ke /dev/null.

Uwe Plonus
sumber
Ini tidak berfungsi dengan bash builtin time . Lihat jawaban saya untuk beberapa penjelasan.
gniourf_gniourf
+1 karena ini adalah jawaban yang berguna untuk pertanyaan serupa. Meskipun @Olivier menjelaskannya dengan lebih baik dalam komentar untuk pertanyaan di atas.
Will Sheppard