In enterprise server environments, maintaining patch compliance is crucial for security and stability. For systems using yum package management (RHEL, CentOS, etc.), administrators often need to verify when the last system-wide update was performed - particularly when:
- Auditing security compliance
- Maintaining change control procedures
- Monitoring automated update systems
While yum doesn't provide a built-in command to query the last update timestamp, several reliable methods exist:
Method 1: Parsing yum Log Files
The most robust approach examines yum's transaction logs:
# Check current log
last_update=$(grep -i "Updated:" /var/log/yum.log | tail -1 | awk '{print $1,$2}')
# Include rotated logs if needed
if [ -z "$last_update" ]; then
last_update=$(zgrep -h "Updated:" /var/log/yum.log* | tail -1 | awk '{print $1,$2}')
fi
echo "Last yum update: $last_update"
Method 2: Querying RPM Database
For systems with frequent package updates, this method provides more granular data:
# Get installation times of all packages, sorted
rpm -qa --last | head -n 10
Here's an enhanced version suitable for Nagios/Icinga monitoring:
#!/bin/bash
# Thresholds (days)
WARNING_DAYS=14
CRITICAL_DAYS=30
# Get last update from logs
LAST_UPDATE=$(zgrep -h "Updated:" /var/log/yum.log* | tail -1)
if [ -z "$LAST_UPDATE" ]; then
echo "UNKNOWN: No yum updates found in logs"
exit 3
fi
# Extract and parse date
LOG_DATE=$(echo "$LAST_UPDATE" | awk '{print $1,$2}')
EPOCH_TIME=$(date -d "$LOG_DATE" +%s 2>/dev/null)
CURRENT_EPOCH=$(date +%s)
if [ -z "$EPOCH_TIME" ]; then
echo "UNKNOWN: Failed to parse date from logs"
exit 3
fi
# Calculate days since last update
DAYS_ELAPSED=$(( (CURRENT_EPOCH - EPOCH_TIME) / 86400 ))
# Evaluate thresholds
if [ "$DAYS_ELAPSED" -ge "$CRITICAL_DAYS" ]; then
echo "CRITICAL: Last yum update $DAYS_ELAPSED days ago on $LOG_DATE"
exit 2
elif [ "$DAYS_ELAPSED" -ge "$WARNING_DAYS" ]; then
echo "WARNING: Last yum update $DAYS_ELAPSED days ago on $LOG_DATE"
exit 1
else
echo "OK: Last yum update $DAYS_ELAPSED days ago on $LOG_DATE"
exit 0
fi
For more accurate results in complex environments:
- Combine log parsing with rpm --last data
- Use journalctl for systems with journald:
journalctl -u yum -n 20
- Consider package-specific updates vs system-wide updates
For newer systems with yum history available:
yum history | grep -E "Update|Upgrade" | tail -n 5
In enterprise Linux environments, particularly those with staged deployment pipelines, tracking the last successful yum update
operation is crucial for maintaining security compliance and operational continuity. The problem compounds when managing multiple servers across different environments (staging vs production) with varying update policies.
The most straightforward approach examines /var/log/yum.log
:
# Basic timestamp extraction
LAST_UPDATE=$(grep "Updated:" /var/log/yum.log | tail -1 | awk '{print $1,$2}')
echo "Last update occurred on: $LAST_UPDATE"
However, this has several limitations:
- Log rotation may archive older entries in
yum.log.1
- Doesn't distinguish between full system updates and single package updates
- Date format requires additional parsing for automation
Here's a more robust implementation that handles log rotation and provides machine-readable output:
#!/bin/bash
# Check both current and rotated logs
for LOG in /var/log/yum.log /var/log/yum.log.*; do
[ -f "$LOG" ] || continue
# Extract newest timestamp matching system update pattern
TS=$(grep -E "Updated:.*(\\$|yum)" "$LOG" | \
tail -1 | \
awk '{print $1" "$2" "$NF}' | \
sed 's/:[0-9]\+$//')
[ -n "$TS" ] && break
done
# Convert to epoch for monitoring systems
EPOCH=$(date -d "$TS" +%s 2>/dev/null)
if [ -n "$EPOCH" ]; then
echo "LAST_YUM_UPDATE=$EPOCH"
else
echo "ERROR: Unable to determine last update time"
exit 1
fi
For systems using yum version 3.2.22+ (RHEL/CentOS 6+), the history feature provides more structured data:
# Get last update transaction ID
LAST_TID=$(yum history | awk '/Update/ {print $1}' | tail -1)
# Get detailed timestamp
yum history info "$LAST_TID" | grep -E "Begin time|Command line"
For Nagios/Icinga integration, here's a complete NRPE plugin implementation:
#!/bin/bash
WARNING_DAYS=14
CRITICAL_DAYS=30
# Get last update timestamp
LAST_UPDATE=$(grep -h "Updated:" /var/log/yum.log* | \
sort -r | \
head -1 | \
awk '{print $1,$2,$3}')
# Convert to days since update
NOW_EPOCH=$(date +%s)
LAST_EPOCH=$(date -d "$LAST_UPDATE" +%s 2>/dev/null || echo 0)
DAYS_SINCE=$(( (NOW_EPOCH - LAST_EPOCH) / 86400 ))
# Evaluation logic
if [ $LAST_EPOCH -eq 0 ]; then
echo "UNKNOWN: Could not parse last update time"
exit 3
elif [ $DAYS_SINCE -ge $CRITICAL_DAYS ]; then
echo "CRITICAL: Last yum update was $DAYS_SINCE days ago"
exit 2
elif [ $DAYS_SINCE -ge $WARNING_DAYS ]; then
echo "WARNING: Last yum update was $DAYS_SINCE days ago"
exit 1
else
echo "OK: Last yum update was $DAYS_SINCE days ago"
exit 0
fi
- Systems using DNF instead of yum will require different logging paths
- Minimal container environments may not maintain yum logs
- Automated patch management systems might bypass standard yum commands
For environments where log parsing isn't reliable, consider creating a marker file during your update procedures:
# In your update script:
touch /var/lib/yum/last_update.timestamp
chmod 644 /var/lib/yum/last_update.timestamp