Server kami baru-baru ini kehabisan file deskriptor, dan sehubungan dengan itu saya punya beberapa pertanyaan. ulimit -n
seharusnya memberi saya jumlah maksimum deskriptor file terbuka. Angka itu adalah 1024. Saya memeriksa jumlah deskriptor file terbuka dengan menjalankan lsof -u root |wc -l
dan mendapat 2500 fds. Itu jauh lebih dari 1024, jadi saya kira itu berarti angka 1024 adalah per proses, bukan per pengguna, seperti yang saya kira. Yah, saya berlari lsof -p$PidOfGlassfish|wc -l
dan mendapatkan 1300. Ini adalah bagian yang tidak saya dapatkan. Jika ulimit -n
bukan jumlah maksimum proses per pengguna atau per proses, lalu apa untungnya? Apakah itu tidak berlaku untuk pengguna root? Dan jika demikian, bagaimana saya bisa mendapatkan pesan kesalahan tentang kehabisan file descriptor?
EDIT: Satu-satunya cara saya bisa masuk akal ulimit -n
adalah jika itu berlaku jumlah file yang terbuka (sebagaimana dinyatakan dalam manual bash) daripada jumlah menangani file (proses yang berbeda dapat membuka file yang sama). Jika ini masalahnya, maka cukup cantumkan jumlah file yang terbuka (memahami '/', sehingga tidak termasuk file yang dipetakan memori) tidak cukup:
lsof -u root |grep /|sort -k9 |wc -l #prints '1738'
Untuk benar-benar melihat jumlah file yang terbuka, saya perlu memfilter pada kolom nama hanya mencetak entri unik. Jadi, yang berikut ini mungkin lebih benar:
lsof -u root |grep /|sort -k9 -u |wc -l #prints '604'
Perintah di atas mengharapkan output pada format berikut dari lsof:
java 32008 root mem REG 8,2 11942368 72721 /usr/lib64/locale/locale-archive
vmtoolsd 4764 root mem REG 8,2 18624 106432 /usr/lib64/open-vm-tools/plugins/vmsvc/libguestInfo.so
Setidaknya ini memberi saya nomor kurang dari 1024 (angka yang dilaporkan oleh ulimit -n
), jadi ini sepertinya langkah ke arah yang benar. "Sayangnya" Saya tidak mengalami masalah dengan kehabisan deskriptor file, jadi saya akan kesulitan memvalidasi ini.
sumber
Jawaban:
Saya menguji ini di Linux versi 2.6.18-164.el5 - Red Hat 4.1.2-46. Saya bisa melihat bahwa ulimit diterapkan per proses.
Parameter ditetapkan pada tingkat pengguna, tetapi diterapkan untuk setiap proses.
Misalnya: 1024 adalah batasnya. Beberapa proses dimulai dan file yang dibuka oleh masing-masing dihitung menggunakan
Tidak ada kesalahan ketika jumlah file dibuka oleh beberapa proses melewati 1024. Saya juga memverifikasi jumlah file unik yang menggabungkan hasil untuk proses yang berbeda dan menghitung file unik. Kesalahan mulai muncul hanya ketika jumlah untuk setiap proses melewati 1024. (java.net.SocketException: Terlalu banyak file yang terbuka di log proses)
sumber
lsof -p$PidOfGlassfish|wc -l
memberi saya 1300? Saya menduga dua pendekatan untuk penghitungan berbeda. Jika tidak, maka mungkin batasnya tidak berlaku untuk pengguna root?ls -l
bukanls
? Yang terakhir memiliki baris tambahan (mis.total 5
) Ketika ada 5 file. Dalam kasus seperti menggunakanls -l
contoh di atas akan melaporkan 6 tidak 5. Saya menggunakanls /proc/<pid>/fd | wc -l
.ls -l
memberi saya satu entri per baris, yang kemudian saya pipa menjadi sesuatu yang lain. Tentu saja, ini juga terjadi ketika perpipaan normalls
(tetapi tidak sebaliknya).Ulimit adalah untuk menangani file. Ini berlaku untuk file, direktori, soket, epoll pipa, eventfds, timerfds dll.
Kapan saja selama proses startup batas mungkin telah diubah. Kunjungi
/proc/<pid>/limits
dan lihat apakah nilainya telah diubah.sumber
@oligofren
Saya juga dilakukan beberapa pengujian untuk menentukan bagaimana
"ulimits -Sn"
untuk"open files"
diberlakukan.Seperti poster yang dipilih dalam tautan , ulimit untuk
"open files"
memang diterapkan per proses. Untuk melihat batas proses saat ini:cat /proc/__process_id__/limits
Untuk menentukan berapa banyak file yang telah dibuka suatu proses, Anda perlu menggunakan perintah berikut:
lsof -P -M -l -n -d '^cwd,^err,^ltx,^mem,^mmap,^pd,^rtd,^txt' -p __process_id__ -a | awk '{if (NR>1) print}' | wc -l
Penjelasan di atas dan metode / hasil pengujian saya
The
"-P -M -l -n"
argumen untuk lsof hanya ada untuk membuat lsof beroperasi secepat mungkin. Jangan ragu untuk mengeluarkannya.The
"-d '^cwd,^err,^ltx,^mem,^mmap,^pd,^rtd,^txt'"
menginstruksikan argumenlsof
untuk mengecualikan file deskriptor dari jenis: cwd / err / LTX / mem / mmap / pd / RTD / txt.Dari halaman manual lsof:
Saya dianggap
"Lnn,jld,m86,tr,v86"
tidak berlaku untuk Linux dan karenanya tidak repot-repot menambahkannya ke daftar pengecualian. Saya tidak yakin tentang itu"Mxx"
.Jika aplikasi Anda menggunakan file / perangkat yang dipetakan memori maka Anda mungkin ingin menghapus
"^mem"
dan"^mmap"
dari daftar pengecualian.Sunting --- mulai snip ---
Sunting: Saya menemukan tautan berikut yang menunjukkan bahwa:
Jadi, jika proses Anda menggunakan file yang dipetakan memori, Anda perlu memfilter file * .so.
Juga, Sun's JVM akan memetakan file jar
Jadi hal-hal seperti tomcat / glassfish juga akan menampilkan file jar yang dipetakan memori. Saya belum menguji apakah ini masuk dalam
"ulimit -Sn"
batas.EDIT --- end snip ---
Secara empiris, saya telah menemukan bahwa
"cwd,rtd,txt"
yang tidak dihitung berkaitan dengan per proses batas file (ulimit -sN).Saya tidak yakin apakah
"err,ltx,pd"
dihitung terhadap batas file karena saya tidak tahu cara membuat file menangani jenis deskriptor ini.The
"-p __process_id__"
Membatasi argumenlsof
hanya kembali informasi untuk__process_id__
ditentukan. Hapus ini jika Anda ingin mendapatkan hitungan untuk semua proses.The
"-a"
argumen digunakan untuk DAN pada pilihan (yaitu "p" dan "d" argumen).The
"awk '{if (NR>1) print}'"
pernyataan digunakan untuk melewatkan header yanglsof
cetakan dalam output.Saya diuji menggunakan skrip perl berikut:
Saya harus menjalankan skrip dalam perl debugger untuk memastikan skrip tidak berhenti dan merilis file deskriptor.
Untuk mengeksekusi:
perl -d test.pl
Di debugger perl, Anda dapat menjalankan program dengan memasukkan
c
dan menekan enter dan jika Andaulimit -Sn
memiliki nilai 1024 , Anda akan menemukan bahwa program berhenti setelah membuatTest1017.log
file masuk/tmp
.Jika sekarang Anda mengidentifikasi pid dari proses perl dan menggunakan
lsof
perintah di atas Anda akan melihat bahwa itu juga menghasilkan 1024 .Hapus
"wc -l"
dan ganti dengan"less"
untuk melihat daftar file yang dihitung menuju batas 1024 . Hapus"-d ^....."
argumen juga untuk melihat bahwacwd,txt
danrtd
deskriptor tidak masuk dalam batas.Jika Anda sekarang menjalankan
"ls -l /proc/__process_id__/fd/ | wc -l"
, Anda akan melihat nilai 1025 dikembalikan. Ini karenals
menambahkan"total 0"
header ke outputnya yang dihitung.catatan:
Untuk memeriksa apakah OS kehabisan deskriptor file, lebih baik membandingkan nilai:
cat /proc/sys/fs/file-nr | awk '{print $1}'
dengan
cat /proc/sys/fs/file-max
https://www.kernel.org/doc/Documentation/sysctl/fs.txt mendokumentasikan apa
file-nr
danfile-max
artinya.sumber
Sepertinya alasanmu adalah seperti, "Aku harus menurunkan batas itu jadi aku tidak kehabisan deskriptor yang berharga". Yang benar adalah sebaliknya - jika server Anda kehabisan file deskriptor, Anda perlu menaikkan batas dari 1.024 ke sesuatu yang lebih besar. Untuk
glassfish
implementasi yang realistis , 32.768 masuk akal.Secara pribadi, saya selalu menaikkan batas menjadi sekitar 8.192 sistem - 1.024 hanya konyol. Tetapi Anda ingin menaikkan
glassfish
lebih tinggi. Periksa/etc/security/limits.conf
. Anda dapat menambahkan entri khusus untukglassfish
berjalan pengguna sebagai.sumber
Anda ingin melihat batas seluruh sistem yang diatur di / proc / sys / fs / file-max dan sesuaikan di sana (hingga reboot berikutnya) atau set fs.file-max di sysctl.conf untuk membuatnya permanen. Ini mungkin membantu - http://www.randombugs.com/linux/tuning-file-descriptors-limits-on-linux.html
sumber
Kesalahan umum untuk membandingkan hasil panggilan lsof mentah dengan batas yang seharusnya.
Untuk batas global (/ proc / sys / fs / file-max) Anda harus melihat / proc / sys / fs / file-nr -> nilai fist menunjukkan apa yang digunakan dan nilai terakhir adalah batas
Batas OpenFile adalah untuk setiap proses tetapi dapat didefinisikan pada pengguna, lihat perintah "ulimit -Hn" untuk batas pengguna dan lihat /etc/security/limits.conf untuk definisi. Umumnya diterapkan dengan "pengguna aplikasi" misalnya: "kucing jantan": tetapkan batas hingga 65000 untuk kucing jantan pengguna yang akan berlaku pada proses java yang dijalankannya.
Jika Anda ingin memeriksa batas yang diterapkan pada suatu proses, dapatkan PID-nya dan kemudian: cat / proc / $ {PID} / limit Jika Anda ingin memeriksa berapa banyak file yang dibuka oleh suatu proses, dapatkan PID-nya dan kemudian: ls -1 / proc / {PID} / fd | wc-l (catatan untuk ls 'minus satu', bukan untuk berbaur dengan 'minus el')
Jika Anda ingin mengetahui detail dengan lsof tetapi hanya untuk penangan file yang menghitung batas, cobalah dengan thoses: lsof -p $ {PID} | grep -P "^ (\ w + \ s +) {3} \ d + \ D +" lsof -p $ {PID} -d '^ cwd, ^ err, ^ ltx, ^ mem, ^ mmap, ^ pd, ^ rtd, ^ txt '-a
Catatan: 'file' adalah file / pipa / koneksi tcp / dll.
Perhatikan bahwa kadang-kadang Anda mungkin harus melakukan root atau menggunakan sudo untuk mendapatkan hasil yang benar untuk perintah, tanpa hak istimewa kadang-kadang Anda tidak memiliki kesalahan, hanya sedikit hasil.
dan akhirnya jika Anda ingin tahu apa 'file' pada sistem file Anda diakses oleh suatu proses, lihat: lsof -p {PID} | grep / | awk '{print $ 9}' | sortir | uniq
Selamat bersenang-senang !
sumber