Saya baru mengenal Linux dan mencoba memahami cara kerja pengalihan.
Saya telah menguji berbagai sintaks untuk mengarahkan ulang stdout
dan stderr
ke file yang sama, yang tidak semuanya menghasilkan hasil yang sama.
Misalnya, jika saya mencoba membuat daftar 2 file yang tidak ada (file1
dan file2
) dan 2 yang melakukan (foo
dan fz
):
Sintaks #1 (tanpa pengalihan):
$ ls file1 foo fz file2
Inilah output yang saya dapatkan di terminal:
ls: cannot access file1: No such file or directory
ls: cannot access file2: No such file or directory
foo fz
Sintaks #2:
Sekarang, dengan pengalihan:
$ ls file1 foo fz file2 > redirect 2>&1
redirect
file berisi sama dengan hasil untuk Sintaks #1:
ls: cannot access file1: No such file or directory
ls: cannot access file2: No such file or directory
foo
fz
Jadi dengan kedua sintaks di atas, tampaknya shell mencetak stderr
pertama, lalu stdout
.
Sintaks #3:
Sekarang, jika saya mencoba dengan salah satu sintaks berikut:
$ ls file1 foo fz file2 > redirect 2> redirect
atau
$ ls file1 foo fz file2 2> redirect > redirect
Kemudian redirect
file akan berisi ini:
foo
fz
nnot access file1: No such file or directory
ls: cannot access file2: No such file or directory
Di sini terlihat seperti stdout
dicetak sebelum stderr
, tetapi kemudian kita melihat bahwa awal stderr
"dipotong" dengan jumlah karakter yang sama dengan stdout
.
stdout
panjangnya 6 karakter (foo fz
, carriage return termasuk), jadi 6 karakter pertama dari stderr
(ls: ca
) telah ditimpa oleh stdout
.
Jadi sepertinya stderr
dicetak terlebih dahulu, dan stdout
kemudian dicetak di atas stderr
bukannya ditambahkan ke dalamnya.
Namun, akan lebih masuk akal bagi saya jika stderr
telah sepenuhnya dihapus dan diganti dengan stdout
, bukan hanya ditipu sebagian.
Sintaks #4:
Satu-satunya cara yang saya temukan untuk memperbaiki Sintaks #3 adalah dengan menambahkan operator append ke stdout
:
$ ls file1 foo fz file2 >> redirect 2> redirect
atau
$ ls file1 foo fz file2 2> redirect >> redirect
Yang menghasilkan sama dengan Sintaks #2:
ls: cannot access file1: No such file or directory
ls: cannot access file2: No such file or directory
foo
fz
Artikel ini di sini menjelaskan bahwa Sintaks #3 salah (mungkin, begitu pula Sintaks #4). Tapi demi argumen:mengapa Sintaks #3 salah? Apa sebenarnya yang dikatakannya (atau tidak mengatakan) shell yang harus dilakukan sebagai lawan dari Sintaks #2?
Terkait:Apa perbedaan antara $(…) dan `…` di Bash?
Juga, apakah ada alasan mengapa output selalu menampilkan stderr
sebelum stdout
?
Terima kasih!
Jawaban yang Diterima:
Ini seperti menjalankan dua proses untuk menulis ke file yang sama pada saat yang sama…ide yang buruk. Anda berakhir dengan dua pegangan file terbuka yang berbeda dan data Anda bisa kacau (seperti yang terjadi pada # 3 di atas). Menggunakan sintaks #2 sudah benar; itu membuat satu menangani file dan mengarahkan stderr dan stdout ke tempat yang sama.
Adapun stderr selalu dicetak terlebih dahulu, tidak ada aturan tentang ini sama sekali. Saya curiga dengan ls
itu karena ls
perlu memeriksa setiap entri dalam direktori sebelum benar-benar dapat menyatakan bahwa file tertentu tidak ada. Jadi daripada membuat N melewati tabel direktori, itu membuat satu lintasan, memeriksa semua argumen baris perintah yang diberikan, melaporkan kesalahan, dan mencetak file yang ditemukan. Perintah lain mungkin mencetak ke stderr setelah stdout, atau bahkan bergantian di antara mereka.