Dalam beberapa shell seperti Bourne, read
builtin tidak dapat membaca seluruh baris dari file di /proc
(perintah di bawah ini harus dijalankan zsh
, ganti $=shell
dengan $shell
shell lain):
$ for shell in bash dash ksh mksh yash zsh schily-sh heirloom-sh "busybox sh"; do
printf '[%s]\n' "$shell"
$=shell -c 'IFS= read x </proc/sys/fs/file-max; echo "$x"'
done
[bash]
602160
[dash]
6
[ksh]
602160
[mksh]
6
[yash]
6
[zsh]
6
[schily-sh]
602160
[heirloom-sh]
602160
[busybox sh]
6
read
standar mensyaratkan input standar perlu berupa file teks , apakah persyaratan itu menyebabkan beragam perilaku?
Baca definisi file teks POSIX , saya melakukan beberapa verifikasi:
$ od -t a </proc/sys/fs/file-max
0000000 6 0 2 1 6 0 nl
0000007
$ find /proc/sys/fs -type f -name 'file-max'
/proc/sys/fs/file-max
Tidak ada NUL
karakter dalam konten /proc/sys/fs/file-max
, dan juga find
melaporkannya sebagai file biasa (Apakah ini bug dalam find
?).
Saya kira shell melakukan sesuatu di bawah tenda, seperti file
:
$ file /proc/sys/fs/file-max
/proc/sys/fs/file-max: empty
strace
penjelasan berbasis jauh lebih mudah dimengerti!cat /proc/sys/fs/file-max | ...
, masalahnya hilang.procfs
tidak dapat menangani beberaparead(2)
panggilan berturut-turut ke file yang sama; perilaku tidak bergantung pada shell. Menggunakancat
dan memipakan karya karenacat
membaca file dalam potongan cukup besar;read
built-in shell kemudian membaca dari pipa satu karakter sekaligus.mksh
.read -N 10 a < /proc/sys/fs/file-max
zsh
:read -u0 -k10
(atau digunakansysread
;$mapfile[/proc/sys/fs/file-max]
tidak berfungsi karena file-file itu tidak dapatmmap
diedit). Dalam kasus apa pun, dengan cangkang apa pun, kita selalu bisaa=$(cat /proc/sys/fs/file-max)
. Dengan beberapa termasukmksh
,zsh
danksh93
,a=$(</proc/sys/fs/file-max)
juga berfungsi dan tidak memotong proses untuk melakukan pembacaan.Jika Anda tertarik untuk mengetahui alasannya? begitulah, Anda dapat melihat jawabannya di sumber kernel di sini :
Pada dasarnya, pencarian (
*ppos
bukan 0) tidak diterapkan untuk membaca (!write
) dari nilai sysctl yang merupakan angka. Setiap kali membaca dilakukan dari/proc/sys/fs/file-max
, rutin yang dimaksud__do_proc_doulongvec_minmax()
dipanggil dari entrifile-max
di dalam tabel konfigurasi dalam file yang sama.Entri lain, seperti
/proc/sys/kernel/poweroff_cmd
diimplementasikan melaluiproc_dostring()
yang memungkinkan pencarian, sehingga Anda dapat melakukannyadd bs=1
dan membaca dari shell Anda tanpa masalah.Perhatikan bahwa karena kernel 2.6, sebagian besar
/proc
bacaan diimplementasikan melalui API baru bernama seq_file dan ini mendukung pencarian sehingga mis. Pembacaan/proc/stat
seharusnya tidak menyebabkan masalah. The/proc/sys/
implementasi, seperti yang kita lihat, tidak menggunakan api ini.sumber
Pada upaya pertama, ini terlihat seperti bug di shell yang mengembalikan kurang dari Bourne Shell asli atau turunannya kembali (sh, bosh, ksh, heirloom).
Bourne Shell asli mencoba membaca blok (64 byte) varian Bourne Shell yang lebih baru membaca 128 byte, tetapi mereka mulai membaca lagi jika tidak ada karakter baris baru.
Latar belakang: / procfs dan implementasi serupa (misalnya
/etc/mtab
file virtual yang dipasang ) memiliki konten dinamis danstat()
panggilan tidak menyebabkan penciptaan kembali konten dinamis terlebih dahulu. Karena alasan ini, ukuran file seperti itu (dari membaca hingga EOF) mungkin berbeda dari apastat()
dikembalikan.Mengingat bahwa standar POSIX memerlukan utilitas untuk mengharapkan pembacaan pendek kapan saja, perangkat lunak yang percaya bahwa
read()
yang mengembalikan kurang dari jumlah byte yang dipesan adalah indikasi EOF yang rusak. Utilitas yang diimplementasikan dengan benar memanggilread()
kedua kalinya jika itu mengembalikan kurang dari yang diharapkan - sampai 0 dikembalikan. Dalam kasusread
builtin, tentu saja cukup untuk membaca sampaiEOF
atau sampaiNL
terlihat.Jika Anda menjalankan
truss
atau klon truss, Anda harus dapat memverifikasi perilaku yang salah untuk shell yang hanya kembali6
dalam percobaan Anda.Dalam kasus khusus ini, tampaknya itu adalah bug kernel Linux, lihat:
Kernel Linux mengembalikan 0 dengan yang kedua
read
dan ini tentu saja salah.Kesimpulan: Kerang yang pertama kali mencoba membaca sepotong data yang cukup besar tidak memicu bug kernel Linux ini.
sumber
File-file di bawah / proc kadang-kadang menggunakan karakter NULL untuk memisahkan bidang di dalam file. Tampaknya membaca tidak dapat menangani ini.
sumber