Note that the order of redirections is significant. For example, the command
ls > dirlist 2>&1
directs both standard output and standard error to the file dirlist,
while the command
ls 2>&1 > dirlist
directs only the standard output to file dirlist, because the
standard error was duplicated from the standard output before the standard
output was redirected to dirlist.
Sekarang, bagian terakhir itu membingungkan saya. Dalam hal ini, kesalahan standar apa pun akan dicetak ke terminal dan STDOUT akan pergi ke file dirlist. Itulah yang akan terjadi, tetapi bukan itu yang saya pahami manualnya.
Sepertinya harus mengatakan "karena kesalahan standar digandakan dari output standar SETELAH output standar dialihkan ke dirlist". Jika STDERR dikirim ke STDOUT sebelum STDOUT diarahkan ke file, maka bukankah file tersebut berisi STDOUT AND STDERR?
Dapatkah seseorang tolong jelaskan ini untuk saya? Apakah pemahaman bacaan saya buruk? Penggunaan kata duplikasi agak aneh bagi saya dalam konteks ini. Mungkin itu melempar saya.
bash
shell
io-redirection
Gregg Leventhal
sumber
sumber
a = 1; b = a; a = 2
Anda berharapa == 2 && b == 1
untuk menjadi kenyataan. Pengalihan2>&1
serupa denganb = a
penugasan - itu berdasarkan nilai, bukan oleh referensi.2>&1
tidak menikahi deskriptor 2 untuk mengajukan deskriptor 1 untuk semua keabadian - mereka masih 2 deskriptor file yang berbeda, yang kebetulan mengarah ke file yang sama.Jawaban:
Duplikasi adalah bagian yang sangat penting di sini.
Mari kita lihat di mana deskriptor file akan pergi sebelum pengalihan. Ini biasanya terminal saat ini, misalnya:
Sekarang, jika kita memanggil
ls -l
tanpa pengalihan, pesan output dan kesalahan pergi ke terminal saya di bawah/dev/pts/1
.Jika pertama kali kami mengarahkan ulang
STDOUT
ke file (ls -l > dirlist
), tampilannya seperti ini:Ketika kita kemudian mengarahkan
STDERR
ke duplikat dariSTDOUT
's file descriptor (ls -l > dirlist 2>&1
),STDERR
pergi ke duplikat dari/home/bon/dirlist
:Jika kita pertama - tama akan mengarahkan ulang
STDERR
ke duplikatSTDOUT
deskriptor file (ls -l 2>&1
):dan kemudian
STDOUT
ke file (ls -l 2>&1 > dirlist
), kita akan mendapatkan ini:Di sini,
STDERR
masih menuju terminal.Anda lihat, urutan di halaman manual sudah benar.
Menguji Pengalihan
Sekarang, Anda bisa mengujinya sendiri. Dengan menggunakan
ls -l /proc/$$/fd/
, Anda melihat ke manaSTDOUT
(dengan fd 1) danSTDERR
(dengan fd 2), untuk proses saat ini:Mari kita buat skrip shell kecil yang menunjukkan di mana file penjelas Anda diarahkan. Dengan cara ini, kami selalu mendapatkan status saat memanggil
ls
, termasuk pengalihan dari shell panggilan.(Dengan CtrlD, Anda mengirim file akhir dan menghentikan
cat
perintah membaca dariSTDIN
.)Sekarang, panggil skrip ini dengan berbagai kombinasi pengalihan:
Anda dapat melihat, bahwa file deskriptor 1 (untuk
STDOUT
) dan 2 (untukSTDERR
) bervariasi. Untuk bersenang-senang, Anda juga bisa mengarahkanSTDIN
dan melihat hasilnya:(Pertanyaan tersisa untuk pembaca: Di mana file deskriptor 255 poin? ;-))
sumber
Tidak, manualnya benar.
Jika pada awalnya 1 menunjuk ke terminal, dan 2 juga ke terminal, maka:
evaluatino pengalihan akan terjadi dari kiri ke kanan.
Jadi ini akan mengevaluasi PERTAMA
2>&1
, dan dengan demikian PERTAMA menyalin apa yang1
digunakan untuk menunjuk ke fd (yaitu, deskriptor filethe terminal
, biasanya / dev / tty) ke fd2
.Jadi pada saat itu fd
2
sekarang menunjuk ke tempat fd1
dulu menunjuk ke (the terminal
)Dan MAKA mengevaluasi
1>somewhere
bagian, dan dengan demikian akan menyalin deskriptor filesomewhere
dalam fd1
(jadi pada saat itu, fd1
sekarang menunjuk kesomewhere
, dan fd2
masih menunjuk kethe terminal
)Jadi ia memang mencetak 1 menjadi "suatu tempat" dan 2 ke dalam terminal, karena 2 telah diduplikasi dari 1 SEBELUM 1 telah diubah.
Pesanan lainnya:
pertama-tama akan mengarahkan ulang fd
1
kesomewhere
, dan kemudian menyalin referensi yang sama ke fd 2, jadi pada akhir 2 juga menunjuk kesomewhere
. Tetapi mereka tidak "terhubung" mulai sekarang. Masing-masing masih dapat dialihkan secara terpisah.ex:
Pada akhir yang itu, fd
1
menunjuk kesomewhere
, dan fd2
diarahkan ke/dev/null
Nama biasa untuk fd
1
adalah STDOUT (output standar), dan nama yang biasa untuk fd2
adalah STDERR (kesalahan standar, karena ini biasanya digunakan untuk menampilkan kesalahan tanpa mengganggu STDOUT)sumber
cmd 1>somewhere 2>&1 ; exec 2>/dev/null
setelah exec, hanya 2 yang telah dialihkan ke / dev / null (1 masih akan "di suatu tempat"). Saya perlu bantuan untuk menemukan cara untuk mengatakan "apa 1 menunjuk ke" bukan "fd 1", namun ... karena itu juga membingungkan ...Saya pikir bagian yang membingungkan di sini adalah kesalahpahaman bahwa mengarahkan stderr ke stdout sebenarnya menghubungkan dua aliran.
Gagasan yang sangat masuk akal, tetapi apa yang terjadi ketika Anda menulis
2>&1
adalah stderr membutuhkan waktu lama untuk mengetahui apa yang sedang ditulis oleh stdout dan menulis ke tempat yang sama. Oleh karena itu jika Anda kemudian memberitahu stdout untuk pergi menulis di tempat lain itu tidak berpengaruh pada tujuan stderr yang sudah dipindahkan.Saya pikir ini sedikit berlawanan dengan intuisi saya sendiri tetapi itulah cara kerjanya. Atur di mana Anda ingin menulis terlebih dahulu kemudian beri tahu semua orang "salin saya". Harapan yang menjelaskan ...
sumber
DUPLIKASI...
itu penting, tetapi lebih dalam arti bahwa itu adalah sumber dari banyak kebingungan . Ini sangat sederhana. Jawaban ini hanyalah ilustrasi "radikal".
Jawaban yang diterima baik, tetapi terlalu panjang dan menekankan "duplikasi".
Q dengan bijak berakhir dengan:
Saya menggunakan notasi bash dan mendefinisikan variabel "satu" dan "dua" sebagai filehandles "1" dan "2". Operator redirection (output)
>
adalah tugas=
.&
dan$
berarti "nilai" dari.Contoh man bash (dengan default "1" ditambahkan)
menjadi:
dan
Dan bahkan ini tidak otomatis bagi saya, dan beberapa yang lain saya kira. Baris pertama memberi Anda
$one
dan$two
keduanya berisi "dirlist". Tentu saja.Baris kedua dimulai dengan tugas yang tidak berguna. Keduanya mulai dengan definisi dengan "TTY" (sedikit simbolik) sebagai arah mereka ; tidak ada nilai yang diubah oleh penugasan ini, dan dengan variabel seperti menangani file, tidak ada yang terkait secara ajaib. Variabel
two
tidak terpengaruh oleh yang berikut inione=dirlist
. Tentu saja tidak.Sombody di sini (6 tahun yang lalu) menyarankan "arahkan ke" alih-alih "salin" atau "duplikat", dan kemudian menyadari: itu akan membingungkan juga.
Duplikasi atau pointer semantik ini bahkan tidak diperlukan. Mungkin ampersand yang perlu lebih diperhatikan. "Nilai" operator / token / apa pun.
Jika - dan hanya jika - Anda mencari cara untuk mendapatkan nomor pekerjaan yang mengejutkan di konsol Anda , maka pesan "selesai" plus sebagai bonus file bernama "2", maka Anda pergi:
Bunyinya secara alami sebagai " copy" / "duplikat" 1 ke 2, dan kemudian keduanya bersama-sama menjadi nol . Tapi idenya salah, dan juga sintaksisnya. (tetapi tidak ada kesalahan sintaks, ini valid)
Cara yang tepat untuk merencanakannya adalah mengarahkan salah satu dari keduanya ke nol, dan kemudian mengarahkan LAINNYA ke tempat yang SAMA:
("1" terkemuka dapat ditinggalkan)
(OK acc. A tidak terlalu panjang, tetapi terlalu banyak daftar - atau: visualisasi yang sangat baik, penjelasan tidak begitu baik)
sumber