* docs: update stale PHP/MySQL/MariaDB version requirements - Requirements.md: PHP 5.4 -> 8.1 (matches 1.2.31+ requirement note) - Requirements.md: MySQL 5.6 -> 5.7, MariaDB 5.5 -> 10.2 (current minimums) - Requirements.md: MySQL section header updated to >= 5.7 / 10.2 - Requirements.md, Install-Under-CentOS_LAMP.md, Install-Under-CentOS_LEMP.md, Installing-Under-Windows.md: comment out innodb_file_format and innodb_large_prefix (removed in MySQL 8.0 / MariaDB 10.3+) Signed-off-by: Thomas Vincent <thomasvincent@gmail.com> * docs: upgrade http:// links to https:// and fix dead wiki URLs - Upgrade http:// to https:// in 8 files: General-Installing-Instructions.md, Graph-Templates.md, How-To-SSH-Tunnels.md, Plugin-Development.md, Standards-Code-Formatting.md, Templates.md, Upgrading-Cacti-Under-Windows.md - Replace two dead docs.cacti.net wiki links: How-To-SSH-Tunnels.md: old wiki SNMP guide -> Net-SNMP man page Plugin-Syslog.md: dead plugin:syslog.config -> plugin_syslog repo Signed-off-by: Thomas Vincent <thomasvincent@gmail.com> * docs: fix technically inaccurate MySQL configuration recommendations - innodb_additional_mem_pool_size: removed in MySQL 5.7.4 / MariaDB 10.0; replaced with removal notice in Requirements.md and comments in Install-Under-CentOS_LAMP.md and Install-Under-CentOS_LEMP.md - max_heap_table_size: clarify ">= 5" means ">= 5% of system RAM" - innodb_buffer_pool_size: clarify ">= 25" means ">= 25% of system RAM" Signed-off-by: Thomas Vincent <thomasvincent@gmail.com> * docs: add missing required PHP extensions to Requirements.md Add dom, mysqlnd, pcntl, Phar, and sqlite3 — all declared as required in composer.json but absent from the module list. pcntl is Linux-only (process control for the poller). Signed-off-by: Thomas Vincent <thomasvincent@gmail.com> * docs: fix 36 spelling errors across 19 documentation files Corrections detected by codespell: - somone->someone, Walkthough->Walkthrough, GUAGE->GAUGE - asociate->associate, messege->message, therefor->therefore - get's->gets, Proxys->Proxies, paralelisation->parallelization - parms->params (6 instances in script data query examples) - finialise->finalise, buildin->built-in, everytime->every time - Unistall->Uninstall, resiliant->resilient, build-in->built-in - requriments->requirements (2 instances), explanitory->explanatory (3 instances) - fro->for, invole->involve, reulting->resulting - stauts->status, tge->the Signed-off-by: Thomas Vincent <thomasvincent@gmail.com> * ci: add codespell spelling check workflow for documentation Adds GitHub Actions workflow that runs codespell==2.4.1 on all Markdown files on every push/PR to main. Also adds .codespell.cfg to skip binary and generated files (JSON, shell scripts, HTML, images). Update .gitignore to allow .github directory (was blocked by .git* glob). Signed-off-by: Thomas Vincent <thomasvincent@gmail.com> * docs: improve voice, consistency, and note formatting across 10 files - Convert passive/impersonal constructions to active voice - Standardize NOTE -> Note in blockquotes for consistency - Reformat inline IMPORTANT/Note callouts as blockquotes - Fix awkward phrasing in LXC container notes - Consolidate fragmented note bullets into single blockquote Signed-off-by: Thomas Vincent <thomasvincent@gmail.com> * docs: fix technical accuracy and correct typos across 10 files - Requirements.md: clarify Composer is for source/develop installs only; RRDtool minimum updated to 1.5+ (1.8+ for 1.3.x); php-snmp section rewritten to describe selective fallback behavior; SELinux/AppArmor advice reworded to recommend policy exceptions over blanket disable - Spine.md: fix PHP Script Server range (10 -> 15); fix 'senstivive' and 'Davices' typos - Trees.md: fix broken table rows split across lines; 'Sporting' -> 'Sorting' - Data-Sources.md: restructure storage table to standard 3-column layout; fix '19b' unit typo -> '19kb' - How-To-SNMP-Custom-Script.md: convert bold/backtick commands to proper fenced code blocks; fix 'intex' and 'BNSMPD' typos - Plugins.md: fix 'onfiguration' typo; fix YouTube thumbnail http -> https; fix 'Tuturial' typo - Standards-Security.md: fix 'invalidate' -> 'invalid' - template_apache_config.md: fix 'apcache2' -> 'apache2' - device-template-specific-proxmox.md: replace service file edit with drop-in approach; remove ProtectSystem=off/ProtectHome=off; add note on minimal required systemd overrides - resource/xml/query_interface_traffic.php: http -> https URL Signed-off-by: Thomas Vincent <thomasvincent@gmail.com> * docs: rename CentOS install guides to Enterprise Linux; fix grammar, logic, and security flaws - Rename Install-Under-CentOS_LAMP.md → Install-Under-Enterprise-Linux-LAMP.md - Rename Install-Under-CentOS_LEMP.md → Install-Under-Enterprise-Linux-LEMP.md - Update README.md ToC links to match new filenames and correct labels LAMP fixes: - Title updated to reflect RHEL/Rocky Linux/AlmaLinux coverage - Fix step numbering: "2.Install" / "3.Enable" missing space after number - Spine build deps: restructure for EL7/EL8/EL9+ separately; EL8 was missing package install after repo enable; EL9+ uses 'crb' not 'powertools' - SELinux URL: fix quadruple-slash typo; switch to English wiki URL LEMP fixes: - Title: "CentOS 7" → "Enterprise Linux (RHEL / Rocky Linux / AlmaLinux)" - TLS: remove TLSv1 and TLSv1.1 (RFC 8996 prohibited, fails OpenSSL 3.x); set ssl_protocols TLSv1.2 TLSv1.3 - Ciphers: remove DH+3DES (Sweet32 / CVE-2016-2183) - HTTP redirect: uncomment return 301 (comment claiming nginx lacks support for 'return' has been wrong since nginx 0.8 / 2009) - PHP location block: fix 'alias' → 'root' (alias breaks $document_root in fastcgi_param SCRIPT_FILENAME); add missing semicolon after index directive - Cron: poller path was /var/www/html/cacti but install target throughout this guide is /usr/share/nginx/html/cacti — align them - DB: split GRANT...IDENTIFIED BY into CREATE USER + GRANT (IDENTIFIED BY on GRANT removed in MySQL 8.0 / MariaDB 10.5.2) - Fix comment typo: "Compression increases performance0" → remove trailing 0 - SELinux URL: fix quadruple-slash typo README.md: - Update section 3.1 and 3.2 links to new filenames - Correct labels from "CentOS 7" to "Enterprise Linux" - Fix "Reports Admistrative Interface" → "Administrative" - Fix "requriments" (×2) → "requirements" * docs: remove Install-Under-CentOS_LAMP.md (superseded by Install-Under-Enterprise-Linux-LAMP.md) * docs: remove Install-Under-CentOS_LEMP.md (superseded by Install-Under-Enterprise-Linux-LEMP.md) * docs: update README ToC links and fix typos - Update 3.1 and 3.2 links from CentOS to Enterprise Linux filenames - Correct labels: "CentOS 7" → "Enterprise Linux (RHEL/Rocky/AlmaLinux)" - Fix "Reports Admistrative" → "Reports Administrative" - Fix "requriments" (×2) → "requirements" * docs: fix grammar, logic, and technical errors in remaining install/upgrade guides Installing-Under-Windows.md: - Replace php_mysql.dll with php_pdo_mysql.dll (php_mysql removed in PHP 7.0) - Remove IIS ISAPI steps referencing php8isapi.dll (ISAPI dropped in PHP 8.0); replace with FastCGI instructions via php-cgi.exe - Remove NO_AUTO_CREATE_USER from sql_mode (removed MySQL 8.0, breaks startup) - sort_buffer_size = 200M → 32M with caveat (per-session; 200M causes OOM under load) - Fix step numbering gaps: main list 5→8, IIS 3→5, Finishing 5→8 - "you will have to user 8.3 notation" → "use" - "c:cygwin" → "c:\cygwin" (missing backslash) - "it's subfolders" → "its subfolders" - "A anm example" → "An example" - "verify/udate" → "verify/update" Installing-Under-Ubuntu-Debian.md: - Cron user: apache → www-data (apache user does not exist on Ubuntu/Debian) - CREATE DATABASE: use utf8mb4 directly; remove redundant ALTER DATABASE - php8.1-mbstring listed twice in apt-get install; deduplicated - "may received" → "may receive" - Note php8.1 is EOL; recommend checking current supported release Upgrading-Cacti-Under-Windows.md: - Fix all steps numbered 1. → proper sequential numbering (1–10) - Remove hardcoded MySQL 5.7 path; use generic %MYSQL_HOME% note Upgrading-Cacti-Under-FreeBSD.md: - mysqldump: remove contradictory -l / --lock-tables=false flags; replace with --single-transaction (correct for InnoDB, no locking) How-To-SSH-Tunnels.md: - Add prominent note: SSH -L is TCP-only; standard SNMP uses UDP; this guide requires TCP transport configured on snmpd and does not work for most network devices - Fix unclosed code fence after ssh-keygen output block - Replace rc.local persistence with systemd unit (rc.local is deprecated and disabled by default on systemd distros: Ubuntu 16.04+, Debian 9+) - ssh-keygen: recommend ed25519 over RSA * docs: correct PHP 8.1 EOL date, Net-SNMP link, and grammar PHP 8.1 security support ended 31 December 2025, not November 2024. Point the snmpd.conf link at www.net-snmp.org (the sourceforge.io mirror is bot-blocked). Fix 'There a two ways extending' to 'There are two ways to extend'. Signed-off-by: Thomas Vincent <thomasvincent@gmail.com> * ci: fix spelling workflow trigger to target develop, not main The repo's default branch is develop; main hasn't moved since 2023. The workflow's push/pull_request filters targeted main, so it never ran on any PR opened against develop. Signed-off-by: Thomas Vincent <thomasvincent@gmail.com> --------- Signed-off-by: Thomas Vincent <thomasvincent@gmail.com>
8.2 KiB
Debugging
Cacti users sometimes complain about NaN's in their graphs. Unfortunately, there are several reasons for this result. The following is a step-by-step procedure recommended for debugging.
Check Cacti Log File
Your cacti log file should be located at <path_cacti>/log/cacti.log. If it is
not, see Settings, Paths. Check for this kind of error:
SPINE: Host[...] DS[....] WARNING: SNMP timeout detected [500 ms], ignoring host '........'
For "reasonable" timeouts, this may be related to a snmpbulkwalk issue. To
change this, see Settings, Poller and lower the value for The Maximum SNMP OIDs Per SNMP Get Request. Start at a value of 2 and increase it again, if the
poller starts working. (1 or less disables snmpbulkwalk) Some agent's don't have
the horsepower to deliver that many OIDs at a time. Therefore, we can reduce the
number for those older/under-powered devices.
Check Basic Data Gathering
For scripts, run them as cactiuser from CLI to check basic functionality. E.g.
for a Perl script named your-perl-script.pl with parameters "p1 p2" under *nix
this would look like:
su - cactiuser
/full/path/to/perl your-perl-script.pl p1 p2
... (check output)
For SNMP, snmpget the exact OID you're asking for, using same community string
and SNMP version as defined within cacti. For an OID of .1.3.6.1.4.something,
community string of very-secret and version 2 for target host target-host
this would look like
snmpget -c very-secret -v 2c target-host .1.3.6.1.4.something
.... (check output)
Check Cacti's poller
First make sure that crontab always shows poller.php. This program will either
call cmd.php, the PHP based poller or spine, the fast alternative, written in
C. Define the poller you're using at Settings, Poller. Spine has to be
implemented separately, it does not come with cacti by default.
Now, clear ./log/cacti.log (or rename it to get a fresh start)
Then, change Settings, Poller Logging Level to DEBUG for one polling
cycle. You may rename this log as well to avoid more stuff added to it with
subsequent polling cycles.
Now, find the host/data source in question. The Host[<id>] is given
numerically, the <id> being a specific number for that host. Find this <id>
from the Devices menu when editing the host: The URL contains a string like
id=<id>
Check, whether the output is as expected. If not, check your script (e.g.
/full/path/to/perl). If OK, proceed to next step
This procedure may be replaced by running the poller manually for the failing
host only. To do so, you need the <id>, again. If you're using cmd.php, set
the DEBUG logging level as defined above and run
php -q cmd.php <id> <id>
If you're using spine, you may override logging level when calling the poller:
./spine --verbosity=5 <id> <id>
All output is printed to STDOUT in both cases. This procedure allows for repeated tests without waiting for the next polling interval. And there's no need to manually search for the failing host between hundreds of lines of output.
Check MySQL updating
In most cases, this step can be skipped. You may want to return to this step if the next one fails (e.g. no rrdtool update to be found)
From debug log, find the MySQL update statement for that host concerning table
poller_output. On very rare occasions, this will fail. Copy that SQL statement
and paste it to a MySQL session started from CLI. This may as well be done from
some tool like phpMyAdmin. Check the SQL return code.
Check RRDfile updating
Down in the same log, you should find some
rrdtool update <filename> --template ...
You should find exactly one update statement for each file.
RRDfiles should be created by the poller. If it does not create them, it will
not fill them either. If it does check your Poller Cache from Utilities and
search for your target. Does the query show up here?
Check RRDfile ownership
If RRDfiles were created e.g. with root ownership, a poller running as cactiuser will not be able to update those files
cd /var/www/html/cacti/rra
ls -l localhost*
-rw-r--r-- 1 root root 463824 May 31 12:40 localhost_load_1min_5.rrd
-rw-r--r-- 1 cactiuser cactiuser 155584 Jun 1 17:10 localhost_mem_buffers_3.rrd
-rw-r--r-- 1 cactiuser cactiuser 155584 Jun 1 17:10 localhost_mem_swap_4.rrd
-rw-r--r-- 1 cactiuser cactiuser 155584 Jun 1 17:10 localhost_proc_7.rrd
-rw-r--r-- 1 cactiuser cactiuser 155584 Jun 1 17:10 localhost_users_6.rrd
Run the following command to cure this problem
chown cactiuser:cactiuser *.rrd
Check RRDfile numbers
You're perhaps wondering about this step, if the former was OK. But due to data sources MINIMUM and MAXIMUM definitions, it is possible, that valid updates for RRDfiles are suppressed, because MINIMUM was not reached or MAXIMUM was exceeded.
Assuming, you've got some valid rrdtool update in step 3, perform a
rrdtool fetch <RRDfile> AVERAGE
and look at the last 10-20 lines. If you find NaN's there, perform
rrdtool info <RRDfile>
and check the ds[...].min and ds[...].max entries, e.g.
ds[loss].min = 0.0000000000e+00
ds[loss].max = 1.0000000000e+02
In this example, MINIMUM = 0 and MAXIMUM = 100. For a ds.[...].type=GAUGE
verify, that e.g. the number returned by the script does not exceed
ds[...].MAX (same holds for MINIMUM, respectively).
If you run into this, not only should you update the data source definition within the Data Template, but also perform a:
rrdtool tune <RRDfile> --maximum <ds-name>:<new ds maximum>
for all existing RRDfiles belonging to that Data Template.
At this step, it is wise to check step and heartbeat of the RRDfile as
well. For standard 300 seconds polling intervals (step=300), it is wise to set
minimal_heartbeat to 600 seconds. If a single update is missing and the next
one occurs in less than 600 seconds from the last one, RRDtool will interpolate
the missing update. Thus, gaps are "filled" automatically by interpolation. Be
aware of the fact, that this is no "real" data! Again, this must be done in the
Data Template itself and by using rrdtool tune for all existing RRDfiles of
this type.
Check rrdtool graph statement
Last resort would be to check, that the correct data sources are used. Go to
Graph Management and select your Graph. Enable DEBUG Mode to find the whole
rrdtool graph statement. You should notice the DEF statements. They specify
the RRDfile and data source to be used. You may check, that all of them are as
wanted.
RPM Installation
Most rpm installations will setup the crontab entry now. If you've followed the
installation instructions to the letter (which you should always do ;-) ), you
may now have two poller running. That's not a good thing, though. Most rpm
installations will setup cron in /etc/cron.d/cacti
Now check all your crontab, especially /etc/crontab and crontab of users root
and cactiuser. Leave only one poller entry for all of them. Personally, I've
chosen /etc/cron.d/cacti to avoid problems when updating RPM's. Most often,
you won't remember this item when updating lots of RPM's, so I felt more secure
to put it here. And I've made some slight modifications, see
shell> vi /etc/cron.d/cacti
*/5 * * * * cactiuser /usr/bin/php -q /var/www/html/cacti/poller.php > /var/local/log/poller.log 2>&1
This will produce a file /var/local/log/poller.log, which includes some
additional information from each poller's run, such as RRDtool errors. It
occupies only some few bytes and will be overwritten each time.
If you're using the crontab of user "cactiuser" instead, this will look like
shell> crontab -e -u cactiuser
*/5 * * * * /usr/bin/php -q /var/www/html/cacti/poller.php > /var/local/log/poller.log 2>&1
Not NaN, but 0 (zero) values
Pay attention to custom scripts. External commands called from there must be in the $PATH of the cactiuser
running the poller. Use /full/path/to/external/command to avoid ambiguity.
User "criggie" reported an issue with running smartctl. It was complaining "you
are not root" so a quick chmod +s on the script fixed that problem.
Copyright (c) 2004-2026 The Cacti Group