Services
banshee/services-collection/services/redis/ssh/
memory
The memory a Redis server uses against maxmemory or the machine, its fragmentation and its evicted keys, by SSH and redis-cli INFO.
by banshee1 installation1 version
Published on October 27, 2026. First version.
// The memory of a Redis server, by SSH and redis-cli INFO on its server: the memory used, against maxmemory
// when one is set or against the machine's memory when none is, the fragmentation, and the keys evicted to
// make room. The password, when Redis asks for one, stays on the server.
need('protocol:ssh');
$port = variable('redis:port', 'integer', array(
'label' => 'Port',
'help' => 'The port Redis listens on, on the server itself.',
'default' => 6379,
));
$password_file = variable('redis:password-file', 'text', array(
'label' => 'Password file',
'help' => 'The path, on the server, of a file the SSH account reads and that holds the Redis password alone, for instance /home/monitoring/.redis-password. Empty: no password.',
'required' => false,
));
output('used', 'number', array('label' => 'Memory used', 'unit' => 'MiB'));
output('used-percent', 'number', array('label' => 'Memory used against its limit', 'unit' => '%'));
output('limit', 'text', array('label' => 'Limit counted against'));
output('fragmentation', 'number', array('label' => 'Fragmentation ratio'));
output('evicted', 'number', array('label' => 'Keys evicted since start'));
watch.above('full', 'Memory nearly full', 'used-percent', array('warning' => 80, 'critical' => 90));
watch.above('fragmentation', 'Memory fragmented', 'fragmentation', array('warning' => 1.5, 'for' => '3 runs', 'enabled' => false));
watch.increase('evicted', 'Keys evicted', 'evicted', array('warning' => 0, 'window' => '1 h', 'enabled' => false));
// INFO through redis-cli, to the Redis of the server on its port: one line "field:value" per figure. A
// password goes from its file into REDISCLI_AUTH, which redis-cli reads, by the shell of the server: it is
// never written on a command line, and never leaves the server. LC_ALL=C keeps the messages in English.
function redis_info($port, $password_file) {
$command = 'LC_ALL=C redis-cli -p ' . $port;
if ($password_file != '') {
if (list.count(text.match($password_file, '^/[A-Za-z0-9_./-]+$')) == 0) {
fail('misconfigured', 'The password file must be an absolute path of letters, digits and . _ / -');
}
$command = 'REDISCLI_AUTH="$(cat \'' . $password_file . '\')" ' . $command;
}
$read = ssh.run($command . ' INFO');
$said = $read['output'] . $read['errors'];
if (!text.contains($read['output'], 'redis_version:')) {
if (text.contains($said, 'Could not connect') || text.contains($said, 'Connection refused')) {
fail('critical', 'Redis is not running', $said);
}
if (list.count(text.match($said, 'NOAUTH|WRONGPASS|NOPERM|invalid password')) > 0) {
fail('misconfigured', 'Redis refuses the account', $said);
}
fail('misconfigured', 'redis-cli did not answer INFO', $said);
}
$info = array();
foreach (text.lines($read['output']) as $line) {
$m = text.match($line, '^([a-z0-9_]+):(.*)$');
if (list.count($m) > 0) {
$info[$m[1]] = $m[2];
}
}
return $info;
}
$info = redis_info($port, $password_file);
// used_memory is what Redis allocated for its data; maxmemory 0 means no limit, and Redis then grows until the
// machine runs out (total_system_memory, from Redis 3.2 on).
$used = $info['used_memory'];
$limit = 'maxmemory';
$total = list.get($info, 'maxmemory', 0);
if ($total == 0) {
$limit = 'system';
$total = list.get($info, 'total_system_memory', 0);
}
if ($total == 0) {
fail('misconfigured', 'Redis gives neither maxmemory nor total_system_memory', 'Redis 3.2 or later is needed.');
}
value('used', number.round($used / 1048576, 1));
value('used-percent', number.round(100 * $used / $total, 1));
value('limit', $limit);
value('fragmentation', $info['mem_fragmentation_ratio']);
value('evicted', $info['evicted_keys']);