Kök tarafından kullanılan açık dosya tanımlayıcılarının sayısı neden ulimit -n'yi aşıyor?


13

Sunucumuz yakın zamanda dosya tanımlayıcıları bitti ve bununla ilgili bazı sorularım var. ulimit -nbana maksimum sayıda açık dosya tanımlayıcı vermesi gerekiyor. Bu sayı 1024'tür. Açık dosya tanımlayıcılarının sayısını çalıştırarak kontrol ettim lsof -u root |wc -lve 2500 fds aldım. Bu 1024'ten çok daha fazla, bu yüzden sanırım 1024 sayısının kullanıcı başına değil, işlem başına olduğu anlamına gelir. Eh, koştum lsof -p$PidOfGlassfish|wc -lve bu anlayamadığım parçasıdır 1300. aldık. Eğer ulimit -nkullanıcı başına veya sürecin başına süreci sayısı değil o zaman için iyi nedir? Kök kullanıcı için geçerli değil mi? Ve eğer öyleyse, dosya tanımlayıcısının bitmesiyle ilgili hata mesajlarını nasıl alabilirim?

EDIT: Anlamsız tek yolu ulimit -n, dosya tanıtıcı sayısı (farklı işlemler aynı dosyayı açabilirsiniz) yerine açık dosya sayısını (bash kılavuzda belirtildiği gibi) uygular. Bu durumda, açık dosya sayısını listelemek ('/' üzerinde selamlamak, böylece bellek eşlenmiş dosyaları hariç tutmak) yeterli değildir :

lsof -u root |grep /|sort  -k9  |wc -l #prints '1738'

Aslında açık dosya sayısını görmek için, yalnızca benzersiz girişleri yazdırırken ad sütununa filtre uygulamam gerekir. Dolayısıyla aşağıdakiler muhtemelen daha doğrudur:

lsof -u root |grep /|sort  -k9 -u |wc -l #prints '604'

Yukarıdaki komut lsof'dan aşağıdaki formatta çıktı bekler:

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

Bu en azından 1024'ten (rapor edilen sayı) daha az bir sayı veriyor ulimit -n, bu yüzden doğru yönde bir adım gibi görünüyor. "Maalesef" Dosya tanımlayıcılarının bitmesi konusunda herhangi bir sorun yaşamıyorum, bu yüzden bunu doğrulamakta zorlanacağım.


2
lsof, bellek eşlemelerini ve açık dosyaları rapor eder, böylece 'wc' boru hattınız bu işlem tarafından kullanılan dosya tanımlayıcılarının sayısının fazla bir tahminini verir.
Richard Kettlewell

Aha! şimdi bu iyi bir bilgi. Ama anladığımdan emin değilim. "Bellek eşlemeleri" ile, bellek eşlemeli bir dosya mı demek istiyorsunuz? Bu benim anlayışım için bir dosya tanıtıcı gerektirir, ya da işletim sistemi dosyayı başka nasıl güncelleyebilir?
oligofren

Ve ikinci takip: Tüm açık dosya tanıtıcılarını bulmanın iyi bir yolu ne olabilir - aslında "ulimit -n" tarafından uygulanan sınırlardan etkilenenler?
oligofren

1
Bellek eşlemeleri için açık bir dosya gerekmez. Yalnızca açık dosyaları listelemek istiyorsanız, lsof çıktısına filtre uygulamak muhtemelen en kolay yaklaşımdır.
Richard Kettlewell

Teşekkürler, cevabımı düzenledi. ´lsof -u root | grep / | sort -k9 -u´ kullanmak makul bir cevaba ne kadar değer veriyor gibi görünüyor. Bu, ulimit -n'den en az bir sayıdır.
oligofren

Yanıtlar:


9

Bunu Linux sürüm 2.6.18-164.el5 - Red Hat 4.1.2-46'da test ettim. Ulimit'in işlem başına uygulandığını görebiliyordum.

Parametre kullanıcı düzeyinde ayarlanır, ancak her işlem için uygulanır.

Örn: 1024 sınırdı. Birden çok işlem başlatıldı ve her biri tarafından açılan dosyalar kullanılarak sayıldı

ls -l /proc/--$pid--/fd/ | wc -l

Birden çok işlem tarafından açılan dosyaların toplamı 1024'ü geçtiğinde hata oluşmadı. Ayrıca, farklı işlemler için sonuçları birleştiren ve benzersiz dosyaları sayan benzersiz dosya sayısını da doğruladım. Hatalar yalnızca her işlem için sayı 1024'ü geçtiğinde görünmeye başladı. (Java.net.SocketException: İşlem günlüklerinde çok fazla açık dosya var)


Bunu test ettiğiniz için teşekkürler. lsof -p$PidOfGlassfish|wc -lBana neden 1300 verdiğine dair bir fikrin var mı? Saymaya yönelik iki yaklaşımın bir şekilde farklı olduğunu tahmin ediyorum. Değilse, belki sınır kök kullanıcı için geçerli değildir?
oligofren

Sadece merak ediyorum, neden kullanmak ls -lyerine ls? İkincisi total 55 dosya olduğunda fazladan bir satıra (ör. ) Sahiptir. Böyle bir durumda ls -l yukarıdaki örnekte kullanım 5 değil rapor 6 olacaktır ls /proc/<pid>/fd | wc -l.
starfry

@starfry Bu benim açımdan sadece zulüm. Bunu genellikle adım adım yapıyorum ve ls -lher satıra bir giriş veriyorum, daha sonra başka bir şeye geçiyorum. Cours arasında, bu normal borulama sırasında da olur ls(aksi halde hayır).
oligofren

3

Ulimit eğe sapları içindir. Dosyalar, dizinler, prizler, boru epolleri, eventfds, timerfds vb. İçin geçerlidir.

İşlemlerin başlatılması sırasında herhangi bir noktada limitler değişmiş olabilir. Ziyaret edin /proc/<pid>/limitsve değerlerin değiştirilip değiştirilmediğine bakın.


3

@oligofren

Ayrıca nasıl uygulandığını belirlemek "ulimits -Sn"için bazı testler yaptım "open files".

  • Poster gibi Seçilmiş belirtilen bağlantı için Ulimit "open files"gerçekten sürecin başına kullanılır. Sürecin mevcut sınırlarının ne olduğunu görmek için:

    cat /proc/__process_id__/limits

  • Bir işlemin kaç dosya açtığını belirlemek için aşağıdaki komutu kullanmanız gerekir:

    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

Yukarıdakilerin ve test yöntemimin / sonuçların açıklaması

"-P -M -l -n"İçin argümanlar lsof yapmak basitçe vardır lsof mümkün olduğunca hızlı çalışır. Onları çıkarmaktan çekinmeyin.

-P - inhibits the conversion of port numbers to port names for network files
-M - disable reporting of portmapper registrations for local TCP, UDP and UDPLITE ports
-l - inhibits the conversion of user ID numbers to login names
-n - inhibits the conversion of network numbers to host names for network files

"-d '^cwd,^err,^ltx,^mem,^mmap,^pd,^rtd,^txt'"Argüman talimatını lsofÇeşidi dosya tanımlayıcıları dışlamak için: cwd / err / LTX'e / mem / mmap / pd / rtd / txt.

Lsof man sayfasından:

   FD         is the File Descriptor number of the file or:

                   cwd  current working directory;
                   Lnn  library references (AIX);
                   err  FD information error (see NAME column);
                   jld  jail directory (FreeBSD);
                   ltx  shared library text (code and data);
                   Mxx  hex memory-mapped type number xx.
                   m86  DOS Merge mapped file;
                   mem  memory-mapped file;
                   mmap memory-mapped device;
                   pd   parent directory;
                   rtd  root directory;
                   tr   kernel trace file (OpenBSD);
                   txt  program text (code and data);
                   v86  VP/ix mapped file;

"Lnn,jld,m86,tr,v86"Linux için geçerli olmadığını düşündüm ve bu nedenle bunları hariç tutma listesine eklemek için uğraşmadım. Emin değilim "Mxx".

Uygulamanız bellek eşlemeli dosyaları / cihazları kullanıyorsa , hariç tutma listesinden "^mem"ve "^mmap"listeden çıkarmak isteyebilirsiniz .

DÜZENLEME --- snip başlat ---

Düzenleme: Bunu gösteren aşağıdaki bağlantı bulundu :

bellek eşlenen .so dosyaları teknik olarak uygulamanın kontrol ettiği bir dosya tanıtıcısı ile aynı değildir. / proc // fd açık dosya tanımlayıcıları için ölçüm noktasıdır

İşleminiz bellek eşlemeli dosyalar kullanıyorsa, * .so dosyalarını filtrelemeniz gerekir.

Ayrıca, Sun'ın JVM'si harita jar dosyalarını hafızaya alacak

Bellek eşlemeli JARfile, bu durumda "JDK sınıflarını" tutan dosya. Bir JAR'ı bellek eşlediğinizde, içindeki dosyalara çok verimli bir şekilde erişebilirsiniz (her seferinde başlangıçtan okumak yerine). Sun JVM, sınıf yolundaki tüm JAR'ları bellekle eşler; uygulama kodunuzun bir JAR'a erişmesi gerekiyorsa, bunu bellek eşlemesiyle de eşleştirebilirsiniz.

Böylece tomcat / glassfish gibi şeyler de bellek eşlemeli jar dosyalarını gösterecektir. Bunların sınıra doğru olup olmadığını test etmedim "ulimit -Sn".

DÜZENLEME --- son snip ---

Ampirik olarak, ben fark ettik "cwd,rtd,txt"vardır sayılmaz sürecin başına dosya sınırı açısından (Ulimit -Sn) ile.

"err,ltx,pd"Bu tanımlayıcı türlerinin dosya tanıtıcılarını nasıl oluşturacağımı bilmediğim için dosya sınırına dahil olup olmadığından emin değilim .

"-p __process_id__"Argümanı kısıtlar lsofyalnızca bilgi döndürmek için __process_id__belirtilmedi. Tüm işlemler için bir sayım almak istiyorsanız bunu kaldırın.

Bağımsız "-a"değişken AND seçimlerine (yani "-p" ve "-d" bağımsız değişkenlerine) kullanılır.

"awk '{if (NR>1) print}'"Açıklamada, başlığını geçmek için kullanılır lsofçıktıda baskılar.

Aşağıdaki perl betiği kullanarak test ettim:

File: test.pl
---snip---
#!/usr/bin/perl -w
foreach $i (1..1100) {
  $FH="FH${i}";
  open ($FH,'>',"/tmp/Test${i}.log") || die "$!";
  print $FH "$i\n";
}
---snip---

Komut dosyasının sonlandırılmasını ve dosya tanımlayıcılarını serbest bırakmamasını sağlamak için perl hata ayıklayıcısında komut dosyasını yürütmek zorunda kaldım.

Yürütmek için: perl -d test.pl

Perl hata ayıklayıcısında, center girip tuşuna basarak programı çalıştırabilirsiniz ve 1024ulimit -Sn değeriniz varsa , dosyayı oluşturduktan sonra programın durduğunu göreceksiniz .Test1017.log/tmp

Şimdi perl işleminin pid'ini belirlerseniz ve yukarıdaki lsofkomutu kullanırsanız, bunun da 1024 çıktısı verdiğini göreceksiniz .

Kaldır "wc -l"ve değiştirin "less"sayılır dosyaların listesini görmek için 1024 sınırı. Kaldır "-d ^....."görmek için de argüman cwd,txtve rtdtanımlayıcılar vermedi limitine sayılır.

Şimdi koşarsanız "ls -l /proc/__process_id__/fd/ | wc -l", 1025 değerinin döndürüldüğünü görürsünüz . Bunun nedeni , çıktısına sayılan lsbir "total 0"üstbilgi eklemesidir .

Not:

İşletim sisteminin dosya tanımlayıcılarının tükenip tükenmediğini kontrol etmek için aşağıdakilerin değerini karşılaştırmak daha iyidir :

cat /proc/sys/fs/file-nr | awk '{print $1}'

ile

cat /proc/sys/fs/file-max

https://www.kernel.org/doc/Documentation/sysctl/fs.txt neyi file-nrve ne file-maxanlama geldiğini belgeler .


0

Muhakemenizin "Bu sınırı düşürmem gerekiyor, bu yüzden değerli tanımlayıcılarım tükenmiyor" gibi bir şey gibi görünüyor. Gerçek şu ki tam tersi - sunucunuzda dosya tanımlayıcıları kalmadıysa, bu sınırı 1.024'ten daha büyük bir şeye yükseltmeniz gerekir . Gerçekçi bir glassfishuygulama için 32.768 makuldür.

Şahsen, her zaman sınırı sistem genelinde 8.192'ye yükseltiyorum - 1.024 sadece saçma. Ama glassfishdaha yükseğe çıkmak isteyeceksin . Kontrol edin /etc/security/limits.conf. Olarak glassfishçalışan kullanıcı için özel bir giriş ekleyebilirsiniz .


Beni nasıl ifade edebileceğinizden emin değilim :-) Merak ettiğim şey neden uygulanmadığıydı. Daha yükseğe koyacağım, ama nasıl çalıştığını da anlamak istiyorum. Sınır 1024 ise, Glassfish'in 1300 tutamağı nasıl olabilir?
oligofren

'lsof -u root | grep / | sort -k9 -u' benzersiz dosya tanımlayıcı girdilerini yazdırır. Sanırım bundan satır sayısı ulimit -n için geçerli gerçek sayıdır.
oligofren

0

/ Proc / sys / fs / file-max içinde ayarlanan sistem genelindeki sınırlara bir göz atmak ve kalıcı olarak ayarlamak için orada (bir sonraki yeniden başlatmaya kadar) ayarlamak veya ss.ctl.conf dosyasında fs.file-max değerini ayarlamak istersiniz. Bu yardımcı olabilir - http://www.randombugs.com/linux/tuning-file-descriptors-limits-on-linux.html


1
Bash hakkındaki bu yorum doğru değil. ulimit, kabuk yoluyla başlatılan işlemler için kullanıcı kimliği başına bir sınır kümesi uygular; bu, işlem ağacının Unix benzeri işletim sistemlerinde nasıl ortaya çıktığı sayesinde esasen her şeydir. Bu bash değil.
EightBitTony

Üzgünüz - düzenleyecek, ancak sistem geniş sınırları hakkında yorum hala geçerli.
rnxrx

Sistemin geniş sınırlarına ulaşması pek olası değildir. Mümkün ama çok olası değil.
David Schwartz

EightBitTony: ulimit, kullanıcı kimliği sınır kümesi başına ulimit ayarlamaz. Pam_limits uygulandığında işlem başına. "Kullanıcı başına" olan ulimit, "ulimit -u" dir. "Tek bir kullanıcı için kullanılabilir maksimum işlem sayısı"
Kullanıcı Adı Yok

0

Ham lsof çağrısının sonucunu varsayılan limitle karşılaştırmak için yaygın hata.

Genel sınır (/ proc / sys / fs / file-max) için / proc / sys / fs / file-nr -> 'ya yumruk değeri ne kullanıldığını gösterir ve son değer sınırdır

OpenFile sınırı her işlem içindir, ancak kullanıcı üzerinde tanımlanabilir, kullanıcı sınırları için "ulimit -Hn" komutuna bakın ve tanımlar için /etc/security/limits.conf dosyasına bakın. Genellikle "uygulama kullanıcısı" ile uygulanır. Örneğin: "tomcat": çalıştırdığı java işleminde uygulanacak kullanıcı tomcat için sınırı 65000 olarak ayarlayın.

Bir işleme uygulanan sınırı denetlemek istiyorsanız, PID'sini alın ve sonra: cat / proc / $ {PID} / limitleri Bir işlem tarafından kaç dosyanın açıldığını kontrol etmek istiyorsanız, PID'sini alın ve sonra: ls -1 / proc / {PID} / fd | wc -l ('eksi bir' olduğuna dikkat edin, 'eksi el' ile karıştırmamak)

Lsof ile ayrıntıları öğrenmek istiyorsanız, ancak yalnızca sınır için geçerli olan dosya işleyicileri için, şu öğeleri deneyin: lsof -p $ {PID} | grep -P "^ (\ w + \ s +) {3} \ d + \ D +" lsof -p $ {PID} -d '^ cwd, ^ err, ^ ltx, ^ mem, ^ mmap, ^ pd, ^ rtd, ^ txt '-a

Not: 'dosyalar' dosyalar / boru / tcp bağlantıları / vb.

Bazen muhtemelen root olmanız veya komutlar için doğru sonuç elde etmek için sudo kullanmanız gerekeceğini, bazen ayrıcalık olmadan hatanızın olmadığını, sadece daha az sonucun olacağını unutmayın.

ve son olarak dosya sisteminizdeki 'dosyalara' bir işlem tarafından erişildiğini bilmek istiyorsanız, şunlara bir göz atın: lsof -p {PID} | grep / | awk '{print $ 9}' | sırala | uniq

iyi eğlenceler !

Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.