[monitoring-plugins] Fix check_swap for FreeBSD with multiple swap ...
Lorenz Kästle
git at monitoring-plugins.org
Tue Sep 15 12:40:14 CEST 2026
Module: monitoring-plugins
Branch: master
Commit: 21d8291f39a802bd605c3a828c3cc6b9d31bd33a
Author: Lorenz Kästle <12514511+RincewindsHat at users.noreply.github.com>
Date: Fri Sep 11 16:34:07 2026 +0200
URL: https://www.monitoring-plugins.org/repositories/monitoring-plugins/commit/?id=21d8291f
Fix check_swap for FreeBSD with multiple swap volumes
On FreeBSD check_swap got a wrong result if multiple
swap volumes are online and swapinfo displays
a summary line ("Total") at the bottom which was
counted twice.
This patch changes the behaviour to find that line and ignore it.
---
configure.ac | 4 ++--
plugins/check_swap.d/swap.c | 45 +++++++++++++++++++++++++++++++++++++++++++--
2 files changed, 45 insertions(+), 4 deletions(-)
diff --git a/configure.ac b/configure.ac
index 3ee89e2e..4972da15 100644
--- a/configure.ac
+++ b/configure.ac
@@ -1633,7 +1633,7 @@ then
if [$PATH_TO_SWAPINFO -k 2>/dev/null | grep -E -i "^Device +1K-blocks +Used +Avail" >/dev/null]
then
- ac_cv_swap_format=["%*s %lf %*d %lf"]
+ ac_cv_swap_format=["%s %lf %*d %lf"]
ac_cv_swap_conv=1024
AC_MSG_RESULT([using FreeBSD format swapinfo])
fi
@@ -1642,7 +1642,7 @@ elif [$PATH_TO_SWAPINFO -dfM 2>/dev/null | grep -E -i "^TYPE +AVAIL +USED +FREE"
then
ac_cv_have_swap=yes
ac_cv_swap_command="$PATH_TO_SWAPINFO -dfM"
- ac_cv_swap_format=["%*s %lu %*d %lu"]
+ ac_cv_swap_format=["%s %lu %*d %lu"]
ac_cv_swap_conv=1024
AC_MSG_RESULT([using HP-UX format swapinfo])
fi
diff --git a/plugins/check_swap.d/swap.c b/plugins/check_swap.d/swap.c
index a3a1a6f3..c7fd5fb1 100644
--- a/plugins/check_swap.d/swap.c
+++ b/plugins/check_swap.d/swap.c
@@ -2,6 +2,7 @@
#include "../popen.h"
#include "../utils.h"
#include "common.h"
+#include <strings.h>
extern int verbose;
@@ -210,7 +211,23 @@ swap_result getSwapFromSwapCommand(swap_config config, const char swap_command[]
*/
if (config.on_aix && !config.allswaps) {
fgets(input_buffer, MAX_INPUT_BUFFER - 1, child_process); /* Ignore first line */
- sscanf(input_buffer, swap_format, &total_swap_mb, &used_swap_mb);
+ int sscanf_result = sscanf(input_buffer, swap_format, &total_swap_mb, &used_swap_mb);
+ switch (sscanf_result) {
+ case 3: {
+ // everything matched, we are good
+ break;
+ }
+ case EOF: {
+ DBG_PRINT_1("sscanf input error");
+ result.errorcode = 1;
+ return result;
+ }
+ default: {
+ DBG_PRINT_1("sscanf failed to match everything");
+ result.errorcode = 1;
+ return result;
+ }
+ }
free_swap_mb = total_swap_mb * (100 - used_swap_mb) / 100;
used_swap_mb = total_swap_mb - free_swap_mb;
@@ -220,7 +237,31 @@ swap_result getSwapFromSwapCommand(swap_config config, const char swap_command[]
}
} else {
while (fgets(input_buffer, MAX_INPUT_BUFFER - 1, child_process)) {
- sscanf(input_buffer, swap_format, &dsktotal_mb, &dskfree_mb);
+ char label[256] = {}; // 256 is just a random guess
+ int sscanf_result =
+ sscanf(input_buffer, swap_format, &label, &dsktotal_mb, &dskfree_mb);
+
+ switch (sscanf_result) {
+ case 3: {
+ // everything matched, we are good
+ break;
+ }
+ case EOF: {
+ DBG_PRINT_1("sscanf input error");
+ result.errorcode = 1;
+ return result;
+ }
+ default: {
+ DBG_PRINT_1("sscanf failed to match everything");
+ result.errorcode = 1;
+ return result;
+ }
+ }
+
+ if (strcasecmp(label, "Total") == 0) {
+ // Total line, ignore this
+ continue;
+ }
dsktotal_mb = dsktotal_mb / config.conversion_factor;
/* AIX lists percent used, so this converts to dskfree in MBs */
More information about the Commits
mailing list