diff --git a/nixos/modules/services/system/earlyoom.nix b/nixos/modules/services/system/earlyoom.nix index ddd5bcebcdd..62935855989 100644 --- a/nixos/modules/services/system/earlyoom.nix +++ b/nixos/modules/services/system/earlyoom.nix @@ -5,8 +5,8 @@ let inherit (lib) mkDefault mkEnableOption mkIf mkOption types - mkRemovedOptionModule - concatStringsSep optional; + mkRemovedOptionModule literalExpression + escapeShellArg concatStringsSep optional optionalString; in { @@ -17,10 +17,26 @@ in type = types.ints.between 1 100; default = 10; description = '' - Minimum of availabe memory (in percent). - If the free memory falls below this threshold and the analog is true for - - the killing begins. + Minimum available memory (in percent). + + If the available memory falls below this threshold (and the analog is true for + ) the killing begins. + SIGTERM is sent first to the process that uses the most memory; then, if the available + memory falls below (and the analog is true for + ), SIGKILL is sent. + + See README 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 . + + See the description of . ''; }; @@ -28,19 +44,20 @@ in type = types.ints.between 1 100; default = 10; description = '' - Minimum of availabe swap space (in percent). - If the available swap space falls below this threshold and the analog - is true for - the killing begins. + Minimum free swap space (in percent) before sending SIGTERM. + + See the description of . ''; }; - # TODO: remove or warn after 1.7 (https://github.com/rfjakob/earlyoom/commit/7ebc4554) - ignoreOOMScoreAdjust = mkOption { - type = types.bool; - default = false; + freeSwapKillThreshold = mkOption { + type = types.nullOr (types.ints.between 1 100); + default = null; description = '' - Ignore oom_score_adjust values of processes. + Minimum free swap space (in percent) before sending SIGKILL. + If unset, this defaults to half of . + + See the description of . ''; }; @@ -63,12 +80,43 @@ in local user to DoS your session by spamming notifications. To actually see the notifications in your GUI session, you need to have - systembus-notify running as your user which this - option handles. + systembus-notify running as your user, which this + option handles by enabling . See README 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 + README and + the man page + 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 = [ @@ -76,7 +124,11 @@ in This option is deprecated and ignored by earlyoom since 1.2. '') (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"; ExecStart = concatStringsSep " " ([ "${pkgs.earlyoom}/bin/earlyoom" - "-m ${toString cfg.freeMemThreshold}" - "-s ${toString cfg.freeSwapThreshold}" + ("-m ${toString cfg.freeMemThreshold}" + + 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.enableNotifications "-n" + ++ optional (cfg.killHook != null) "-N ${escapeShellArg cfg.killHook}" + ++ cfg.extraArgs ); }; }; diff --git a/nixos/tests/all-tests.nix b/nixos/tests/all-tests.nix index 8d54f78a948..47587b1b30c 100644 --- a/nixos/tests/all-tests.nix +++ b/nixos/tests/all-tests.nix @@ -132,6 +132,7 @@ in domination = handleTest ./domination.nix {}; dovecot = handleTest ./dovecot.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-nixops = (handleTestOn ["x86_64-linux"] ./ec2.nix {}).boot-ec2-nixops or {}; ecryptfs = handleTest ./ecryptfs.nix {}; diff --git a/nixos/tests/earlyoom.nix b/nixos/tests/earlyoom.nix new file mode 100644 index 00000000000..75bdf56899b --- /dev/null +++ b/nixos/tests/earlyoom.nix @@ -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") + ''; +}) diff --git a/pkgs/os-specific/linux/earlyoom/default.nix b/pkgs/os-specific/linux/earlyoom/default.nix index 46e83609722..ad7468bac0f 100644 --- a/pkgs/os-specific/linux/earlyoom/default.nix +++ b/pkgs/os-specific/linux/earlyoom/default.nix @@ -1,4 +1,4 @@ -{ lib, stdenv, fetchFromGitHub, pandoc, installShellFiles, withManpage ? false }: +{ lib, stdenv, fetchFromGitHub, pandoc, installShellFiles, withManpage ? false, nixosTests }: stdenv.mkDerivation rec { pname = "earlyoom"; @@ -23,6 +23,10 @@ stdenv.mkDerivation rec { installManPage earlyoom.1 ''; + passthru.tests = { + inherit (nixosTests) earlyoom; + }; + meta = with lib; { description = "Early OOM Daemon for Linux"; homepage = "https://github.com/rfjakob/earlyoom";