Ubuntu环境下Python脚本意外内存耗尽问题排查与解决咨询
Python脚本被OOM Killer终止的问题排查与解决方案
问题背景
Python脚本运行时被标记为Killed,dmesg输出如下错误:
[Sat Dec 3 11:25:59 2022] Out of memory: Killed process 1126 (python) total-vm:17534768kB, anon-rss:14299092kB, file-rss:2752kB, shmem-rss:0kB, UID:1000 pgtables:28200kB oom_score_adj:0
脚本是长时间运行的任务(需数小时),同时运行两个实例,在虚拟环境中通过tmux执行。核心逻辑是读取最大约2GB的CSV文件到内存,用pandas拆分后输出小文件,代码模式如下:
for os.walk: df = read_csv() smaller_dfs = df.groupby for small_df in smaller_dfs: small_df.to_csv()
原本认为每次循环后上一个CSV的数据会被释放,但虚拟机有16GB内存,执行期间top显示总内存占用仅2-3GB,buff/cache占7-8GB,突然内存耗尽超出预期。
dmesg输出的进程表中两个Python进程:
[Sat Dec 3 11:25:59 2022] [ pid ] uid tgid total_vm rss pgtables_bytes swapents oom_score_adj name [Sat Dec 3 11:25:59 2022] [ 184] 0 184 17344 979 147456 0 -250 systemd-journal [Sat Dec 3 11:25:59 2022] [ 217] 0 217 5054 988 65536 0 -1000 systemd-udevd [Sat Dec 3 11:25:59 2022] [ 342] 0 342 70036 4488 90112 0 -1000 multipathd [Sat Dec 3 11:25:59 2022] [ 413] 102 413 22665 554 77824 0 0 systemd-timesyn [Sat Dec 3 11:25:59 2022] [ 484] 100 484 6850 921 77824 0 0 systemd-network [Sat Dec 3 11:25:59 2022] [ 487] 101 487 6136 1444 94208 0 0 systemd-resolve [Sat Dec 3 11:25:59 2022] [ 522] 0 522 60290 929 102400 0 0 accounts-daemon [Sat Dec 3 11:25:59 2022] [ 523] 0 523 637 183 49152 0 0 acpid [Sat Dec 3 11:25:59 2022] [ 527] 0 527 2137 567 53248 0 0 cron [Sat Dec 3 11:25:59 2022] [ 529] 103 529 1894 915 49152 0 -900 dbus-daemon [Sat Dec 3 11:25:59 2022] [ 538] 0 538 20475 740 61440 0 0 irqbalance [Sat Dec 3 11:25:59 2022] [ 540] 0 540 7407 2833 90112 0 0 networkd-dispat [Sat Dec 3 11:25:59 2022] [ 542] 0 542 59108 902 98304 0 0 polkitd [Sat Dec 3 11:25:59 2022] [ 545] 104 545 56125 958 81920 0 0 rsyslogd [Sat Dec 3 11:25:59 2022] [ 547] 0 547 363271 1292 204800 0 0 amazon-ssm-agen [Sat Dec 3 11:25:59 2022] [ 555] 0 555 274152 4234 290816 0 -900 snapd [Sat Dec 3 11:25:59 2022] [ 557] 0 557 4336 998 69632 0 0 systemd-logind [Sat Dec 3 11:25:59 2022] [ 565] 0 565 98885 1209 135168 0 0 udisksd [Sat Dec 3 11:25:59 2022] [ 566] 0 566 951 560 49152 0 0 atd [Sat Dec 3 11:25:59 2022] [ 599] 0 599 78585 931 106496 0 0 ModemManager [Sat Dec 3 11:25:59 2022] [ 606] 0 606 1840 436 53248 0 0 agetty [Sat Dec 3 11:25:59 2022] [ 611] 0 611 13313 362 94208 0 0 nginx [Sat Dec 3 11:25:59 2022] [ 613] 33 613 13454 821 94208 0 0 nginx [Sat Dec 3 11:25:59 2022] [ 614] 33 614 13454 821 94208 0 0 nginx [Sat Dec 3 11:25:59 2022] [ 628] 0 628 1459 362 53248 0 0 agetty [Sat Dec 3 11:25:59 2022] [ 657] 0 657 27034 2733 114688 0 0 unattended-upgr [Sat Dec 3 11:25:59 2022] [ 750] 0 750 3046 938 61440 0 -1000 sshd [Sat Dec 3 11:25:59 2022] [ 780] 0 780 3452 1050 73728 0 0 sshd [Sat Dec 3 11:25:59 2022] [ 789] 1000 789 4731 1118 73728 0 0 systemd [Sat Dec 3 11:25:59 2022] [ 793] 1000 793 25976 822 98304 0 0 (sd-pam) [Sat Dec 3 11:25:59 2022] [ 919] 1000 919 3486 809 73728 0 0 sshd [Sat Dec 3 11:25:59 2022] [ 920] 1000 920 2543 976 61440 0 0 bash [Sat Dec 3 11:25:59 2022] [ 1050] 0 1050 365631 1936 225280 0 0 ssm-agent-worke [Sat Dec 3 11:25:59 2022] [ 1074] 1000 1074 2534 1281 65536 0 0 tmux: server [Sat Dec 3 11:25:59 2022] [ 1075] 1000 1075 2565 914 57344 0 0 bash [Sat Dec 3 11:25:59 2022] [ 1105] 1000 1105 2564 967 53248 0 0 bash [Sat Dec 3 11:25:59 2022] [ 1126] 1000 1126 4383692 3575461 28876800 0 0 python [Sat Dec 3 11:25:59 2022] [ 1131] 1000 1131 2752 785 69632 0 0 top [Sat Dec 3 11:25:59 2022] [ 1174] 1000 1174 2757 754 57344 0 0 top [Sat Dec 3 11:25:59 2022] [ 1278] 0 1278 3452 1040 61440 0 0 sshd [Sat Dec 3 11:25:59 2022] [ 1372] 1000 1372 3486 811 61440 0 0 sshd [Sat Dec 3 11:25:59 2022] [ 1373] 1000 1373 1473 564 45056 0 0 sftp-server [Sat Dec 3 11:25:59 2022] [ 1382] 1000 1382 2760 793 61440 0 0 top [Sat Dec 3 11:25:59 2022] [ 1404] 1000 1404 2760 794 65536 0 0 top [Sat Dec 3 11:25:59 2022] [ 1569] 1000 1569 436810 384689 3260416 0 0 python [Sat Dec 3 11:25:59 2022] [ 1578] 1000 1578 2760 817 57344 0 0 top
执行期间free命令输出:
total used free shared buff/cache available Mem: 16240152 6257732 6280208 868 3702212 9695756 Swap: 0 0 0
问题解答
1. 排查步骤
- 聚焦OOM时刻的真实内存占用:
dmesg里的anon-rss:14299092kB显示被杀死的Python进程实际占用了约13.6GB物理内存,这是触发OOM的直接原因。top是采样式监控,脚本处理数据时可能出现瞬间内存峰值(比如groupby操作生成临时数据、大DataFrame的副本),这个峰值没被捕捉到。 - 持续跟踪Python进程内存变化:用
ps aux --sort=-%mem实时监控两个Python进程的内存,或者在脚本里加入内存监控逻辑,比如每次循环前后用psutil库的process.memory_info().rss打印当前内存使用,定位内存飙升的节点。 - 检查pandas内存泄漏:即使循环逻辑看似释放了数据,pandas的某些操作可能隐式保留引用(比如
groupby返回的对象持有原DataFrame引用,或全局变量、闭包意外留存旧数据)。可以在循环末尾手动删除变量并强制GC,观察内存是否下降。 - 分析buff/cache的可回收性:Linux的
buff/cache在内存紧张时会被回收,但如果存在大量不可回收的匿名页,或其他进程竞争内存,可能导致buff/cache无法及时释放触发OOM。用vmstat 1观察内存回收情况,查看si/so列(swap进出)是否异常,或用slabtop检查内核缓存占用。 - 排查隐性内存占用:检查虚拟环境依赖、tmux会话中的后台进程、系统日志或临时文件导致的内核内存消耗,这些在
top中可能不明显,但会占用内存。
2. 脚本中降低OOM概率的操作
- 手动触发垃圾回收:在每次循环末尾加入
import gc; gc.collect(),强制回收不再使用的内存。这会增加少量CPU开销,但能及时释放pandas可能遗留的内存。 - 优化pandas内存使用:
- 读取CSV时指定
dtype参数,将字符串、整数等类型设为更节省内存的类型(比如用category类型存储重复值多的列,用int32代替int64),降低初始内存占用。 - 使用
pandas.read_csv的chunksize
- 读取CSV时指定
相关产品推荐
相关产品推荐

