[代碼修訂版] Python 踩坑之旅進程篇其五打不開的文件

代碼示例支持
平臺: Centos 6.3
Python: 2.7.14
代碼示例: 菜單 - Python踩坑指南代碼示例

1.1 踩坑案例

長期運行的daemon進程或者socket測試類進程, 常常遇到的坑是:shell

IOError: [Errno 24] Too many open filesbash

即進程遇到 IO 錯誤, 沒法打開更多的文件.socket

1.2 填坑和分析

通常從兩個方面入手:測試

1.2.1 從程序優化入手

  • 檢查文件打開是否遵循了"誰打開誰關閉"原則
  • 文件是否存在關閉泄露

a. 誰打開誰關閉是個普適的原則:優化

  • 只有邏輯設計者本身最熟悉
    • 哪些文件 FD 須要一直維持打開狀態
    • 哪些文件直到某個事件發生後關閉
  • 短暫的文件讀寫打開推薦使用 pythonic 的 with statement
# with 語法會在生命週期後自動關閉打開的文件 FD
with open('xxxx_path.file', 'w') as fhandle:
    fhandle.dosth()

b. 檢查文件 FD 是否存在泄漏設計

系統設計階段通常會預估系統整體可打開的 FD 狀況. 當出現以下狀況時可能出現了泄漏 BUGcode

  • 外圍監控系統發現該進程 FD 大量突破了設計預估
  • 打開 FD 增加趨勢異常
    • 通常隨着業務增長, FD 會線性增加, 但有限度和規律
    • 若是增加曲線不停的出現陡峭增加且在業務低峯期也如此可能出現了泄露

Python 基礎庫 CUP 提供對進程打開 FD 的支持, 詳見示例代碼.生命週期

1.2.2 從資源軟硬限入手

  • 瞭解系統的資源軟硬限制
  • 檢查進程可打開的FD是否突破了系統限制
    • 長期運行的 daemon 進程尤爲注意

Centos 6.3 Linux系統爲例, 查看 /etc/security/limits.conf 得到系統軟硬限資源進程

* soft nofile 10240
* hard nofile 10240

其中, 用戶不能突破系統的硬線 hard nofile limit.

用戶也能夠經過 shell 命令 ulimit -n 來限定該 shell 啓動的全部進程的 nofile

  • 固然非 root 用戶是不能突破系統硬線的
  • 用戶爲了進程控制, 能夠設定nofile更小

ulimit -a 能夠查看當前用戶被設定的限制, 示例:

[test@agent1 ~]$ ulimit -a
core file size          (blocks, -c) 0
.......
open files                      (-n) 10240
.....
virtual memory          (kbytes, -v) unlimited
file locks                      (-x) unlimited

1.4.1 技術關鍵字

  • Open FD
  • 資源 Soft limit / Hard limit

下期坑位預告

  • PyDaemon 進程長什麼樣

Life is short. We use Python.

相關文章
相關標籤/搜索