Kemarin saya membaca komentar SO ini yang mengatakan bahwa di shell (setidaknya bash
) >&-
“memiliki hasil yang sama dengan” >/dev/null
.
Komentar itu sebenarnya mengacu pada panduan ABS sebagai sumber informasinya. Tapi sumber itu mengatakan bahwa >&-
sintaks "menutup deskriptor file".
Tidak jelas bagi saya apakah dua tindakan menutup deskriptor file dan mengarahkannya ke perangkat nol benar-benar setara. Jadi pertanyaan saya adalah:benarkah?
Di permukaan tampaknya menutup deskriptor seperti menutup pintu tetapi mengarahkannya ke perangkat nol membuka pintu ke limbo! Keduanya tidak tampak persis sama bagi saya karena jika saya melihat pintu yang tertutup, saya tidak akan mencoba membuang apa pun darinya, tetapi jika saya melihat pintu yang terbuka, saya akan berasumsi bahwa saya bisa.
Dengan kata lain, saya selalu bertanya-tanya apakah >/dev/null
artinya cat mybigfile >/dev/null
sebenarnya akan memproses setiap byte file dan menulisnya ke /dev/null
yang melupakannya. Di sisi lain, jika shell menemukan deskriptor file tertutup, saya cenderung berpikir (tetapi saya tidak yakin) bahwa shell tidak akan menulis apa pun, meskipun pertanyaannya tetap apakah cat
akan tetap membaca setiap byte.
Komentar ini mengatakan >&-
dan >/dev/null
“harus ” sama saja, tapi itu bukan jawaban yang begitu menggema bagi saya. Saya ingin memiliki jawaban yang lebih otoritatif dengan beberapa referensi ke standar atau inti sumber atau tidak…
Jawaban yang Diterima:
Tidak, Anda pasti tidak ingin menutup deskriptor file 0, 1 dan 2.
Jika Anda melakukannya, pertama kali aplikasi membuka file, itu akan menjadi stdin/stdout/stderr…
Misalnya, jika Anda melakukannya:
echo text | tee file >&-
Ketika tee
(setidaknya beberapa implementasi, seperti busybox') membuka file untuk menulis, itu akan terbuka pada deskriptor file 1 (stdout). Jadi tee
akan menulis text
dua kali ke dalam file
:
$ echo text | strace tee file >&-
[...]
open("file", O_WRONLY|O_CREAT|O_TRUNC, 0666) = 1
read(0, "textn", 8193) = 5
write(1, "textn", 5) = 5
write(1, "textn", 5) = 5
read(0, "", 8193) = 0
exit_group(0) = ?
Itu telah diketahui menyebabkan kerentanan keamanan. Misalnya:
chsh 2>&-
Dan chsh
(aplikasi setuid) mungkin berakhir dengan menulis pesan kesalahan di /etc/passwd
.
Beberapa alat dan bahkan beberapa perpustakaan mencoba mencegahnya. Misalnya GNU tee
akan memindahkan deskriptor file ke satu di atas 2 jika file yang dibuka untuk penulisan diberi 0, 1, 2 saat busybox tee
tidak akan.
Sebagian besar alat, jika mereka tidak dapat menulis ke stdout (karena misalnya tidak terbuka), akan melaporkan pesan kesalahan pada stderr (dalam bahasa pengguna yang berarti pemrosesan ekstra untuk membuka dan mengurai file lokalisasi...), jadi itu akan secara signifikan kurang efisien, dan mungkin menyebabkan program gagal.
Bagaimanapun, itu tidak akan lebih efisien. Program masih akan melakukan write()
panggilan sistem. Itu hanya bisa lebih efisien jika program berhenti menulis ke stdout/stderr setelah write()
pertama gagal panggilan sistem, tetapi program umumnya tidak melakukan itu. Mereka biasanya keluar dengan kesalahan atau terus mencoba.