OCS Inventory NG is an open source IT asset management platform that automatically discovers and inventories hardware and software across every networked device in your organization. When OCS Inventory's Apache/PHP frontend becomes unavailable due to a misconfigured PHP-FPM worker pool exhaustion or an Apache crash, agents attempting to submit their hardware and software inventories receive connection refused errors and queue their submissions locally — but if the outage persists past the agent's local retry window, inventory records are lost; when MySQL grows beyond the available disk space on the inventory server, new agent submissions fail with "disk full" errors while the web console continues functioning, silently discarding inventory data for every device that checks in during the outage; when IP Discovery scans stop running because the scanning agent was reinstalled without re-enabling the feature, your subnet map freezes at its last-known state while new devices and VLAN migrations go undiscovered. These failures leave your software license compliance reports, hardware lifecycle planning, and security audits based on stale or incomplete data.
Vigilmon gives you external visibility into OCS Inventory's inventory pipeline health through HTTP probe monitoring and heartbeat monitors for scheduled inventory and discovery jobs. This tutorial covers both.
Why OCS Inventory Needs External Monitoring
OCS Inventory's failure modes directly impact license compliance and security audit accuracy:
- PHP-FPM worker exhaustion: OCS Inventory's Apache frontend uses PHP-FPM to process agent inventory submissions; during mass re-inventory events (triggered by a policy change that resets all agent inventory intervals), all agents on a large network submit simultaneously, exhausting the PHP-FPM worker pool; new connections queue and then time out, causing agents to discard their inventory submissions when the retry limit is exceeded
- MySQL disk exhaustion: OCS Inventory stores a complete hardware and software inventory for every managed device in MySQL; inventories include CPU, RAM, storage volumes, network interfaces, installed software, registry keys, printers, and monitors; on a 5,000-device deployment, the MySQL database can reach hundreds of gigabytes; when disk fills, INSERTs fail with
ERROR 1114 (HY000): The table is full, and the OCS Inventory server returns HTTP 500 to agents — inventory submissions are silently discarded - Agent submission rate drop: OCS Inventory agents submit inventory on a schedule (daily by default); when a network segment loses connectivity to the OCS server, all agents on that segment stop submitting; the web console shows these devices as "last seen 2 days ago" but only if an operator checks the console — there is no automatic alert on stale inventory count
- Duplicate device accumulation: OCS Inventory creates duplicate records when an agent reinstalls (new agent ID), when a system is re-imaged, or when MAC address changes cause duplicate detection to fail; duplicate records inflate software license counts, causing false over-deployment alerts; deduplication is manual, and without a monitor on duplicate count, the problem silently grows
- IP Discovery scan failure: OCS Inventory's IP Discovery feature uses agents as network scanners for ARP and SNMP discovery; when the designated scanning agent is decommissioned without reassigning the scanning role, subnet discovery stops and the network map freezes — new devices, rogue devices, and VLAN additions go undiscovered
- Administration console unavailability: OCS Inventory's PHP web console is separate from the agent submission endpoint; when the console becomes unavailable (Apache misconfiguration, PHP error in the admin code path), operators cannot access license compliance reports, generate inventory exports, or manage deployment packages — even though agent submissions continue to work
External monitoring with Vigilmon adds:
- Proactive alerting when the OCS Inventory server stops accepting agent submissions
- Database disk growth tracking through periodic checks before the 80% threshold triggers a submission failure
- Agent submission heartbeat monitoring to detect when periodic re-inventory jobs stop completing
- Multi-region probe consensus that filters transient Apache restart gaps from genuine server failures
Step 1: Build an OCS Inventory Health Endpoint
OCS Inventory does not expose a native health endpoint, but its Apache frontend has a predictable XML response format for agent check-ins. Build a dedicated sidecar that probes the submission URL and MySQL health.
PHP Health Endpoint
Add a lightweight health script to your OCS Inventory web root:
<?php
// /var/www/html/ocsreports/health.php
// Probe MySQL connectivity and disk usage
header('Content-Type: application/json');
$host = getenv('OCS_DB_HOST') ?: 'localhost';
$port = getenv('OCS_DB_PORT') ?: '3306';
$user = getenv('OCS_DB_USER') ?: 'ocs';
$pass = getenv('OCS_DB_PASS') ?: '';
$db = getenv('OCS_DB_NAME') ?: 'ocsweb';
$checks = [];
$healthy = true;
// MySQL connectivity check
try {
$pdo = new PDO(
"mysql:host=$host;port=$port;dbname=$db",
$user, $pass,
[PDO::ATTR_TIMEOUT => 5, PDO::ATTR_ERRMODE => PDO::ERRMODE_EXCEPTION]
);
// Check database size (sum of all tables in this schema)
$stmt = $pdo->query(
"SELECT ROUND(SUM(data_length + index_length) / 1024 / 1024, 2) AS size_mb
FROM information_schema.tables
WHERE table_schema = '$db'"
);
$row = $stmt->fetch(PDO::FETCH_ASSOC);
$checks['mysql'] = 'ok';
$checks['db_size_mb'] = (float)$row['size_mb'];
} catch (Exception $e) {
$checks['mysql'] = 'down: ' . $e->getMessage();
$healthy = false;
}
// Disk usage check — alert if /var/lib/mysql or the data directory > 80%
$diskTotal = disk_total_space('/var/lib/mysql');
$diskFree = disk_free_space('/var/lib/mysql');
if ($diskTotal > 0) {
$usedPct = round((($diskTotal - $diskFree) / $diskTotal) * 100, 1);
$checks['disk_used_pct'] = $usedPct;
if ($usedPct > 80) {
$checks['disk_warning'] = "disk ${usedPct}% full — above 80% threshold";
$healthy = false;
}
}
// Stale inventory count — devices not seen in 30 days
if (isset($pdo)) {
try {
$stmt = $pdo->query(
"SELECT COUNT(*) AS stale_count FROM hardware
WHERE DATEDIFF(NOW(), LASTSEEN) > 30"
);
$row = $stmt->fetch(PDO::FETCH_ASSOC);
$checks['stale_devices_30d'] = (int)$row['stale_count'];
} catch (Exception $e) {
$checks['stale_check'] = 'error: ' . $e->getMessage();
}
}
http_response_code($healthy ? 200 : 503);
echo json_encode(['status' => $healthy ? 'ok' : 'degraded', 'checks' => $checks]);
Secure this file by restricting access to the Vigilmon probe IP range in Apache:
# /etc/apache2/conf-available/ocs-health.conf
<Location /ocsreports/health.php>
Require ip 185.199.0.0/16 # Vigilmon probe ranges — adjust to actual
Require ip 127.0.0.1
</Location>
Node.js Sidecar Alternative
If you prefer to keep health check logic outside the web root:
// health/ocs-inventory.js
const express = require('express');
const mysql = require('mysql2/promise');
const { execSync } = require('child_process');
const app = express();
const DB_CONFIG = {
host: process.env.OCS_DB_HOST || 'localhost',
port: parseInt(process.env.OCS_DB_PORT || '3306'),
user: process.env.OCS_DB_USER || 'ocs',
password: process.env.OCS_DB_PASS || '',
database: process.env.OCS_DB_NAME || 'ocsweb',
connectTimeout: 5000,
};
app.get('/health/ocs-inventory', async (req, res) => {
const checks = {};
let healthy = true;
let conn;
try {
conn = await mysql.createConnection(DB_CONFIG);
checks.mysql = 'ok';
const [rows] = await conn.execute(
`SELECT ROUND(SUM(data_length + index_length) / 1024 / 1024, 2) AS size_mb
FROM information_schema.tables WHERE table_schema = ?`,
[DB_CONFIG.database]
);
checks.db_size_mb = parseFloat(rows[0].size_mb || 0);
const [stale] = await conn.execute(
`SELECT COUNT(*) AS cnt FROM hardware WHERE DATEDIFF(NOW(), LASTSEEN) > 30`
);
checks.stale_devices_30d = parseInt(stale[0].cnt || 0);
const [subs] = await conn.execute(
`SELECT COUNT(*) AS cnt FROM hardware WHERE DATEDIFF(NOW(), LASTSEEN) < 1`
);
checks.devices_seen_today = parseInt(subs[0].cnt || 0);
} catch (err) {
checks.mysql = `down: ${err.message}`;
healthy = false;
} finally {
if (conn) conn.end().catch(() => {});
}
// Disk check
try {
const df = execSync("df /var/lib/mysql --output=pcent | tail -1").toString().trim().replace('%','');
const usedPct = parseInt(df);
checks.disk_used_pct = usedPct;
if (usedPct > 80) {
checks.disk_warning = `disk ${usedPct}% full`;
healthy = false;
}
} catch (err) {
checks.disk = `error: ${err.message}`;
}
return res.status(healthy ? 200 : 503).json({
status: healthy ? 'ok' : 'degraded',
checks,
});
});
app.listen(3011, () => console.log('OCS Inventory health sidecar on :3011'));
Step 2: Configure Vigilmon Monitoring
HTTP Monitor — OCS Inventory Server
In your Vigilmon dashboard, create an HTTP monitor for the OCS Inventory health endpoint:
| Field | Value |
|-------|-------|
| Monitor name | OCS Inventory Server |
| URL | http://ocs-server.internal:3011/health/ocs-inventory |
| Method | GET |
| Check interval | Every 2 minutes |
| Expected status | 200 |
| Alert threshold | 2 consecutive failures |
| Regions | Select 2+ regions for consensus |
HTTP Monitor — OCS Agent Submission Endpoint
Also probe the OCS Inventory agent submission endpoint directly to verify agents can reach the server:
| Field | Value |
|-------|-------|
| Monitor name | OCS Inventory Agent Endpoint |
| URL | http://ocs-server.your-org.example.com/ocsinventory |
| Method | GET |
| Expected status | 200 (OCS returns 200 even for GET on agent endpoint) |
| Check interval | Every 5 minutes |
HTTP Monitor — Administration Console
Monitor the OCS Inventory web console separately from the agent endpoint:
| Field | Value |
|-------|-------|
| Monitor name | OCS Inventory Admin Console |
| URL | http://ocs-server.your-org.example.com/ocsreports/ |
| Method | GET |
| Expected status | 200 |
| Check interval | Every 5 minutes |
Heartbeat Monitor — Daily Inventory Submission
Create a heartbeat monitor to verify that scheduled inventory submissions are completing. Configure the heartbeat with a 36-hour timeout (allowing for daily schedules with some drift):
# /etc/cron.daily/ocs-inventory-heartbeat
#!/bin/bash
# Run after OCS agent completes daily inventory submission
/usr/sbin/ocsinventory-agent --server=http://ocs-server.your-org.example.com/ocsinventory \
--logfile=/var/log/ocsinventory-agent.log && \
curl -fsS --max-time 10 \
"https://vigilmon.online/hb/your-heartbeat-token" > /dev/null 2>&1
Step 3: Configure Alerting
Alert Policies
OCS Inventory Server Alert
- Trigger: 2 consecutive failed HTTP probes (HTTP 503 or connection refused)
- Severity: Critical
- Channels: PagerDuty + Slack #infrastructure-alerts
- Message: "OCS Inventory server is unreachable. Agent inventory submissions are failing. IT asset data is not being updated."
Database Disk Alert (via health endpoint 503)
- Trigger: HTTP 503 from health sidecar (disk >80% or MySQL down)
- Severity: High
- Channels: Slack #infrastructure-alerts + email to IT ops
- Message: "OCS Inventory database disk is over 80% capacity. Inventory submissions will fail if disk fills."
Stale Inventory Alert
Add a daily cron check for growing stale device counts and ping a heartbeat only if the count is healthy:
#!/bin/bash
# /etc/cron.daily/ocs-stale-check
STALE=$(mysql -u ocs -p"${OCS_DB_PASS}" ocsweb -sN -e \
"SELECT COUNT(*) FROM hardware WHERE DATEDIFF(NOW(), LASTSEEN) > 30;")
if [ "$STALE" -lt 100 ]; then
# Stale count is within acceptable range
curl -fsS --max-time 10 \
"https://vigilmon.online/hb/your-stale-check-heartbeat" > /dev/null 2>&1
else
echo "WARNING: $STALE devices with inventory older than 30 days" | \
mail -s "OCS Inventory: Stale device alert" ops@your-org.example.com
fi
Configure the heartbeat monitor with a 25-hour timeout so any day where the stale count is out of bounds triggers an alert.
Daily Inventory Heartbeat Alert
- Trigger: Heartbeat not received for 36 hours
- Severity: High
- Channels: Slack #infrastructure-alerts
- Message: "OCS Inventory daily agent submission heartbeat missed. Agent may be offline or unable to reach the OCS server."
Key Metrics Summary
| Metric | Alert Threshold | Impact | |--------|----------------|--------| | OCS Inventory HTTP health | Any 503 or failure | Agent submissions failing; IT asset data not updating | | MySQL database connectivity | Any failure | All inventory submissions discarded | | Database disk usage | >80% | Imminent disk full causing submission failures | | Agent submission rate | Drop >20% vs 7-day avg | Segment of devices unable to reach OCS server | | Stale device count (>30d) | Growing week-over-week | Offline devices undetected; stale license compliance | | Administration console | Any failure | Operators cannot access compliance reports | | Duplicate device count | Growing without deduplication | Inflated license counts; false over-deployment alerts |
Conclusion
OCS Inventory is only as useful as the freshness and completeness of its data. Disk exhaustion, PHP-FPM overload, and agent submission failures silently corrupt your IT asset records without any notification unless you have external monitoring in place. Vigilmon HTTP probes on the OCS Inventory server catch application failures immediately, while heartbeat monitors on scheduled inventory and discovery jobs give you liveness coverage that internal process monitors miss entirely.
Configure the monitors in this tutorial and you will know about OCS Inventory problems before stale inventory data reaches your compliance reports.