173 lines
4.5 KiB
Markdown
173 lines
4.5 KiB
Markdown
# cputild - CPU Idle Time Monitor
|
||
|
||
## Overview
|
||
|
||
**cputild** is a lightweight daemon that continuously monitors CPU utilization by reading from `/proc/stat` and writes the current CPU usage percentage to `/tmp/cputild`. It's designed to run as a background service on Linux systems, providing real-time CPU metrics suitable for other tools to consume.
|
||
|
||
## Features
|
||
|
||
- **Continuous Monitoring**: Reads CPU statistics every second
|
||
- **Accurate Calculation**: Uses jiffies-based delta calculation for precise utilization
|
||
- **Signal Handling**: Gracefully responds to `SIGINT` (Ctrl+C) for clean shutdown
|
||
- **Daemon Ready**: Includes systemd service configuration for production use
|
||
- **Efficient I/O**: Reopens files on each iteration for volatile data sources
|
||
|
||
## Requirements
|
||
|
||
- **Operating System**: Linux (requires `/proc/stat` support)
|
||
- **Build Tools**: CMake 3.31+, GCC or compatible C11 compiler
|
||
- **Systemd**: For service management (optional)
|
||
|
||
## Building the Project
|
||
|
||
### Prerequisites
|
||
```bash
|
||
sudo apt install cmake build-essential # Debian/Ubuntu
|
||
sudo yum install cmake gcc # Fedora/CentOS
|
||
```
|
||
|
||
### Build Process
|
||
```bash
|
||
# Using the install script (recommended for production)
|
||
./install.sh
|
||
|
||
# Or manual build
|
||
mkdir build && cd build
|
||
cmake -S ../.. -DCMAKE_BUILD_TYPE=RelWithDebInfo
|
||
cmake --build .
|
||
# Optional: sudo cmake --install ../.. --prefix /usr/local
|
||
```
|
||
|
||
### Build Options
|
||
The `CMakeLists.txt` supports multiple build types:
|
||
- **Debug** (default): For development and debugging
|
||
- **Release**: Optimized without debug symbols
|
||
- **RelWithDebInfo** (used by install.sh): Optimized with debug info
|
||
|
||
```bash
|
||
cmake -S . -B build -DCMAKE_BUILD_TYPE=Release
|
||
cmake --build build
|
||
```
|
||
|
||
## Installation
|
||
|
||
### Automated Installation
|
||
The provided `install.sh` script handles the complete installation process:
|
||
```bash
|
||
./install.sh
|
||
```
|
||
|
||
This script will:
|
||
1. Create a temporary build directory
|
||
2. Configure and build the project with `CMake`
|
||
3. Install the binary to `/usr/local/bin/cputild`
|
||
4. Copy and enable the systemd service
|
||
5. Reload systemd daemon
|
||
|
||
### Manual Installation
|
||
```bash
|
||
sudo cmake --install build --prefix /usr/local
|
||
sudo cp cputild.service /etc/systemd/system/cputild.service
|
||
sudo systemctl daemon-reload
|
||
sudo systemctl enable cputild.service
|
||
sudo systemctl start cputild.service
|
||
```
|
||
|
||
## Systemd Service
|
||
|
||
### Service Behavior
|
||
When running as a systemd service, cputild:
|
||
- Starts automatically on boot (if enabled)
|
||
- Restarts on failure (`Restart=on-failure`)
|
||
- Responds to `SIGINT` for graceful shutdown
|
||
|
||
### Management Commands
|
||
```bash
|
||
# Enable service (start on boot)
|
||
sudo systemctl enable cputild.service
|
||
|
||
# Start service
|
||
sudo systemctl start cputild.service
|
||
|
||
# Check status
|
||
sudo systemctl status cputild.service
|
||
|
||
# Stop service
|
||
sudo systemctl stop cputild.service
|
||
|
||
# Restart service
|
||
sudo systemctl restart cputild.service
|
||
|
||
# View logs
|
||
sudo journalctl -u cputild.service
|
||
```
|
||
|
||
## How It Works
|
||
|
||
### Algorithm
|
||
1. **Read** CPU statistics from `/proc/stat` (in jiffies)
|
||
2. **Parse** the first line: `cpu user nice system idle iowait irq softirq steal guest guest_nice`
|
||
3. **Calculate** active time = user + nice + system + irq + softirq + steal + guest + guest_nice
|
||
4. **Calculate** idle time = iowait + idle
|
||
5. **Compute** delta (difference) since last measurement
|
||
6. **Derive** utilization = active_delta / (active_delta + idle_delta) × 100
|
||
7. **Write** result to `/tmp/cputild` (percentage, 2 decimal places)
|
||
|
||
### Output Format
|
||
```
|
||
/tmp/cputild: 45.23
|
||
```
|
||
The file contains only the number (no newline) for easy parsing by other tools.
|
||
|
||
## Signal Handling
|
||
|
||
The program uses a simple volatile flag pattern for signal handling:
|
||
|
||
| Signal | Effect |
|
||
|--------|--------|
|
||
| `SIGINT` (Ctrl+C) | Gracefully sets `running=0` and terminates |
|
||
|
||
## Troubleshooting
|
||
|
||
### Permission Issues
|
||
```bash
|
||
# If you cannot write to /tmp/cputild
|
||
sudo chmod 666 /tmp
|
||
```
|
||
|
||
### Systemd Service Not Starting
|
||
```bash
|
||
# Check for errors
|
||
sudo systemctl status cputild.service -l
|
||
|
||
# Check journal logs
|
||
sudo journalctl -xeu cputild.service
|
||
```
|
||
|
||
### Manual Test
|
||
```bash
|
||
# Test in foreground
|
||
/usr/local/bin/cputild
|
||
|
||
# Verify output
|
||
cat /tmp/cputild
|
||
```
|
||
|
||
## File Structure
|
||
```
|
||
cputild/
|
||
├── CMakeLists.txt # Build configuration
|
||
├── install.sh # Installation script
|
||
├── cputild.service # systemd unit file
|
||
└── main.c # Source code
|
||
```
|
||
|
||
## Author
|
||
Linus Vogel <linus@linvogel.ch>
|
||
|
||
## License
|
||
Free to use and modify.
|
||
|
||
## Disclaimer
|
||
I have used an LLM to help with formulating most of the comments as well as this
|
||
README file. The actual code I have written myself. |