โดยทั่วไปแล้ว 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
)
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 จะไม่ช้าลงในสถานการณ์ที่มีหน่วยความจำเหลือน้อย
รวบรวมตัวเองเป็นเรื่องง่าย:
git clone https://github.com/rfjakob/earlyoom.git
cd earlyoom
make
ทางเลือก: รันการทดสอบตัวเองแบบรวม:
make test
เริ่ม Earlyoom โดยอัตโนมัติโดยการลงทะเบียนเป็นบริการ:
sudo make install # systemd
sudo make install-initscript # non-systemd
โปรดทราบว่าสำหรับระบบที่ปิดใช้งาน SELinux (Ubuntu 19.04, Debian 9 ... ) คำเตือน chcon ที่รายงานความล้มเหลวในการตั้งค่าบริบทสามารถถูกเพิกเฉยได้อย่างปลอดภัย
สำหรับ Debian 10+ และ Ubuntu 18.04+ มีแพ็คเกจ Debian:
sudo apt install earlyoom
สำหรับ Fedora และ RHEL 8 ที่มี EPEL มีแพ็คเกจ Fedora:
sudo dnf install earlyoom
sudo systemctl enable --now earlyoom
สำหรับ Arch Linux มีแพ็คเกจ Arch Linux:
sudo pacman -S earlyoom
sudo systemctl enable --now earlyoom
ความพร้อมใช้งานในรุ่นอื่นๆ: ดูหน้าการตอบกลับ
เพียงเริ่มต้นปฏิบัติการที่คุณเพิ่งรวบรวม:
./earlyoom
โดยจะแจ้งให้คุณทราบว่าคุณมีหน่วยความจำและสวอปเท่าใด จำนวนขั้นต่ำ จำนวนหน่วยความจำที่พร้อมใช้งาน และจำนวนสวอปว่าง
./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 status earlyoom
หากต้องการดูการทำงาน 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 restart earlyoom
โปรดทราบว่าไฟล์การกำหนดค่านี้ไม่มีผลกระทบต่ออินสแตนซ์ช่วงต้นภายนอก 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 โดยเฉพาะผมยินดียอมรับ
เวอร์ชัน 1.8.2, 07-05-2024
earlyoom.service
systemdprocess_mrelease
ไปยัง syscalls ที่อนุญาต (กระทำ)IPAddressDeny
(กระทำ)-p
(กระทำ)เวอร์ชัน 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 ที่ใหญ่ที่สุดเวอร์ชัน 1.7, 05-03-2022
-N
เพื่อรันสคริปต์ทุกครั้งที่กระบวนการถูกฆ่า (กระทำส่วนหน้าคน)-g
เพื่อฆ่ากลุ่มกระบวนการทั้งหมด (#247)-i
(ละเว้นสำหรับความเข้ากันได้) มันทำงานไม่ถูกต้องบนเคอร์เนล Linux 5.9+ (#234)เวอร์ชัน 1.6.2, 14-10-2020
1.6.1, 07-07-2020
1.6, 11-04-2020
notify-send
แบบเก่าด้วย dbus-send
/ systembus-notify (#183)-n
/ -N
เปิดใช้งานตรรกะใหม่แล้ว/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
uid
ของกระบวนการที่ถูกฆ่า นอกเหนือจาก pid และชื่อmake test
)cppcheck
เมื่อพร้อมใช้งานmake bench
)earlyoom.service
v1.3.1, 27-02-2020
เวอร์ชัน 1.3, 26-05-2019
เวอร์ชัน 1.2, 28-10-2018
-k
ตอนนี้ถูกละเว้นเนื่องจากความเข้ากันได้) (ฉบับที่ #80)เวอร์ชัน 1.1, 07-07-2018
--help
นอกเหนือจาก -h
-S
(กระทำ)เวอร์ชัน 1.0, 28-01-2018
--prefer
และ --avoid
ตัวเลือก (@TomJohnZ)-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: การเปิดตัวครั้งแรก