Kemarin saya membaca komentar SO ini yang mengatakan bahwa di shell (setidaknya bash
) >&-
"memiliki hasil yang sama dengan" >/dev/null
.
Komentar itu sebenarnya merujuk pada panduan ABS sebagai sumber informasinya. Tetapi sumber itu mengatakan bahwa >&-
sintaks "menutup deskriptor file".
Tidak jelas bagi saya apakah dua tindakan menutup deskriptor file dan mengarahkannya ke perangkat nol sama sekali setara. Jadi pertanyaan saya adalah: apakah mereka?
Di permukaan itu tampaknya menutup deskriptor seperti menutup pintu tetapi mengarahkannya ke perangkat nol membuka pintu ke limbo! Keduanya tampaknya tidak persis sama bagi saya karena jika saya melihat pintu yang tertutup, saya tidak akan mencoba untuk membuang apa pun darinya, tetapi jika saya melihat pintu yang terbuka saya akan menganggap saya bisa.
Dengan kata lain, saya selalu bertanya-tanya apakah >/dev/null
cara yang cat mybigfile >/dev/null
benar-benar akan memproses setiap byte file dan menulisnya /dev/null
yang lupa. Di sisi lain, jika shell menemukan deskriptor file tertutup, saya cenderung berpikir (tapi tidak yakin) bahwa ia tidak akan menulis apa-apa, meskipun pertanyaannya tetap apakah cat
masih akan membaca setiap byte.
Komentar ini mengatakan >&-
dan >/dev/null
" harus " sama, tetapi itu bukan jawaban yang meyakinkan bagi saya. Saya ingin memiliki jawaban yang lebih berwibawa dengan beberapa referensi ke standar atau sumber inti atau tidak ...
sumber
Jawaban:
Tidak, Anda tentu 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:
Ketika
tee
(setidaknya beberapa implementasi, seperti busybox ') membuka file untuk ditulis, itu akan dibuka pada deskriptor file 1 (stdout). Jaditee
akan menulistext
dua kali menjadifile
:Itu telah diketahui menyebabkan kerentanan keamanan. Misalnya:
Dan
chsh
(aplikasi setuid) mungkin berakhir dengan menulis pesan kesalahan di/etc/passwd
.Beberapa alat dan bahkan beberapa perpustakaan mencoba untuk menjaga itu. Sebagai contoh, GNU
tee
akan memindahkan deskriptor file ke yang di atas 2 jika file yang dibuka untuk penulisan diberikan 0, 1, 2 sedangkan busyboxtee
tidak.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 pelokalan ...), 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 menyerah menulis ke stdout / stderr setelah kegagalanwrite()
sistem panggilan pertama, tetapi program umumnya tidak melakukan itu. Mereka umumnya keluar dengan kesalahan atau terus mencoba.sumber
Ini bukan jawaban lengkap untuk pertanyaan Anda, tetapi ya, di atas adalah cara kerjanya.
cat
membaca file yang dinamai, atau input standar jika tidak ada file yang dinamai, dan output ke standarnya mengeluarkan konten tersebut sampai bertemu EOF pada (termasuk input standar) file terakhir yang dinamai. Itulah yang pekerjaan.Dengan menambahkan
>/dev/null
Anda mengarahkan output standar ke / dev / null. Itu adalah file khusus (simpul perangkat) yang membuang apa pun yang tertulis di dalamnya (dan segera mengembalikan EOF saat dibaca). Perhatikan bahwa pengalihan I / O adalah fitur yang disediakan oleh shell, bukan oleh masing-masing aplikasi individual, dan bahwa tidak ada yang ajaib tentang nama / dev / null, hanya apa yang terjadi di sebagian besar sistem mirip Unix .Penting juga untuk dicatat bahwa mekanisme spesifik node perangkat bervariasi dari satu sistem operasi ke sistem operasi, tetapi cat (yang, dalam sistem GNU, berarti coreutils) adalah lintas-platform (kode sumber yang sama perlu dijalankan setidaknya di Linux dan Hurd) dan karenanya tidak dapat membawa dependensi ke kernel sistem operasi tertentu. Selain itu, ia masih berfungsi jika Anda membuat alias / dev / null (di Linux, ini berarti simpul perangkat dengan nomor perangkat utama / minor yang sama) dengan nama lain. Dan selalu ada kasus menulis di tempat lain yang berperilaku sama secara efektif (katakanlah, / dev / nol).
Ini mengikuti yang
cat
tidak mengetahui properti khusus dari / dev / null, dan memang mungkin tidak menyadari pengalihan di tempat pertama, tetapi masih perlu melakukan pekerjaan yang persis sama: membaca file yang dinamai, dan menampilkan konten dari file tersebut untuk output standarnya. Bahwa keluaran standar daricat
kekosongan bukanlah sesuatucat
yang dikhawatirkan.sumber
cat mybigfile > /dev/null
akan menyebabkancat
membaca setiap bytebigfile
ke dalam memori. Dan, untuk setiapn
byte, itu akan memanggilwrite(1, buffer, n)
. Tanpa diketahuicat
program,write
akan melakukan apa-apa (kecuali mungkin untuk beberapa pembukuan sepele). Menulis ke/dev/null
tidak memerlukan pemrosesan setiap byte.cat
ataucp
yang akan bekerja denganmmap
memasukkan potongan besar file sumber ke dalam memori, kemudian memanggilwrite()
wilayah yang dipetakan. Jika Anda menulis/dev/null
surat kepada ,write()
panggilan akan kembali sekaligus tanpa kesalahan pada halaman file sumber, sehingga tidak akan pernah benar-benar dibaca dari disk.cat
berjalan pada banyak platform, tetapi pandangan sekilas pada kode sumber akan menunjukkan banyak#ifdef
s: itu bukan kode yang sama yang berjalan pada semua platform, dan ada banyak bagian yang bergantung pada sistem.