When debugging memory issues on headless servers, traditional tools like top
or htop
provide textual output but lack visual representation. While solutions like Munin track historical trends, we often need snapshot visualizations for immediate analysis.
The most lightweight approach converts process memory data into visual formats through these steps:
# Step 1: Get process memory data
ps -eo pid,user,%mem,command --sort=-%mem | head -n 10 > process_mem.txt
# Step 2: Convert to CSV format
awk 'NR>1 {print $1","$2","$3}' process_mem.txt > mem_data.csv
Here's a complete Python script generating a pie chart PNG:
import pandas as pd
import matplotlib.pyplot as plt
def generate_mem_chart():
# Read process data
df = pd.read_csv('mem_data.csv', names=['PID','User','Memory'])
# Create figure without GUI backend
plt.switch_backend('Agg')
fig, ax = plt.subplots(figsize=(10,8))
# Generate pie chart
ax.pie(df['Memory'],
labels=df['User'],
autopct='%1.1f%%',
shadow=True)
ax.set_title('Process Memory Distribution')
plt.savefig('memory_pie.png', dpi=100)
if __name__ == "__main__":
generate_mem_chart()
For interactive filtering, create an HTML file with Chart.js:
<!DOCTYPE html>
<html>
<head>
<script src="https://cdn.jsdelivr.net/npm/chart.js"></script>
</head>
<body>
<canvas id="memChart" width="800" height="400"></canvas>
<script>
fetch('mem_data.csv')
.then(response => response.text())
.then(data => {
const rows = data.trim().split('\n');
const chartData = {
labels: [],
datasets: [{
data: [],
backgroundColor: []
}]
};
rows.forEach(row => {
const [pid, user, mem] = row.split(',');
chartData.labels.push(${user} (${pid}));
chartData.datasets[0].data.push(parseFloat(mem));
chartData.datasets[0].backgroundColor.push(
hsl(${Math.random() * 360}, 70%, 50%)
);
});
new Chart(document.getElementById('memChart'), {
type: 'pie',
data: chartData,
options: { responsive: false }
});
});
</script>
</body>
</html>
For regular monitoring, consider these enhancements:
- Add cron job to regenerate visuals periodically
- Implement memory threshold alerts
- Include timestamp in output filenames
When troubleshooting memory issues on headless servers, traditional tools like top
or htop
provide raw numbers but lack visual representation. Here's a Python solution that generates both static HTML/SVG visualizations and PNG outputs without requiring X11.
# Install required packages on Debian/Ubuntu
sudo apt-get install python3-matplotlib python3-psutil
This script creates both interactive HTML (using Plotly) and static PNG outputs:
import psutil
import matplotlib.pyplot as plt
from plotly.graph_objects import Figure, Pie
import plotly.io as pio
def generate_memory_graphs():
processes = []
mem_usages = []
for proc in psutil.process_iter(['pid', 'name', 'memory_percent']):
try:
if proc.info['memory_percent'] > 0.1: # Filter small processes
processes.append(f"{proc.info['name']} (PID: {proc.info['pid']})")
mem_usages.append(proc.info['memory_percent'])
except psutil.NoSuchProcess:
continue
# Generate Matplotlib PNG
plt.figure(figsize=(12, 8))
plt.pie(mem_usages, labels=processes, autopct='%1.1f%%')
plt.title('Process Memory Allocation')
plt.savefig('/tmp/memory_usage.png', dpi=150, bbox_inches='tight')
# Generate Plotly HTML
fig = Figure(data=[Pie(labels=processes, values=mem_usages)])
pio.write_html(fig, '/tmp/memory_usage.html', auto_open=False)
if __name__ == "__main__":
generate_memory_graphs()
For environments without Python available:
#!/bin/bash
# Generate memory data file
ps -eo pid,user,%mem,command --sort=-%mem | awk 'NR<=11 && NR>1 {print $3,$4" ("$1")"}' > /tmp/mem.dat
# Create gnuplot script
cat << EOF > /tmp/mem.gnuplot
set terminal png size 800,600
set output '/tmp/memory_gnuplot.png'
set title "Process Memory Usage"
set style data histograms
set style fill solid
plot '/tmp/mem.dat' using 1:xtic(2) title "Memory %"
EOF
gnuplot /tmp/mem.gnuplot
To make the visualization accessible via web without installing a full monitoring suite:
# Simple Python HTTP server for access
python3 -m http.server 8000 --directory /tmp
Combine with cron for periodic updates:
# Add to crontab -e
*/5 * * * * /usr/bin/python3 /path/to/memory_graph.py
Extend the Python script to include process filtering by memory threshold or process name:
def filter_processes(min_mem=0.5, exclude_list=['systemd', 'sshd']):
return [proc for proc in psutil.process_iter(['pid', 'name', 'memory_percent'])
if proc.info['memory_percent'] > min_mem
and not any(exc in proc.info['name'] for exc in exclude_list)]