nixos/earlyoom: bring the module up to date (#163663)

* nixos/earlyoom: bring the module up to date

Removes deprecated option `ignoreOOMScoreAdjust`, introduces `killHook`
as a replacement for `notificationsCommand`, and adds an `extraArgs`
option for things not covered by the module.

* nixos/earlyoom: add nixos test

* nixos/earlyoom: add reportInterval

Allows setting the interval for logging a memory report. Defaults to
3600 following upstream
     (https://github.com/rfjakob/earlyoom/blob/master/earlyoom.default#L5)
to avoid flooding logs.

* nixos/earlyoom: add free{Mem,Swap}KillThreshold

Fixes https://github.com/NixOS/nixpkgs/issues/83504
This commit is contained in:
Naïm Favier 2022-03-24 08:34:09 +01:00 committed by GitHub
parent 5f7799415a
commit a8296e7537
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
4 changed files with 99 additions and 22 deletions

View File

@ -5,8 +5,8 @@ let
inherit (lib) inherit (lib)
mkDefault mkEnableOption mkIf mkOption types mkDefault mkEnableOption mkIf mkOption types
mkRemovedOptionModule mkRemovedOptionModule literalExpression
concatStringsSep optional; escapeShellArg concatStringsSep optional optionalString;
in in
{ {
@ -17,10 +17,26 @@ in
type = types.ints.between 1 100; type = types.ints.between 1 100;
default = 10; default = 10;
description = '' description = ''
Minimum of availabe memory (in percent). Minimum available memory (in percent).
If the free memory falls below this threshold and the analog is true for
<option>services.earlyoom.freeSwapThreshold</option> If the available memory falls below this threshold (and the analog is true for
the killing begins. <option>freeSwapThreshold</option>) the killing begins.
SIGTERM is sent first to the process that uses the most memory; then, if the available
memory falls below <option>freeMemKillThreshold</option> (and the analog is true for
<option>freeSwapKillThreshold</option>), SIGKILL is sent.
See <link xlink:href="https://github.com/rfjakob/earlyoom#command-line-options">README</link> for details.
'';
};
freeMemKillThreshold = mkOption {
type = types.nullOr (types.ints.between 1 100);
default = null;
description = ''
Minimum available memory (in percent) before sending SIGKILL.
If unset, this defaults to half of <option>freeMemThreshold</option>.
See the description of <xref linkend="opt-services.earlyoom.freeMemThreshold"/>.
''; '';
}; };
@ -28,19 +44,20 @@ in
type = types.ints.between 1 100; type = types.ints.between 1 100;
default = 10; default = 10;
description = '' description = ''
Minimum of availabe swap space (in percent). Minimum free swap space (in percent) before sending SIGTERM.
If the available swap space falls below this threshold and the analog
is true for <option>services.earlyoom.freeMemThreshold</option> See the description of <xref linkend="opt-services.earlyoom.freeMemThreshold"/>.
the killing begins.
''; '';
}; };
# TODO: remove or warn after 1.7 (https://github.com/rfjakob/earlyoom/commit/7ebc4554) freeSwapKillThreshold = mkOption {
ignoreOOMScoreAdjust = mkOption { type = types.nullOr (types.ints.between 1 100);
type = types.bool; default = null;
default = false;
description = '' description = ''
Ignore oom_score_adjust values of processes. Minimum free swap space (in percent) before sending SIGKILL.
If unset, this defaults to half of <option>freeSwapThreshold</option>.
See the description of <xref linkend="opt-services.earlyoom.freeMemThreshold"/>.
''; '';
}; };
@ -63,12 +80,43 @@ in
local user to DoS your session by spamming notifications. local user to DoS your session by spamming notifications.
To actually see the notifications in your GUI session, you need to have To actually see the notifications in your GUI session, you need to have
<literal>systembus-notify</literal> running as your user which this <literal>systembus-notify</literal> running as your user, which this
option handles. option handles by enabling <option>services.systembus-notify</option>.
See <link xlink:href="https://github.com/rfjakob/earlyoom#notifications">README</link> for details. See <link xlink:href="https://github.com/rfjakob/earlyoom#notifications">README</link> for details.
''; '';
}; };
killHook = mkOption {
type = types.nullOr types.path;
default = null;
example = literalExpression ''
pkgs.writeShellScript "earlyoom-kill-hook" '''
echo "Process $EARLYOOM_NAME ($EARLYOOM_PID) was killed" >> /path/to/log
'''
'';
description = ''
An absolute path to an executable to be run for each process killed.
Some environment variables are available, see
<link xlink:href="https://github.com/rfjakob/earlyoom#notifications">README</link> and
<link xlink:href="https://github.com/rfjakob/earlyoom/blob/master/MANPAGE.md#-n-pathtoscript">the man page</link>
for details.
'';
};
reportInterval = mkOption {
type = types.int;
default = 3600;
example = 0;
description = "Interval (in seconds) at which a memory report is printed (set to 0 to disable).";
};
extraArgs = mkOption {
type = types.listOf types.str;
default = [];
example = [ "-g" "--prefer '(^|/)(java|chromium)$'" ];
description = "Extra command-line arguments to be passed to earlyoom.";
};
}; };
imports = [ imports = [
@ -76,7 +124,11 @@ in
This option is deprecated and ignored by earlyoom since 1.2. This option is deprecated and ignored by earlyoom since 1.2.
'') '')
(mkRemovedOptionModule [ "services" "earlyoom" "notificationsCommand" ] '' (mkRemovedOptionModule [ "services" "earlyoom" "notificationsCommand" ] ''
This option is deprecated and ignored by earlyoom since 1.6. This option was removed in earlyoom 1.6, but was reimplemented in 1.7
and is available as the new option `services.earlyoom.killHook`.
'')
(mkRemovedOptionModule [ "services" "earlyoom" "ignoreOOMScoreAdjust" ] ''
This option is deprecated and ignored by earlyoom since 1.7.
'') '')
]; ];
@ -91,12 +143,16 @@ in
StandardError = "journal"; StandardError = "journal";
ExecStart = concatStringsSep " " ([ ExecStart = concatStringsSep " " ([
"${pkgs.earlyoom}/bin/earlyoom" "${pkgs.earlyoom}/bin/earlyoom"
"-m ${toString cfg.freeMemThreshold}" ("-m ${toString cfg.freeMemThreshold}"
"-s ${toString cfg.freeSwapThreshold}" + optionalString (cfg.freeMemKillThreshold != null) ",${toString cfg.freeMemKillThreshold}")
("-s ${toString cfg.freeSwapThreshold}"
+ optionalString (cfg.freeSwapKillThreshold != null) ",${toString cfg.freeSwapKillThreshold}")
"-r ${toString cfg.reportInterval}"
] ]
++ optional cfg.ignoreOOMScoreAdjust "-i"
++ optional cfg.enableDebugInfo "-d" ++ optional cfg.enableDebugInfo "-d"
++ optional cfg.enableNotifications "-n" ++ optional cfg.enableNotifications "-n"
++ optional (cfg.killHook != null) "-N ${escapeShellArg cfg.killHook}"
++ cfg.extraArgs
); );
}; };
}; };

View File

@ -132,6 +132,7 @@ in
domination = handleTest ./domination.nix {}; domination = handleTest ./domination.nix {};
dovecot = handleTest ./dovecot.nix {}; dovecot = handleTest ./dovecot.nix {};
drbd = handleTest ./drbd.nix {}; drbd = handleTest ./drbd.nix {};
earlyoom = handleTestOn ["x86_64-linux"] ./earlyoom.nix {};
ec2-config = (handleTestOn ["x86_64-linux"] ./ec2.nix {}).boot-ec2-config or {}; ec2-config = (handleTestOn ["x86_64-linux"] ./ec2.nix {}).boot-ec2-config or {};
ec2-nixops = (handleTestOn ["x86_64-linux"] ./ec2.nix {}).boot-ec2-nixops or {}; ec2-nixops = (handleTestOn ["x86_64-linux"] ./ec2.nix {}).boot-ec2-nixops or {};
ecryptfs = handleTest ./ecryptfs.nix {}; ecryptfs = handleTest ./ecryptfs.nix {};

16
nixos/tests/earlyoom.nix Normal file
View File

@ -0,0 +1,16 @@
import ./make-test-python.nix ({ lib, ... }: {
name = "earlyoom";
meta = {
maintainers = with lib.maintainers; [ ncfavier ];
};
machine = {
services.earlyoom = {
enable = true;
};
};
testScript = ''
machine.wait_for_unit("earlyoom.service")
'';
})

View File

@ -1,4 +1,4 @@
{ lib, stdenv, fetchFromGitHub, pandoc, installShellFiles, withManpage ? false }: { lib, stdenv, fetchFromGitHub, pandoc, installShellFiles, withManpage ? false, nixosTests }:
stdenv.mkDerivation rec { stdenv.mkDerivation rec {
pname = "earlyoom"; pname = "earlyoom";
@ -23,6 +23,10 @@ stdenv.mkDerivation rec {
installManPage earlyoom.1 installManPage earlyoom.1
''; '';
passthru.tests = {
inherit (nixosTests) earlyoom;
};
meta = with lib; { meta = with lib; {
description = "Early OOM Daemon for Linux"; description = "Early OOM Daemon for Linux";
homepage = "https://github.com/rfjakob/earlyoom"; homepage = "https://github.com/rfjakob/earlyoom";