diff options
Diffstat (limited to 'system/earlyoom')
-rw-r--r-- | system/earlyoom/README | 30 | ||||
-rw-r--r-- | system/earlyoom/doinst.sh | 25 | ||||
-rw-r--r-- | system/earlyoom/earlyoom.8 | 270 | ||||
-rw-r--r-- | system/earlyoom/earlyoom.SlackBuild | 114 | ||||
-rw-r--r-- | system/earlyoom/earlyoom.info | 10 | ||||
-rw-r--r-- | system/earlyoom/rc.earlyoom | 97 | ||||
-rw-r--r-- | system/earlyoom/slack-desc | 19 |
7 files changed, 565 insertions, 0 deletions
diff --git a/system/earlyoom/README b/system/earlyoom/README new file mode 100644 index 0000000000..95f8c2fbec --- /dev/null +++ b/system/earlyoom/README @@ -0,0 +1,30 @@ +earlyoom (the early out-of-memory daemon) + +The Linux kernel's OOM-killer generally has a bad reputation among +Linux users. One may have to sit in front of an unresponsive system, +listening to the grinding disk for minutes, and press the reset +button to quickly get back to what one was doing after running out of +patience. + +earlyoom is a userspace daemon that can be triggered earlier than the +kernel's OOM-killer. It checks the amount of available memory and free +swap up to 10 times a second (less often if there is a lot of free +memory). By default if both are below 10%, it will kill the largest +process (highest oom_score). The percentage value is configurable via +command line arguments. + +To enable it, put this line in your rc.local after running chmod +x on +/etc/rc.d/rc.earlyoom: + +if [ -x /etc/rc.d/rc.earlyoom ]; then + /etc/rc.d/rc.earlyoom start +fi + +...and to have it exit at shutdown, put this in your rc.local_shutdown: + +if [ -x /etc/rc.d/rc.earlyoom ]; then + /etc/rc.d/rc.earlyoom stop +fi + +A log file for it is kept at /var/log/earlyoom.log, and earlyoom can +be configured by modifying /etc/default/earlyoom. diff --git a/system/earlyoom/doinst.sh b/system/earlyoom/doinst.sh new file mode 100644 index 0000000000..e32196a11c --- /dev/null +++ b/system/earlyoom/doinst.sh @@ -0,0 +1,25 @@ +#!/bin/sh + +config() { + NEW="$1" + OLD="$(dirname $NEW)/$(basename $NEW .new)" + if [ ! -r $OLD ]; then + mv $NEW $OLD + elif [ "$(cat $OLD | md5sum)" = "$(cat $NEW | md5sum)" ]; then + rm $NEW + fi +} + +preserve_perms() { + NEW="$1" + OLD="$(dirname $NEW)/$(basename $NEW .new)" + if [ -e $OLD ]; then + cp -a $OLD ${NEW}.incoming + cat $NEW > ${NEW}.incoming + mv ${NEW}.incoming $NEW + fi + config $NEW +} + +config etc/default/earlyoom.new +preserve_perms etc/rc.d/rc.earlyoom.new diff --git a/system/earlyoom/earlyoom.8 b/system/earlyoom/earlyoom.8 new file mode 100644 index 0000000000..9431b55a44 --- /dev/null +++ b/system/earlyoom/earlyoom.8 @@ -0,0 +1,270 @@ +.TH "earlyoom" "8" "August 2023" "1.7" "Linux System Administrator's Manual" +.hy +.SH NAME +.PP +earlyoom - Early OOM Daemon +.SH SYNOPSIS +.PP +\f[B]earlyoom\f[R] [\f[B]OPTION\f[R]]\&... +.SH DESCRIPTION +.PP +The oom-killer generally has a bad reputation among Linux users. +One may have to sit in front of an unresponsive system, listening to the +grinding disk for minutes, and press the reset button to quickly get +back to what one was doing after running out of patience. +.PP +\f[B]earlyoom\f[R] checks the amount of available memory and free swap +up to 10 times a second (less often if there is a lot of free memory). +If \f[B]both\f[R] memory \f[B]and\f[R] swap are below 10%, it will kill +the largest process (highest \f[C]oom_score\f[R]). +The percentage value is configurable via command line arguments. +.PP +If there is a failure when trying to kill a process, \f[B]earlyoom\f[R] +sleeps for 1 second to limit log spam due to recurring errors. +.SH OPTIONS +.SS -m PERCENT[,KILL_PERCENT] +.PP +set available memory minimum to PERCENT of total (default 10 %). +.PP +earlyoom starts sending SIGTERM once \f[B]both\f[R] memory \f[B]and\f[R] +swap are below their respective PERCENT setting. +It sends SIGKILL once \f[B]both\f[R] are below their respective +KILL_PERCENT setting (default PERCENT/2). +.PP +Use the same value for PERCENT and KILL_PERCENT if you always want to +use SIGKILL. +.PP +Examples: +.IP +.nf +\f[C] +earlyoom # sets PERCENT=10, KILL_PERCENT=5 +earlyoom -m 30 # sets PERCENT=30, KILL_PERCENT=15 +earlyoom -m 20,18 # sets PERCENT=20, KILL_PERCENT=18 +\f[R] +.fi +.SS -s PERCENT[,KILL_PERCENT] +.PP +set free swap minimum to PERCENT of total (default 10 %). +Send SIGKILL if at or below KILL_PERCENT (default PERCENT/2), otherwise +SIGTERM. +.PP +You can use \f[C]-s 100\f[R] to have earlyoom effectively ignore swap +usage: Processes are killed once available memory drops below the +configured minimum, no matter how much swap is free. +.PP +Use the same value for PERCENT and KILL_PERCENT if you always want to +use SIGKILL. +.SS -M SIZE[,KILL_SIZE] +.PP +As an alternative to specifying a percentage of total memory, +\f[C]-M\f[R] sets the available memory minimum to SIZE KiB. +The value is internally converted to a percentage. +If you pass both \f[C]-M\f[R] and \f[C]-m\f[R], the lower value is used. +Example: Reserve 10% of RAM but at most 1 GiB: +.IP +.nf +\f[C] +earlyoom -m 10 -M 1048576 +\f[R] +.fi +.PP +earlyoom sends SIGKILL if at or below KILL_SIZE (default SIZE/2), +otherwise SIGTERM. +.SS -S SIZE[,KILL_SIZE] +.PP +As an alternative to specifying a percentage of total swap, \f[C]-S\f[R] +sets the free swap minimum to SIZE KiB. +The value is internally converted to a percentage. +If you pass both \f[C]-S\f[R] and \f[C]-s\f[R], the lower value is used. +.PP +Send SIGKILL if at or below KILL_SIZE (default SIZE/2), otherwise +SIGTERM. +.SS -k +.PP +removed in earlyoom v1.2, ignored for compatibility +.SS -i +.PP +removed in earlyoom v1.7, ignored for compatibility +.SS -d +.PP +enable debugging messages +.SS -v +.PP +print version information and exit +.SS -r INTERVAL +.PP +Time between printing periodic memory reports, in seconds (default 1.0). +A memory report looks like this: +.IP +.nf +\f[C] +mem avail: 21790 of 23909 MiB (91.14%), swap free: 0 of 0 MiB ( 0.00%) +\f[R] +.fi +.PP +Set to 3600 to print a report every hour, to 86400 to print once a day +etc. +Set to 0 to disable printing periodic memory reports. +Free memory monitoring and low-memory killing runs independently of this +option at an adaptive poll rate that only depends on free memory. +Due to the adaptive poll rate, when there is a lot of free memory, the +actual interval may be up to 1 second longer than the setting. +.SS -p +.PP +Increase earlyoom\[cq]s priority: set niceness of earlyoom to -20 and +oom_score_adj to -100. +.PP +When earlyoom is run through its default systemd service, the +\f[C]-p\f[R] switch doesn\[cq]t work. +To achieve the same effect, enter the following three lines into +\f[C]sudo systemctl edit earlyoom\f[R]: +.IP +.nf +\f[C] +[Service] +OOMScoreAdjust=-100 +Nice=-20 +\f[R] +.fi +.SS -n +.PP +Enable notifications via d-bus. +.PP +To actually see the notifications in your GUI session, you need to have +systembus-notify (https://github.com/rfjakob/systembus-notify) running +as your user. +.SS -N /PATH/TO/SCRIPT +.PP +Run the given script for each process killed. +Must be an absolute path. +.PP +Within the script, information about the killed process can be obtained +via the following environment variables: +.IP +.nf +\f[C] +EARLYOOM_PID Process PID +EARLYOOM_NAME Process name truncated to 16 bytes (as reported in /proc/PID/comm) +EARLYOOM_UID UID of the user running the process +\f[R] +.fi +.PP +WARNING: \f[C]EARLYOOM_NAME\f[R] can contain spaces, newlines, special +characters and is controlled by the user, or it can be empty! +Make sure that your notification script can handle that! +.SS -g +.PP +Kill all processes that have same process group id (PGID) as the process +with excessive memory usage. +.PP +For example, with this flag turned on, the whole application will be +killed when one of its subprocess consumes too much memory (as long as +they all have the same PGID, of course). +.PP +Enable this flag when completely cleaning up the \[lq]entire +application\[rq] is more desirable, and you are sure that the +application puts all its processes in the same PGID. +.PP +Note that some desktop environments (GNOME, for example) put all desktop +application in the same process group as \f[C]gnome-shell\f[R]. +earlyoom might kill all such processes including \f[C]gnome-shell\f[R] +when this flag is turned on. +.PP +Be sure to check how your environment behaves beforehand. +Use +.IP +.nf +\f[C] +pstree -gT +\f[R] +.fi +.PP +to show all processes with the PGID in brackets. +.SS --prefer REGEX +.PP +prefer killing processes matching REGEX (adds 300 to oom_score) +.SS --avoid REGEX +.PP +avoid killing processes matching REGEX (subtracts 300 from oom_score) +.SS --ignore REGEX +.PP +ignore processes matching REGEX. +.PP +Unlike the --avoid option, this option disables any potential killing of +the matched processes that might have occurred due to the processes +attaining a high oom_score. +.PP +Use this option with caution as other processes might be sacrificed in +place of the ignored processes when earlyoom determines to kill +processes. +.SS --dryrun +.PP +dry run (do not kill any processes) +.SS -h, --help +.PP +this help text +.SH EXIT STATUS +.PP +0: Successful program execution. +.PP +1: Other error - inspect message for details +.PP +2: Switch conflict. +.PP +4: Could not cd to /proc +.PP +5: Could not open proc +.PP +7: Could not open /proc/sysrq-trigger +.PP +13: Unknown options. +.PP +14: Wrong parameters for other options. +.PP +15: Wrong parameters for memory threshold. +.PP +16: Wrong parameters for swap threshold. +.PP +102: Could not open /proc/meminfo +.PP +103: Could not read /proc/meminfo +.PP +104: Could not find a specific entry in /proc/meminfo +.PP +105: Could not convert number when parse the contents of /proc/meminfo +.SH Why not trigger the kernel oom killer? +.PP +Earlyoom does not use \f[C]echo f > /proc/sysrq-trigger\f[R] because the +Chrome people made their browser always be the first (innocent!) +victim by setting \f[C]oom_score_adj\f[R] very high. +Instead, earlyoom finds out itself by reading through +\f[C]/proc/*/status\f[R] (actually \f[C]/proc/*/statm\f[R], which +contains the same information but is easier to parse programmatically). +.PP +Additionally, in recent kernels (tested on 4.0.5), triggering the kernel +oom killer manually may not work at all. +That is, it may only free some graphics memory (that will be allocated +immediately again) and not actually kill any process. +.SH MEMORY USAGE +.PP +About 2 MiB VmRSS. +All memory is locked using mlockall() to make sure earlyoom does not +slow down in low memory situations. +.SH BUGS +.PP +If there is zero total swap on earlyoom startup, any \f[C]-S\f[R] +(uppercase \[lq]S\[rq]) values are ignored, a warning is printed, and +default swap percentages are used. +.PP +For processes matched by \f[C]--prefer\f[R], negative +\f[C]oom_score_adj\f[R] values are not taken into account, and the +process gets an effective \f[C]oom_score\f[R] of at least 300. +See https://github.com/rfjakob/earlyoom/issues/159 for details. +.SH AUTHOR +.PP +The author of earlyoom is Jakob Unterwurzacher +<jakobunt@gmail.com>. +.PP +This manual page was written by Yangfl <mmyangfl@gmail.com>, +for the Debian project (and may be used by others). diff --git a/system/earlyoom/earlyoom.SlackBuild b/system/earlyoom/earlyoom.SlackBuild new file mode 100644 index 0000000000..9a04c78429 --- /dev/null +++ b/system/earlyoom/earlyoom.SlackBuild @@ -0,0 +1,114 @@ +#!/bin/bash + +# Slackware build script for earlyoom + +# Copyright 2022 Charadon US +# Copyright 2023 B. Watson +# All rights reserved. +# +# Redistribution and use of this script, with or without modification, is +# permitted provided that the following conditions are met: +# +# 1. Redistributions of this script must retain the above copyright +# notice, this list of conditions and the following disclaimer. +# +# THIS SOFTWARE IS PROVIDED BY THE AUTHOR "AS IS" AND ANY EXPRESS OR IMPLIED +# WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF +# MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO +# EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +# SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, +# PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; +# OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, +# WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR +# OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF +# ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +# 20230829 bkw: BUILD=2 +# - add LICENSE and README.md to the doc dir. +# - binary in /usr/sbin, man page in section 8, since this is admin stuff. +# - have the init script delete the PID file after stop or force_stop. +# - actually use SLKCFLAGS. +# - make /etc/default/earlyoom a .new config file. +# - add a bit more detail to README. + +cd $(dirname $0) ; CWD=$(pwd) + +PRGNAM=earlyoom +VERSION=${VERSION:-1.7} +BUILD=${BUILD:-2} +TAG=${TAG:-_SBo} +PKGTYPE=${PKGTYPE:-tgz} + +if [ -z "$ARCH" ]; then +case "$( uname -m )" in + i?86) ARCH=i586 ;; + arm*) ARCH=arm ;; + *) ARCH=$( uname -m ) ;; +esac +fi + +if [ ! -z "${PRINT_PACKAGE_NAME}" ]; then + echo "$PRGNAM-$VERSION-$ARCH-$BUILD$TAG.$PKGTYPE" + exit 0 +fi + +TMP=${TMP:-/tmp/SBo} +PKG=$TMP/package-$PRGNAM +OUTPUT=${OUTPUT:-/tmp} + +if [ "$ARCH" = "i586" ]; then + SLKCFLAGS="-O2 -march=i586 -mtune=i686" +elif [ "$ARCH" = "i686" ]; then + SLKCFLAGS="-O2 -march=i686 -mtune=i686" +elif [ "$ARCH" = "x86_64" ]; then + SLKCFLAGS="-O2 -fPIC" +else + SLKCFLAGS="-O2" +fi + +set -e + +rm -rf $PKG +mkdir -p $TMP $PKG $OUTPUT +cd $TMP +rm -rf $PRGNAM-$VERSION +tar xvf $CWD/$PRGNAM-$VERSION.tar.gz +cd $PRGNAM-$VERSION +chown -R root:root . +find -L . -perm /111 -a \! -perm 755 -a -exec chmod 755 {} + -o \ + \! -perm /111 -a \! -perm 644 -a -exec chmod 644 {} + + +# 20230829 bkw: don't generate the man page even if pandoc is installed, +# since we're going to use a prebuilt one. +sed -i '/^PANDOC *:=/d' Makefile + +# 20230829 bkw: no way to do this on the make command line: +sed -i "/^CFLAGS/s,-Wall,& $SLKCFLAGS," Makefile + +# 20230829 bkw: note to self: non-canonical use of BINDIR here. It's not +# the full path (/usr/sbin), it gets PREFIX prepended to it. +make PREFIX=/usr BINDIR=/sbin +strip $PRGNAM +make DESTDIR=$PKG PREFIX=/usr BINDIR=/sbin install-bin + +# 20230829 bkw: prebuilt man page is a bit different from the generated one: +# - it's a section 8 page. +# - it has the date and "Linux System Administrator's Manual" filled in. +# - get rid of fancy unicode angle brackets for email addresses, just use <>. +mkdir -p $PKG/usr/man/man8 +gzip -9 < $CWD/earlyoom.8 > $PKG/usr/man/man8/earlyoom.8.gz + +install -Dm644 $CWD/rc.earlyoom $PKG/etc/rc.d/rc.earlyoom.new +install -Dm644 earlyoom.default $PKG/etc/default/earlyoom.new + +PKGDOC=$PKG/usr/doc/$PRGNAM-$VERSION +mkdir -p $PKGDOC +cp -a README* LICENSE* $PKGDOC +cat $CWD/$PRGNAM.SlackBuild > $PKGDOC/$PRGNAM.SlackBuild + +mkdir -p $PKG/install +cat $CWD/slack-desc > $PKG/install/slack-desc +cat $CWD/doinst.sh > $PKG/install/doinst.sh + +cd $PKG +/sbin/makepkg -l y -c n $OUTPUT/$PRGNAM-$VERSION-$ARCH-$BUILD$TAG.$PKGTYPE diff --git a/system/earlyoom/earlyoom.info b/system/earlyoom/earlyoom.info new file mode 100644 index 0000000000..bb2d219617 --- /dev/null +++ b/system/earlyoom/earlyoom.info @@ -0,0 +1,10 @@ +PRGNAM="earlyoom" +VERSION="1.7" +HOMEPAGE="https://github.com/rfjakob/earlyoom" +DOWNLOAD="https://github.com/rfjakob/earlyoom/archive/v1.7/earlyoom-1.7.tar.gz" +MD5SUM="9c567930c60b2ccdc536951b005d413d" +DOWNLOAD_x86_64="" +MD5SUM_x86_64="" +REQUIRES="" +MAINTAINER="B. Watson" +EMAIL="urchlay@slackware.uk" diff --git a/system/earlyoom/rc.earlyoom b/system/earlyoom/rc.earlyoom new file mode 100644 index 0000000000..0e1cbb303d --- /dev/null +++ b/system/earlyoom/rc.earlyoom @@ -0,0 +1,97 @@ +#!/bin/sh +set -eu + +. /etc/default/earlyoom + +do_start() { + if [ -f /var/run/earlyoom.pid ]; + then + if ps -p "$(cat /var/run/earlyoom.pid)" > /dev/null 2>&1 + then + echo "earlyoom is already running." + exit 0 + fi + fi + echo "Starting earlyoom..." + # shellcheck disable=2086 + nohup /usr/sbin/earlyoom $EARLYOOM_ARGS > /var/log/earlyoom.log 2>&1 & + echo "$!" > /var/run/earlyoom.pid + exit 0 +} + +do_stop() { + if [ -f /var/run/earlyoom.pid ]; + then + if ps -p "$(cat /var/run/earlyoom.pid)" > /dev/null 2>&1 + then + echo "Stopping earlyoom..." + kill -15 "$(cat /var/run/earlyoom.pid)" > /dev/null 2>&1 + rm -f /var/run/earlyoom.pid + exit 0 + fi + fi + echo "earlyoom is not running..." +} + +do_force_stop() { + if [ -f /var/run/earlyoom.pid ]; + then + if ps -p "$(cat /var/run/earlyoom.pid)" > /dev/null 2>&1 + then + echo "Killing earlyoom..." + kill -9 "$(cat /var/run/earlyoom.pid)" > /dev/null 2>&1 + rm -f /var/run/earlyoom.pid + exit 0 + fi + fi + echo "earlyoom appears to not be running." + exit 0 +} + +do_restart() { + do_stop + do_start +} + +do_status() { + if [ -f /var/run/earlyoom.pid ]; + then + if ps -p "$(cat /var/run/earlyoom.pid)" > /dev/null 2>&1 + then + echo "earlyoom is running with pid $(cat /var/run/earlyoom.pid)." + exit 0 + fi + fi + echo "earlyoom is not running." +} + +do_help() { + echo "USAGE: rc.earlyoom (start|stop|force-stop|restart|status)" + exit 0 +} + +if [ -z "${1-}" ]; +then + do_help +fi + +case $1 in + start) + do_start + ;; + stop) + do_stop + ;; + restart) + do_restart + ;; + force-stop) + do_force_stop + ;; + status) + do_status + ;; + *) + do_help + ;; +esac diff --git a/system/earlyoom/slack-desc b/system/earlyoom/slack-desc new file mode 100644 index 0000000000..5eef07ce20 --- /dev/null +++ b/system/earlyoom/slack-desc @@ -0,0 +1,19 @@ +# HOW TO EDIT THIS FILE: +# The "handy ruler" below makes it easier to edit a package description. +# Line up the first '|' above the ':' following the base package name, and +# the '|' on the right side marks the last column you can put a character in. +# You must make exactly 11 lines for the formatting to be correct. It's also +# customary to leave one space after the ':' except on otherwise blank lines. + + |-----handy-ruler------------------------------------------------------| +earlyoom: earlyoom (the early out-of-memory daemon) +earlyoom: +earlyoom: earlyoom is a userspace daemon that can be triggered earlier than the +earlyoom: kernel's OOM-killer. It checks the amount of available memory and free +earlyoom: swap up to 10 times a second (less often if there is a lot of free +earlyoom: memory). By default if both are below 10%, it will kill the largest +earlyoom: process (highest oom_score). The percentage value is configurable via +earlyoom: command line arguments. +earlyoom: +earlyoom: +earlyoom: |