โดยทั่วไปแล้ว oom-killer จะมีชื่อเสียงที่ไม่ดีในหมู่ผู้ใช้ Linux นี่อาจเป็นส่วนหนึ่งของเหตุผลที่ Linux เรียกใช้เมื่อไม่มีทางเลือกอื่นเท่านั้น มันจะสลับสภาพแวดล้อมเดสก์ท็อป วางแคชทั้งหน้า และล้างบัฟเฟอร์ทุกอันก่อนที่กระบวนการจะหยุดทำงานในที่สุด อย่างน้อยนั่นคือสิ่งที่ฉันคิดว่ามันจะทำ ฉันยังไม่อดทนพอที่จะรอมัน โดยนั่งอยู่หน้าระบบที่ไม่ตอบสนอง
สิ่งนี้ทำให้ฉันและคนอื่นๆ สงสัยว่า oom-killer สามารถกำหนดค่าให้เข้ามาก่อนหน้านี้ได้หรือไม่: reddit r/linux, superuser.com, unix.stackexchange.com
ปรากฎว่าไม่ทำไม่ได้ อย่างน้อยก็ใช้ oom-killer ในเคอร์เนล อย่างไรก็ตาม ในส่วนของผู้ใช้ เราสามารถทำทุกอย่างที่เราต้องการได้
Earlyoom ต้องการความเรียบง่ายและมั่นคง เขียนด้วยภาษา C ล้วนๆ ไม่มีการขึ้นต่อกัน ชุดทดสอบที่ครอบคลุม (การทดสอบหน่วยและการทดสอบการรวม) เขียนด้วยภาษา Go
Earlyoom ตรวจสอบจำนวนหน่วยความจำที่มีอยู่และสลับฟรีสูงสุด 10 ครั้งต่อวินาที (บ่อยครั้งน้อยกว่าหากมีหน่วยความจำว่างจำนวนมาก) โดยค่าเริ่มต้น หากทั้งสองค่าต่ำกว่า 10% ระบบจะฆ่ากระบวนการที่ใหญ่ที่สุด (สูงสุด oom_score
) ค่าเปอร์เซ็นต์สามารถกำหนดค่าได้ผ่านทางอาร์กิวเมนต์บรรทัดคำสั่ง
ในเอาต์พุต free -m
ด้านล่าง หน่วยความจำที่ใช้ได้คือ 2170 MiB และค่าสวอปฟรีคือ 231 MiB
total used free shared buff/cache available Mem: 7842 4523 137 841 3182 2170 Swap: 1023 792 231
เหตุใดจึงมีการตรวจสอบหน่วยความจำ "ว่าง" แทนที่จะเป็นหน่วยความจำ "ว่าง" บนระบบ Linux ที่ดี หน่วยความจำ "ว่าง" ควรจะใกล้เคียงกับศูนย์ เนื่องจาก Linux ใช้หน่วยความจำกายภาพที่มีอยู่ทั้งหมดเพื่อแคชการเข้าถึงดิสก์ แคชเหล่านี้สามารถทิ้งได้ทุกเมื่อที่ต้องการหน่วยความจำสำหรับสิ่งอื่น
หน่วยความจำ "ที่มีอยู่" คำนึงถึงสิ่งนั้น โดยจะสรุปหน่วยความจำทั้งหมดที่ไม่ได้ใช้หรือสามารถปล่อยได้ทันที
โปรดทราบว่าคุณต้องมีเคอร์เนล free
และ Linux เวอร์ชัน 3.14+ เวอร์ชันล่าสุดจึงจะเห็นคอลัมน์ "พร้อมใช้งาน" หากคุณมีเคอร์เนลล่าสุด แต่เป็น free
เวอร์ชันเก่า คุณสามารถรับค่าได้จาก grep MemAvailable /proc/meminfo
เมื่อทั้งหน่วยความจำที่มีอยู่และการสลับฟรีของคุณลดลงต่ำกว่า 10% ของหน่วยความจำทั้งหมดที่มีให้กับกระบวนการพื้นที่ผู้ใช้ (= รวมที่ใช้ร่วมกัน) มันจะส่งสัญญาณ SIGTERM
ไปยังกระบวนการที่ใช้หน่วยความจำมากที่สุดตามความเห็นของเคอร์เนล ( /proc/*/oom_score
)
nohang ซึ่งเป็นโปรเจ็กต์ที่คล้ายกันเช่น Earlyoom เขียนด้วย Python และมีคุณสมบัติเพิ่มเติมและตัวเลือกการกำหนดค่า
แพตช์เคอร์เนลข้อมูลแผงความดัน (psi) ของ facebooks และตัวช่วย oomd userspace ที่มาพร้อมกัน แพตช์นี้รวมอยู่ใน Linux 4.20
Earlyoom ไม่ได้ใช้ echo f > /proc/sysrq-trigger
เพราะ:
ในเคอร์เนลบางเวอร์ชัน (ทดสอบบนเวอร์ชัน 4.0.5) การทริกเกอร์เคอร์เนล oom killer ด้วยตนเองจะไม่ทำงานเลย นั่นคืออาจทำให้หน่วยความจำกราฟิกบางส่วนว่างเท่านั้น (ซึ่งจะถูกจัดสรรทันทีอีกครั้ง) และไม่ได้ฆ่ากระบวนการใดๆ เลย ที่นี่คุณสามารถดูว่าสิ่งนี้มีลักษณะอย่างไรบนเครื่องของฉัน (กราฟิกในตัวของ Intel)
ปัญหานี้ได้รับการแก้ไขแล้วใน Linux v5.17 (commit f530243a)
เช่นเดียวกับเคอร์เนล Linux Earlyoom ค้นหาเหยื่อโดยการอ่านผ่าน /proc/*/oom_score
ประมาณ 2 MiB
( VmRSS
) แม้ว่าจะมีเพียง 220 kiB
เท่านั้นที่เป็นหน่วยความจำส่วนตัว ( RssAnon
) ส่วนที่เหลือคือไลบรารี libc ( RssFile
) ที่แชร์กับกระบวนการอื่น หน่วยความจำทั้งหมดถูกล็อคโดยใช้ mlockall()
เพื่อให้แน่ใจว่า Earlyoom จะไม่ช้าลงในสถานการณ์ที่มีหน่วยความจำเหลือน้อย
รวบรวมตัวเองเป็นเรื่องง่าย:
โคลนคอมไพล์ https://github.com/rfjakob/earlyoom.gitcd ทำ
ทางเลือก: รันการทดสอบตัวเองแบบรวม:
ทำการทดสอบ
เริ่ม Earlyoom โดยอัตโนมัติโดยการลงทะเบียนเป็นบริการ:
sudo ทำการติดตั้ง # systemdsudo ทำการติดตั้ง initscript # ไม่ใช่ systemd
โปรดทราบว่าสำหรับระบบที่ปิดใช้งาน SELinux (Ubuntu 19.04, Debian 9 ... ) คำเตือน chcon ที่รายงานความล้มเหลวในการตั้งค่าบริบทสามารถถูกเพิกเฉยได้อย่างปลอดภัย
สำหรับ Debian 10+ และ Ubuntu 18.04+ มีแพ็คเกจ Debian:
sudo apt ติดตั้งก่อนเวลา
สำหรับ Fedora และ RHEL 8 ที่มี EPEL มีแพ็คเกจ Fedora:
sudo dnf ติดตั้งก่อนเวลา sudo systemctl เปิดใช้งาน - ตอนนี้เร็วขึ้น
สำหรับ Arch Linux มีแพ็คเกจ Arch Linux:
sudo pacman -S เร็วเกินไป sudo systemctl เปิดใช้งาน - ตอนนี้เร็วขึ้น
ความพร้อมใช้งานในรุ่นอื่นๆ: ดูหน้าการตอบกลับ
เพียงเริ่มต้นปฏิบัติการที่คุณเพิ่งรวบรวม:
./ช่วงต้น
โดยจะแจ้งให้คุณทราบว่าคุณมีหน่วยความจำและสวอปเท่าใด จำนวนขั้นต่ำ จำนวนหน่วยความจำที่พร้อมใช้งาน และจำนวนสวอปว่าง
./earlyoom eearlyoom v1.8 mem total: 23890 MiB, user mem total: 21701 MiB, swap total: 8191 MiB sending SIGTERM when mem avail <= 10.00% and swap free <= 10.00%, SIGKILL when mem avail <= 5.00% and swap free <= 5.00% mem avail: 20012 of 21701 MiB (92.22%), swap free: 5251 of 8191 MiB (64.11%) mem avail: 20031 of 21721 MiB (92.22%), swap free: 5251 of 8191 MiB (64.11%) mem avail: 20033 of 21723 MiB (92.22%), swap free: 5251 of 8191 MiB (64.11%) [...]
หากค่าลดลงต่ำกว่าค่าต่ำสุด กระบวนการจะถูกหยุดทำงานจนกว่าจะสูงกว่าค่าต่ำสุดอีกครั้ง ทุกการกระทำจะถูกบันทึกไว้ที่ stderr หากคุณใช้งาน Earlyoom เป็นบริการ systemd คุณสามารถดู 10 บรรทัดสุดท้ายได้โดยใช้
สถานะ systemctl ก่อนเวลา
หากต้องการดูการทำงาน earlyoom
ให้สร้าง/จำลองหน่วยความจำรั่ว และปล่อยให้ earlyoom
ดำเนินการดังนี้:
tail /dev/zero
หากคุณต้องการดำเนินการใดๆ เพิ่มเติมหลังจากที่กระบวนการถูกฆ่าโดย earlyoom
(เช่น การส่งอีเมล) คุณสามารถแยกวิเคราะห์บันทึกได้โดย:
sudo journalctl -u earlyoom | grep sending
ตัวอย่างเอาต์พุตสำหรับคำสั่งทดสอบด้านบน ( tail /dev/zero
) จะมีลักษณะดังนี้:
Feb 20 10:59:34 debian earlyoom[10231]: sending SIGTERM to process 7378 uid 1000 "tail": oom_score 156, VmRSS 4962 MiB
สำหรับ
earlyoom
เวอร์ชันเก่า ให้ใช้:sudo journalctl -u earlyoom | grep -iE "(sending|killing)"
ตั้งแต่เวอร์ชัน 1.6 เป็นต้นมา Earlyoom สามารถส่งการแจ้งเตือนเกี่ยวกับกระบวนการที่ถูกฆ่าผ่านระบบ d-bus Pass -n
เพื่อเปิดใช้งาน
หากต้องการดูการแจ้งเตือนในเซสชัน GUI ของคุณ คุณจะต้องให้ systembus-notify ทำงานเป็นผู้ใช้ของคุณ
นอกจากนี้ Earlyoom ยังสามารถรันสคริปต์สำหรับแต่ละกระบวนการที่ถูกฆ่า โดยให้ข้อมูลเกี่ยวกับกระบวนการผ่านตัวแปรสภาพแวดล้อม EARLYOOM_PID
, EARLYOOM_UID
และ EARLYOOM_NAME
ผ่าน -N /path/to/script
เพื่อเปิดใช้งาน
คำเตือน: ในกรณีของโหมด dryrun สคริปต์จะถูกดำเนินการอย่างรวดเร็ว ตรวจสอบให้แน่ใจว่าคุณได้ใช้ขีดจำกัดอัตราบางประเภทแล้ว
ธงบรรทัดคำสั่ง --prefer
ระบุกระบวนการที่ต้องการฆ่า ในทำนองเดียวกัน --avoid
ระบุกระบวนการเพื่อหลีกเลี่ยงการฆ่า ดู https://github.com/rfjakob/earlyoom/blob/master/MANPAGE.md#--prefer-regex สำหรับรายละเอียด
หากคุณใช้งาน Earlyoom เป็นบริการระบบ (ผ่าน systemd หรือ init.d) คุณสามารถปรับการกำหนดค่าผ่านไฟล์ที่ให้ไว้ใน /etc/default/earlyoom
ไฟล์นี้มีตัวอย่างบางส่วนในความคิดเห็นอยู่แล้ว ซึ่งคุณสามารถใช้เพื่อสร้างชุดการกำหนดค่าของคุณเองตามตัวเลือกบรรทัดคำสั่งที่รองรับ เช่น:
EARLYOOM_ARGS="-m 5 -r 60 --avoid '(^|/)(init|Xorg|ssh)$' --prefer '(^|/)(java|chromium)$'"
หลังจากปรับไฟล์แล้ว เพียงรีสตาร์ทบริการเพื่อใช้การเปลี่ยนแปลง ตัวอย่างเช่น สำหรับ systemd:
systemctl รีสตาร์ทก่อนเวลา
โปรดทราบว่าไฟล์การกำหนดค่านี้ไม่มีผลกระทบต่ออินสแตนซ์ช่วงต้นภายนอก systemd/init.d
earlyoom v1.8 Usage: ./earlyoom [OPTION]... -m PERCENT[,KILL_PERCENT] set available memory minimum to PERCENT of total (default 10 %). earlyoom sends SIGTERM once below PERCENT, then SIGKILL once below KILL_PERCENT (default PERCENT/2). -s PERCENT[,KILL_PERCENT] set free swap minimum to PERCENT of total (default 10 %). Note: both memory and swap must be below minimum for earlyoom to act. -M SIZE[,KILL_SIZE] set available memory minimum to SIZE KiB -S SIZE[,KILL_SIZE] set free swap minimum to SIZE KiB -n enable d-bus notifications -N /PATH/TO/SCRIPT call script after oom kill -g kill all processes within a process group -d, --debug enable debugging messages -v print version information and exit -r INTERVAL memory report interval in seconds (default 1), set to 0 to disable completely -p set niceness of earlyoom to -20 and oom_score_adj to -100 --ignore-root-user do not kill processes owned by root --sort-by-rss find process with the largest rss (default oom_score) --prefer REGEX prefer to kill processes matching REGEX --avoid REGEX avoid killing processes matching REGEX --ignore REGEX ignore processes matching REGEX --dryrun dry run (do not kill any processes) --syslog use syslog instead of std streams -h, --help this help text
ดูหน้าคนสำหรับรายละเอียด
ยินดีรายงานข้อผิดพลาดและคำขอดึงข้อมูลผ่าน GitHub โดยเฉพาะผมยินดียอมรับ
รายงานกรณีการใช้งานและข้อเสนอแนะ
เราไม่ใช้ procps/libproc2 เพราะ procps_pids_select() ด้วยเหตุผลบางอย่าง มักจะแยกวิเคราะห์ /proc/$pid/status เสมอ ราคาค่อนข้างแพงและเราไม่ต้องการมัน
เวอร์ชัน 1.8.2, 07-05-2024
เพิ่ม process_mrelease
ไปยัง syscalls ที่อนุญาต (กระทำ)
แก้ไขไวยากรณ์ IPAddressDeny
(กระทำ)
อนุญาต -p
(กระทำ)
แก้ไขในไฟล์หน่วย earlyoom.service
systemd
เวอร์ชัน 1.8.1, 17-04-2024
แก้ไขความล้มเหลวในการทดสอบเล็กน้อยที่เกิดจากการเปลี่ยนข้อความใหม่ (กระทำ)
เวอร์ชัน 1.8, 15-04-2024
แนะนำ user mem total
/ meminfo_t.UserMemTotal
และคำนวณ MemAvailablePercent ตามนั้น (กระทำ ข้อมูลเพิ่มเติมในหน้า man)
ใช้ process_mrelease
(#266)
สนับสนุน NO_COLOR
(https://no-color.org/)
อย่าสับสนกับกระบวนการที่มีเธรดหลักของซอมบี้ (กระทำ)
เพิ่ม --sort-by-rss
ขอบคุณ @RanHuang! นี่จะเลือกกระบวนการที่จะฆ่าบัญชี ไปยัง RSS ที่ใหญ่ที่สุดแทนที่จะเป็น oom_score ที่ใหญ่ที่สุด
ขณะนี้ชุดทดสอบ Gitlab CI ยังทำงานบน Amazon Linux 2 และ Oracle Linux 7 อีกด้วย
เวอร์ชัน 1.7, 05-03-2022
เพิ่มแฟล็ก -N
เพื่อรันสคริปต์ทุกครั้งที่กระบวนการถูกฆ่า (กระทำส่วนหน้าคน)
เพิ่มแฟล็ก -g
เพื่อฆ่ากลุ่มกระบวนการทั้งหมด (#247)
ลบแฟล็ก -i
(ละเว้นสำหรับความเข้ากันได้) มันทำงานไม่ถูกต้องบนเคอร์เนล Linux 5.9+ (#234)
การแข็งตัว: ลดความสามารถโดยรอบเมื่อเริ่มต้น (#234)
เวอร์ชัน 1.6.2, 14-10-2020
ตรวจสอบสถานการณ์หน่วยความจำอีกครั้งก่อนฆ่าเหยื่อ (กระทำ)
อย่ายุติตัวเราเอง (#205)
ดัมพ์บัฟเฟอร์ข้อผิดพลาดในการแปลง /proc/meminfo (#214)
1.6.1, 07-07-2020
ทำความสะอาดกระบวนการซอมบี้ส่ง dbus (#200)
ข้ามกระบวนการด้วย oom_score_adj=-1000 (210)
1.6, 11-04-2020
-n
/ -N
เปิดใช้งานตรรกะใหม่แล้ว
คุณต้องให้ systembus-notify ทำงานในเซสชัน GUI ของคุณเพื่อรับการแจ้งเตือนเกี่ยวกับการทำงาน
แทนที่ตรรกะการแจ้งเตือน GUI แบบ notify-send
แบบเก่าด้วย dbus-send
/ systembus-notify (#183)
จัดการ /proc
ติดตั้งด้วย Hidepid อย่างสง่างาม (ฉบับที่ #184)
เวอร์ชัน 1.5, 22-03-2020
-p
: ตั้งค่า oom_score_adj เป็น -100
แทนที่จะเป็น -1000
(#170)
อนุญาตให้ใช้ ทั้ง -M
และ -m
และ -S
และ -s
จะใช้ค่าที่ต่ำกว่า (แปลงเป็นเปอร์เซ็นต์)
ตั้งค่าช่วงเวลารายงานหน่วยความจำใน earlyoom.default
เป็น 1 ชั่วโมงแทนที่จะเป็น 1 นาที (#177)
เวอร์ชัน 1.4, 01-03-2020
ใช้ตัวแปรบล็อกโลคัลเมื่อเป็นไปได้
แนะนำ PATH_LEN เพื่อแทนที่ความยาวบัฟเฟอร์แบบฮาร์ดโค้ดหลายแบบ
ทำให้ตรรกะการเลือกเหยื่อเร็วขึ้น 50% ด้วยแอตทริบิวต์กระบวนการโหลดแบบ Lazy Loading
บันทึก ID ผู้ใช้ uid
ของกระบวนการที่ถูกฆ่า นอกเหนือจาก pid และชื่อ
บันทึกการแก้ไขข้อบกพร่องสีเป็นสีเทาอ่อน
การล้างโค้ด
ขยายชุดทดสอบ ( make test
)
เรียกใช้ cppcheck
เมื่อพร้อมใช้งาน
เพิ่มเกณฑ์มาตรฐานการทดสอบหน่วย ( make bench
)
ยกเลิกสิทธิ์รูทในไฟล์หน่วย systemd earlyoom.service
v1.3.1, 27-02-2020
แก้ไขความล้มเหลวของชุดทดสอบปลอมบนระบบที่มี RAM จำนวนมาก (ฉบับที่ #156)
เวอร์ชัน 1.3, 26-05-2019
อย่าออกโดยมีข้อผิดพลาดร้ายแรงหากขีดจำกัด SIGTERM < ขีดจำกัด SIGKILL
อนุญาตให้มีขีดจำกัด SIGKILL เป็นศูนย์
วิธีนี้ช่วยแก้ไขปัญหาที่บางครั้ง Earlyoom ฆ่ากระบวนการมากกว่าหนึ่งกระบวนการเมื่อกระบวนการเดียวก็เพียงพอแล้ว (ฉบับที่ #121)
รอให้กระบวนการออกจริงเมื่อส่งสัญญาณ
มีเสรีนิยมมากขึ้นในสิ่งที่จำกัดในการยอมรับสำหรับ SIGTERM และ SIGKILL (ฉบับที่ 97)
ฟอร์แมตเอาต์พุตเริ่มต้นใหม่เพื่อให้ชัดเจนว่าทั้งการแลกเปลี่ยนและ mem ต้องเป็น <= จำกัด
เพิ่มสคริปต์ตัวช่วย notify_all_users.py
เพิ่ม CODE_OF_CONDUCT.md (กติกาผู้ร่วมให้ข้อมูล 1.4) (#102)
แก้ไขชื่อแอป UTF8 ที่อาจถูกตัดทอนในเอาต์พุตบันทึก (#110)
เวอร์ชัน 1.2, 28-10-2018
ใช้ Adaptive Sleep Time (= อัตราการสำรวจแบบปรับตัว) เพื่อลดการใช้งาน CPU ต่อไป (ฉบับที่ 61)
ลบตัวเลือกเพื่อใช้เคอร์เนล oom-killer ( -k
ตอนนี้ถูกละเว้นเนื่องจากความเข้ากันได้) (ฉบับที่ #80)
จัดการกรณีของ Swap ที่ถูกเพิ่มหรือลบออกอย่างสง่างามหลังจากเริ่มต้น Earlyoom (ฉบับที่ 62, กระทำ)
ใช้ staged kill: อันดับแรก SIGTERM ตามด้วย SIGKILL พร้อมขีดจำกัดที่กำหนดค่าได้ (ฉบับที่ #67)
เวอร์ชัน 1.1, 07-07-2018
แก้ไขการฉีดโค้ดเชลล์ที่เป็นไปได้ผ่านการแจ้งเตือน GUI (กระทำ)
หากล้มเหลวในการฆ่ากระบวนการใด ๆ ให้พักเพียง 1 วินาทีแทนที่จะเป็น 10 (ฉบับที่ #74)
ส่งการแจ้งเตือน GUI หลังจาก การฆ่า ไม่ใช่ก่อนหน้า (ฉบับที่ #73)
ยอมรับ --help
นอกเหนือจาก -h
แก้ไขชื่อกระบวนการที่ไม่ถูกต้องในบันทึกและในการแจ้งเตือนการฆ่า (กระทำ 1, กระทำ 2, ฉบับที่ #52, ฉบับที่ #65, ฉบับที่ #194)
แก้ไขการหารที่เป็นไปได้ด้วยศูนย์ด้วย -S
(กระทำ)
เวอร์ชัน 1.0, 28-01-2018
เพิ่ม --prefer
และ --avoid
ตัวเลือก (@TomJohnZ)
เพิ่มการรองรับการแจ้งเตือน GUI เพิ่มตัวเลือก -n
และ -N
v0.12: เพิ่มตัวเลือก -M
และ -S
(@nailgun); เพิ่มหน้า man กำหนดพารามิเตอร์ Makefile (@yangfl)
v0.11: แก้ไขพฤติกรรมที่ไม่ได้กำหนดใน get_entry_fatal (การส่งคืนที่หายไป, การคอมมิต)
v0.10: อนุญาตให้แทนที่ตัวแปร VERSION ของ Makefile เพื่อให้บรรจุภัณฑ์ง่ายขึ้น เพิ่มตัวเลือกบรรทัดคำสั่ง -v
v0.9: หาก oom_score ของกระบวนการทั้งหมดเป็น 0 ให้ใช้ VmRss เพื่อค้นหาเหยื่อ
v0.8: ใช้การคาดเดาหากเคอร์เนลไม่มี MemAvailable
v0.7: เลือกเหยื่อด้วย oom_score แทน VmRSS เพิ่มตัวเลือก -i
และ -d
v0.6: เพิ่มตัวเลือกบรรทัดคำสั่ง -m
, -s
, -k
v0.5: เพิ่มการสนับสนุนการแลกเปลี่ยน
v0.4: เพิ่มสคริปต์เริ่มต้น SysV (ขอบคุณ @joeytwiddle) ใช้ MemAvailable
ใหม่จาก /proc/meminfo
(ต้องการ Linux 3.14+, คอมมิต)
v0.2: เพิ่มไฟล์หน่วย systemd
v0.1: การเปิดตัวครั้งแรก