linux系統(tǒng)出現(xiàn)“out of memory”錯(cuò)誤的根本解決方法包括:1.查明原因,使用top命令查看內(nèi)存占用高的進(jìn)程,或用pmap -x
先說個(gè)實(shí)在的,OOM killer是linux內(nèi)核的最后一道防線。它會(huì)選擇性地殺死一些進(jìn)程,釋放內(nèi)存,保證系統(tǒng)核心功能還能運(yùn)行。但這肯定不是我們想要的,程序無故被殺,數(shù)據(jù)丟失是小,系統(tǒng)崩潰是大。所以,得從根本上解決問題。
解決方案
-
查明原因:誰在瘋狂吃內(nèi)存?
最直接的辦法,用top命令。看看哪個(gè)進(jìn)程的%MEM占用率高得離譜。如果是你寫的程序,那趕緊回去debug吧。如果是一些系統(tǒng)服務(wù),那就要具體問題具體分析了。
再高級(jí)一點(diǎn),可以用pmap -x
查看進(jìn)程的內(nèi)存映射情況,看看哪些內(nèi)存區(qū)域占用最多。pid是進(jìn)程ID,top命令里能找到。 -
增加Swap空間:應(yīng)急措施
Swap空間相當(dāng)于硬盤上的虛擬內(nèi)存。當(dāng)物理內(nèi)存不夠用時(shí),系統(tǒng)會(huì)把一部分不常用的內(nèi)存數(shù)據(jù)放到Swap空間里。這能緩解燃眉之急,但速度肯定比物理內(nèi)存慢很多,所以只能算是應(yīng)急措施。
怎么增加Swap空間?簡單說幾步:
- 創(chuàng)建一個(gè)文件作為Swap空間:sudo fallocate -l 2G /swapfile (這里創(chuàng)建了一個(gè)2GB的Swap文件)
- 設(shè)置正確的權(quán)限:sudo chmod 600 /swapfile
- 格式化為Swap文件系統(tǒng):sudo mkswap /swapfile
- 啟用Swap空間:sudo swapon /swapfile
- 添加到/etc/fstab,讓系統(tǒng)啟動(dòng)時(shí)自動(dòng)啟用:echo ‘/swapfile swap swap defaults 0 0’ | sudo tee -a /etc/fstab
別忘了,Swap空間不是萬能的。頻繁的Swap操作(thrashing)會(huì)導(dǎo)致系統(tǒng)性能急劇下降。
-
優(yōu)化程序:釜底抽薪
如果內(nèi)存占用是程序造成的,那就要優(yōu)化代碼了。常見的優(yōu)化手段包括:
- 減少內(nèi)存泄漏: 檢查代碼中是否有內(nèi)存分配后沒有釋放的情況。Valgrind是個(gè)好工具。
- 使用更高效的數(shù)據(jù)結(jié)構(gòu): 比如,用哈希表代替線性查找,用壓縮數(shù)據(jù)結(jié)構(gòu)減少內(nèi)存占用。
- 優(yōu)化算法: 避免不必要的內(nèi)存復(fù)制,減少臨時(shí)變量的創(chuàng)建。
- 使用內(nèi)存池: 減少頻繁的內(nèi)存分配和釋放操作。
-
限制進(jìn)程內(nèi)存使用:治標(biāo)之策
可以使用ulimit命令限制進(jìn)程的內(nèi)存使用量。例如,ulimit -v 2000000限制進(jìn)程的虛擬內(nèi)存使用量為2GB。但這只是治標(biāo)之策,不能解決根本問題。
-
升級(jí)硬件:終極方案
如果以上方法都無效,那就只能升級(jí)硬件了。加內(nèi)存條是最直接有效的辦法。
如何監(jiān)控Linux系統(tǒng)內(nèi)存使用情況?
監(jiān)控內(nèi)存使用情況是預(yù)防OOM錯(cuò)誤的有效手段。除了top命令,還可以使用free -m命令查看內(nèi)存使用情況。free -m會(huì)以MB為單位顯示內(nèi)存使用情況,包括總內(nèi)存、已用內(nèi)存、空閑內(nèi)存、Swap空間等。
更高級(jí)的監(jiān)控工具包括:
- vmstat: 報(bào)告虛擬內(nèi)存統(tǒng)計(jì)信息。
- sar: 收集、報(bào)告和保存系統(tǒng)活動(dòng)信息,包括內(nèi)存使用情況。
- Grafana + Prometheus: 搭建一套完整的監(jiān)控系統(tǒng),可以實(shí)時(shí)監(jiān)控內(nèi)存使用情況,并設(shè)置告警。
OOM Killer是如何工作的?如何避免被它殺死?
OOM Killer會(huì)根據(jù)一個(gè)叫做oom_score的參數(shù)來選擇要?dú)⑺赖倪M(jìn)程。oom_score越高,被殺死的可能性越大。這個(gè)分?jǐn)?shù)會(huì)考慮進(jìn)程的內(nèi)存占用、運(yùn)行時(shí)間、用戶權(quán)限等因素。
如何避免被OOM Killer殺死?
- 降低oom_score: 可以通過調(diào)整/proc/
/oom_adj或/proc/ /oom_score_adj文件來降低進(jìn)程的oom_score。例如,echo -17 > /proc/ /oom_score_adj可以將進(jìn)程的oom_score降到最低,使其幾乎不可能被OOM Killer殺死。但是,這樣做有風(fēng)險(xiǎn),如果該進(jìn)程真的導(dǎo)致了OOM,可能會(huì)導(dǎo)致系統(tǒng)崩潰。 - 合理分配內(nèi)存: 盡量避免程序占用過多的內(nèi)存。
- 使用cgroups: cgroups可以限制進(jìn)程的資源使用量,包括內(nèi)存。
如何分析OOM日志?
OOM Killer殺死進(jìn)程后,會(huì)在系統(tǒng)日志中留下記錄。這些日志通常包含被殺死的進(jìn)程ID、進(jìn)程名、內(nèi)存占用情況等信息。分析這些日志可以幫助我們找到導(dǎo)致OOM的原因。
日志通常位于/var/log/syslog或/var/log/kern.log文件中。可以使用grep命令過濾出OOM相關(guān)的日志。例如,grep “Out of memory” /var/log/syslog。
分析OOM日志需要一定的經(jīng)驗(yàn),但只要耐心分析,就能找到問題的根源。