Modern PHP 8.1+ System Monitoring for MRTG
A type-safe, cross-platform web service that provides system metrics (CPU, memory, disk, battery, etc.) in MRTG-compatible format. Built as a simpler alternative to SNMP for monitoring remote servers via HTTP(S) endpoints.
- 17 Sensor Types: CPU, Memory, Disk, Battery (6 types), Process count, Folder operations, Network ping
- Cross-Platform: Windows, Linux, macOS, BusyBox (Synology NAS)
- Modern PHP 8.1+: Enums, readonly properties, strict types, match expressions
- Type-Safe: PHPStan level 8 analysis
- Tested: PHPUnit integration and unit tests
- PSR-4 Autoloading: Composer-based dependency management
- 100% Backward Compatible: Existing MRTG configs work unchanged
- PHP 8.1 or higher
- Composer
- Web server (Apache, Nginx, built-in PHP server)
- Shell access for system commands (
exec()enabled)
composer installFor Apache or Nginx, set the document root to the public/ directory:
DocumentRoot /path/to/mrtg_remote_sensor/publicphp -S localhost:8080 -t publicln -s public/index.php index.php# CPU usage
curl "http://localhost/index.php?key=cpu"
# Memory usage
curl "http://localhost/index.php?key=mem"
# Disk usage for root
curl "http://localhost/index.php?key=disk¶m=/"| Sensor Key | Description | Parameters | Example |
|---|---|---|---|
cpu |
CPU load (1-min average) | - | ?key=cpu |
cpu% |
CPU percentage | - | ?key=cpu% |
mem |
Memory usage (bytes) | - | ?key=mem |
mem% |
Memory percentage | - | ?key=mem% |
disk |
Disk usage (bytes) | param=/path |
?key=disk¶m=/ |
disk% |
Disk percentage | param=/path |
?key=disk%¶m=/home |
battery |
Battery percentage (macOS) | - | ?key=battery |
battery% |
Battery remaining (macOS) | - | ?key=battery% |
battery- |
Battery used (macOS) | - | ?key=battery- |
batt_volt |
Battery voltage (macOS) | - | ?key=batt_volt |
batt_amp |
Battery amperage (macOS) | - | ?key=batt_amp |
batt_cycles |
Battery cycles (macOS) | - | ?key=batt_cycles |
proc |
Process count | param=filter |
?key=proc¶m=apache |
foldersize |
Folder size (MB) | param=/path |
?key=foldersize¶m=/var/log |
filecount |
File count | param=/path |
?key=filecount¶m=/tmp |
foldercount |
Subfolder count | param=/path |
?key=foldercount¶m=/etc |
pingtime |
Ping time (ms) | param=host |
?key=pingtime¶m=8.8.8.8 |
key(required): Sensor typeparam(optional): Sensor-specific parameter (path, hostname, filter)options(optional): Additional options (comma-separatedkey=value)config=1(optional): Return full MRTG configuration blockdebug=1(optional): Enable debug output
For file/folder operations, use options for filtering:
?key=filecount¶m=/var&options=recursive=1,name=*.log
Available options:
recursive=1: Enable recursive operationsmtime=<value>: Filter by modification time (passed tofind)name=<pattern>: Filter by filename pattern
Add to your mrtg.cfg:
Target[server_cpu]: `curl -s "http://server/index.php?key=cpu"`
Title[server_cpu]: Server: CPU Usage
PageTop[server_cpu]: <h1>Server: CPU Usage</h1>
MaxBytes[server_cpu]: 500
Options[server_cpu]: gauge,growright,nobanner
Add config=1 to get a complete MRTG configuration block:
curl "http://server/index.php?key=cpu&config=1"Output:
Target[server_cpu_abc123]: `curl -s "http://server/index.php?key=cpu"`
Title[server_cpu_abc123]: server: CPU Usage
PageTop[server_cpu_abc123]: <h1>server: CPU Usage</h1>
ShortLegend[server_cpu_abc123]:
Options[server_cpu_abc123]: gauge,growright,nobanner
MaxBytes[server_cpu_abc123]: 500
kMG[server_cpu_abc123]: k,M,G,T,P
Open public/overview.html in a browser to test all sensor types interactively.
# All tests
composer test
# Unit tests only
vendor/bin/phpunit tests/Unit
# Integration tests only
vendor/bin/phpunit tests/Integrationcomposer analyseRuns PHPStan level 8 analysis on src/ directory.
composer formatApplies PSR-12 coding standards using PHP-CS-Fixer.
.
├── public/ # Web root
│ ├── index.php # Entry point
│ ├── overview.html # Interactive testing UI
│ └── view.html # Single sensor view
├── src/ # PSR-4 source code
│ ├── Cache/ # File caching
│ ├── Command/ # Command execution
│ ├── Enum/ # Type-safe enums
│ ├── Http/ # Request/Response
│ ├── OS/ # OS abstraction layer
│ ├── Sensor/ # Sensor logic & results
│ └── Output/ # MRTG formatting
├── tests/ # PHPUnit tests
│ ├── Unit/ # Unit tests
│ └── Integration/ # Integration tests
├── var/ # Runtime data
│ └── cache/ # Cache files
├── composer.json # Dependencies
├── phpunit.xml # Test configuration
├── phpstan.neon # Static analysis config
└── .php-cs-fixer.php # Code style config
- Enums (PHP 8.1+):
SensorType,OSTypefor type safety - Readonly Properties (PHP 8.1+): Immutable
SensorResultvalue objects - #[\Override] Attribute (PHP 8.1+): Safe method overriding
- Constructor Property Promotion (PHP 8.0+): Concise dependency injection
- Match Expressions (PHP 8.0+): Clean sensor routing
- Union Types (PHP 8.0+): Flexible type hints (
int|float|string) - Strict Types:
declare(strict_types=1)everywhere - Typed Properties (PHP 7.4+): Full type coverage
- Sensor (
Sensor\Sensor): Main business logic, all 17 sensor implementations - OSTools (
OS\OSTools): Abstract base for OS-specific implementationsLinuxTools: Linux/Unix commandsDarwinTools: macOS with battery supportWindowsTools: Windows viawmicBusyBoxTools: Synology NAS
- OSDetector (
OS\OSDetector): Auto-detect operating system - FileCache (
Cache\FileCache): Command output caching - CommandExecutor (
Command\CommandExecutor): Shell command execution - SensorResult (
Sensor\SensorResult): Immutable sensor data (15 properties) - MrtgFormatter (
Output\MrtgFormatter): MRTG output generation - Request (
Http\Request): Readonly request object - Response (
Http\Response): Immutable response with factory methods
- Commands:
sys_getloadavg(),free,df,du,ps,uptime - Full support for all sensor types except battery
- Commands:
sysctl,vm_stat,df,du,system_profiler,ps - Full battery support via
system_profiler SPPowerDataType
- Commands:
wmic(CPU, memory, disk, processes) - Folder operations require PHP COM extension
- Detected via
/usr/syno/synoman/ - Limited command set with fallbacks
- Read-only operations: No write/modify commands executed
- No root/sudo: All commands run with web server privileges
- Input sanitization:
Sensor::sanitize()removes shell metacharacters - Type safety: Strict types and enums prevent type juggling
- Validated parameters: Enum validation for sensor types
Recommended: Restrict access via web server configuration (IP whitelist, basic auth).
- File-based caching: Command output cached (30-3600 seconds)
- Lazy loading: PSR-4 autoloading loads classes on demand
- Efficient commands: OS-specific optimizations
- Automatic cleanup: Expired cache files removed
The modernized version maintains 100% API compatibility with the legacy version:
- Same URL parameters and sensor keys
- Same MRTG 4-line output format
- Existing MRTG configurations work unchanged
- Simply run
composer installand point web server topublic/
Note: Requires PHP 8.1+ (uses enums, readonly properties, and match expressions).
See MODERNIZATION_SUMMARY.md for detailed migration information.
On macOS, free command doesn't exist (expected). The DarwinTools class uses vm_stat instead.
Ensure PHP can execute shell commands:
php -r "echo exec('whoami');"If blocked, check disable_functions in php.ini.
Cache is stored in var/cache/. Ensure it's writable:
chmod 755 var/cache- Fork the repository
- Create a feature branch
- Add tests for new functionality
- Run quality checks:
composer test composer analyse composer format - Submit a pull request
This project is open source. Check LICENSE file for details.
- Original concept: Simple alternative to SNMP for MRTG
- Modernization: PHP 8.1+ refactoring with strict types and testing
- Powered by: MRTG (Multi Router Traffic Grapher)
