כיצד לתקן את השגיאה 'יותר מדי קבצים פתוחים' בלינוקס


לעתים קרובות מתרחשות שגיאות 'יותר מדי קבצים פתוחים' בשרתי לינוקס בעלי עומס גבוה. משמעות הדבר היא שתהליך פתח קבצים רבים מדי (מתארי קבצים) ואינו יכול לפתוח קבצים חדשים. בלינוקס, "מגבלת הקובץ הפתוח המקסימלית" נקבעת כברירת מחדל לכל תהליך או משתמש והערכים קטנים למדי.

במאמר זה, נבחן כיצד לבדוק את המגבלות הנוכחיות על המספר המרבי של קבצים פתוחים ב- Linux, וכיצד לשנות הגדרה זו באופן גלובלי עבור השרת כולו, עבור שירותים ספציפיים ועבור הפעלת משתמש. המאמר ישים לרוב מפיצי לינוקס המודרניים (דביאן, אובונטו, CentOS, RHEL, Oracle Linux, Rocky וכו ')

שגיאת 'יותר מדי קבצים פתוחים' ומגבלת קבצים פתוחים בלינוקס

קודם כל, בואו נראה היכן מופיעות שגיאות 'יותר מדי קבצים פתוחים'. לרוב זה קורה בשרתים עם שרת אינטרנט מותקן Nginx/httpd או שרת מסד נתונים המריץ MySQL/MariaDB/PostgreSQL בעת קריאת מספר רב של קבצי יומן. לדוגמה, כאשר Nginx חורג ממגבלת הקבצים הפתוחים, תראה שגיאה:

socket () failed (29: Too many open files) while connecting to upstream

או:

HTTP: Accept error: accept tcp [::]:<port_number>: accept4: too many open files.

באפליקציות Python:

OSError: [Errno 24] Too many open files.

באמצעות פקודה זו, באפשרותך לקבל את המספר המרבי של מתארי קבצים שהמערכת שלך יכולה לפתוח:

# cat /proc/sys/fs/file-max

כדי לברר כמה קבצים פתוחים כעת, הפעל:

# cat /proc/sys/fs/file-nr
7122    123      92312720
  • 7122 — המספר הכולל של קבצים פתוחים

  • 123 - מספר הקבצים הפתוחים שאינם בשימוש כרגע

  • 92312720 - מספר התיקים המרבי המותר לפתיחה

בלינוקס, ניתן להגדיר מגבלות מקסימום של קבצים פתוחים בכמה רמות:

  • ליבת מערכת ההפעלה

  • שירות

  • משתמש

כדי להציג את המגבלה הנוכחית על מספר הקבצים הפתוחים בליבת Linux, הפעל:

sysctl fs.file-max
fs.file-max = 92233720

בוא נציג את מגבלת הקבצים הפתוחים עבור תהליך אחד של המשתמש הנוכחי:

# ulimit -n

כברירת מחדל, מספר הקבצים עבור תהליך אחד של תהליך זה מוגבל ל- 1024.

בוא נציג את המספר המרבי עבור משתמש אחד (מקסימום תהליכי משתמש):

# ulimit -u
5041

הכפלת

1024 * 5041

נותן לנו

5161984

- זהו המספר המרבי של קבצים פתוחים על ידי כל תהליכי המשתמש.

קיימים שני סוגים של מגבלות על מספר הקבצים הפתוחים: קשה ורך. גבולות רכים הם מייעצים. אם מספר הקבצים הפתוחים חרג מהמגבלה הקשיחה, המשתמש לא יוכל לפתוח קבצים חדשים עד לסגירת הקבצים שנפתחו בעבר.

כדי להציג את המגבלות הנוכחיות, השתמש בפקודה ulimit עם

-S

(רך) או

-H

(קשה) ואת האפשרות

-n

(המספר המרבי של מתארי קבצים פתוחים).

כדי להציג את המגבלה הרכה, הפעל פקודה זו:

# ulimit -Sn

כדי להציג את ערך הגבול הקשיח:

ulimit -Hn

כיצד להגדיל את מגבלת הקבצים הפתוחים המקסימלית בלינוקס?

כדי לאפשר לכל השירותים לפתוח מספר רב של קבצים, באפשרותך לשנות את המגבלות במערכת ההפעלה Linux. כדי להפוך הגדרות חדשות לקבועות ולמנוע את איפוסן לאחר הפעלה מחדש של שרת או הפעלה, עליך לבצע שינויים ב- /etc/security/limits.conf. קובץ זה מאפשר להגביל את מספר משאבי המערכת השונים הזמינים לתהליך משתמש. השתמש בתבנית הבאה:

username restriction_type restriction_name value

לדוגמה:

apache  hard nofile 978160
apache soft nofile 978160

באפשרותך להשתמש ב-

*

במקום שם משתמש. משמעות הדבר היא שמגבלת קבצים פתוחים זו תחול על כל משתמשי לינוקס:

* hard nofile 97816
* soft nofile 97816

לדוגמה, קיבלת שגיאת קבצים פתוחים רבים מדי עבור Nginx. בדוק כמה קבצים מותר לתהליך משתמש זה לפתוח:

$ sudo -u nginx bash -c 'ulimit -n'
1024

זה לא מספיק עבור שרת בעומס גבוה. הוסף את השורות הבאות אל /etc/security/limits.conf:

nginx hard nofile 50000
nginx soft nofile 50000

בליבות Linux ישנות יותר, ניתן להגדיר את הערך של fs.file-max ל- 10000. אז בדוק את הערך הזה והגדל אותו כך שהוא גדול מהמספר ב- limits.conf:

# sysctl -w fs.file-max=500000

פעולה זו תגדיל באופן זמני את מגבלת הקבצים הפתוחים. כדי להפוך את ההגדרות החדשות לקבועות, עליך להוסיף את השורה הבאה לקובץ /etc/sysctl.conf:

fs.file-max = 500000

ויישמו אותו:

sysctl -p

בדוק שהקובץ /etc/pam.d/common-session (Debian/Ubuntu) או /etc/pam.d/login (CentOS/RedHat/Fedora) מכיל את השורה:

session required pam_limits.so

אם לא, הוסף אותו לסוף קובץ התצורה. פרמטר זה מאפשר החלת מגבלות קבצים פתוחים לאחר אימות המשתמש.

לאחר ביצוע שינויים, פתח מחדש את הקונסולה ובדוק את הערך max_open_files:

# ulimit -n
50000

הגדלת המספר המרבי של מתארי קבצים פתוחים לכל שירות

באפשרותך להגדיל את מתארי הקבצים הפתוחים המרביים עבור שירות ספציפי, במקום עבור מערכת ההפעלה כולה. בואו ניקח אפאצ'י כדוגמה. פתח את הגדרות השירות באמצעות systemctl:

# systemctl edit httpd.service

הוסף את המגבלות הרצויות, לדוגמה:

[Service]
LimitNOFILE=16000
LimitNOFILESoft=16000

לאחר ביצוע השינויים, עדכן את תצורת השירות והפעל אותה מחדש:

# systemctl daemon-reload
# systemctl restart httpd.service

כדי לבדוק אם הערכים השתנו, קבל את השירות PID:

# systemctl status httpd.service

לדוגמה, PID השירות הוא 3724:

# cat /proc/3724/limits | grep "Max open files"

הערך חייב להיות 16000.

לפיכך, שינית את ערך הקבצים הפתוחים המרבי עבור שירות ספציפי.

כיצד להגדיר קבצים פתוחים מקסימליים עבור Nginx ו- Apache?

לאחר הגדלת המגבלה על מספר הקבצים הפתוחים עבור שרת, עליך גם לשנות את קובץ תצורת השירות. לדוגמה, ציין/שנה את ערך ההוראה הבא בקובץ התצורה של Nginx /etc/nginx/nginx.conf:

worker_rlimit_nofile 16000

הוראת worker_rlimit_nofile מגדירה את המגבלה על מספר הקבצים הפתוחים על-ידי תהליך עובד ( RLIMIT_NOFILE ). Nginx זקוקה למתארי קבצים כדי להחזיר קובץ סטטי מהמטמון עבור כל חיבור לקוח. ככל שיותר משתמשים מתחברים לשרת שלך וככל ש-Nginx מחזירה יותר קבצים סטטיים, כך נעשה שימוש רב יותר במתארי קבצים. מספר הידיות המרבי מוגבל ברמת מערכת ההפעלה ו/או השירות. אם מספר הקבצים הפתוחים ב- Nginx חורג, "

socket() failed (24: Too many open files) while connecting to upstream error

" יתרחש.

בעת הגדרת Nginx בשרת 8 ליבות בעומס גבוה עם worker_connections 8192, עליך לציין 8192*2*8 (vCPU)=131072 ב- worker_rlimit_nofile.

לאחר מכן הפעל מחדש את Nginx.

# nginx -t && service nginx -s reload

כדי לראות את מספר הקבצים הפתוחים עבור תהליכי משתמש של Nginx:

su nginx
# ulimit -Hn
# for pid in `pidof nginx`; do echo "$(< /proc/$pid/cmdline)"; egrep 'files|Limit' /proc/$pid/limits; echo "Currently open files: $(ls -1 /proc/$pid/fd | wc -l)"; echo; done

עבור Apache, עליך ליצור ספרייה:

# mkdir /lib/systemd/system/httpd.service.d/

לאחר מכן צור את הקובץ limit_nofile.conf:

# nano /lib/systemd/system/httpd.service.d/limit_nofile.conf

הוסיפו לו:

[Service]
LimitNOFILE=16000

אל תשכח להפעיל מחדש את שירות httpd.

שינוי מגבלת הקבצים הפתוחים עבור הפעלת המשתמש הנוכחית

כדי לשנות את מגבלות הקבצים הפתוחים המרביות עבור הפעלת המשתמש הנוכחית שלך, הפעל פקודה זו:

# ulimit -n 3000

אם תציין כאן ערך גדול מזה שצוין בגבול הקשיח, תופיע שגיאה:

-bash: ulimit: open files: cannot modify limit: Operation not permitted

לאחר סגירת ההפעלה ופתיחת הפעלה חדשה, המגבלות יחזרו לערכים הראשוניים שצוינו ב- /etc/security/limits.conf.

במאמר זה, למדנו כיצד לפתור את הבעיה כאשר הערך של מגבלת מתארי קבצים פתוחים בלינוקס קטן מדי, ובדקנו מספר אפשרויות לשינוי מגבלות אלה בשרת.