How to Find and Kill Old Processes in Linux Based on Name and Start Time


2 views

On Linux systems, it's common to encounter processes that appear to be running but are actually stuck in an inactive state. These processes often consume system resources without doing any real work. The challenge is to identify these processes based on:

  • Process name pattern
  • Start time (older than a specified duration)
  • Current state (running but not consuming CPU)

The most reliable approach combines ps with awk for filtering. Here's a basic command to find processes older than 7 days:

ps -eo pid,comm,lstart,etime | awk '{
    # Convert elapsed time to days
    split($5, time, "-");
    if (time[1] >= 7) {
        print $0;
    }
}'

Here's a more complete bash script that:

  1. Finds processes by name pattern
  2. Filters by start time
  3. Provides kill options
#!/bin/bash

# Configuration
PROCESS_NAME="myapp"
MAX_DAYS=7
DRY_RUN=true

# Find processes
ps -eo pid,comm,lstart,etime | grep "$PROCESS_NAME" | awk -v max_days="$MAX_DAYS" '{
    # Parse the elapsed time
    if ($5 ~ /-/) {
        split($5, time, "-");
        if (time[1] >= max_days) {
            print $1 " " $2 " " $3 " " $4 " " $5;
        }
    }
}' | while read -r pid comm _ _ _; do
    if [ "$DRY_RUN" = true ]; then
        echo "Would kill process $pid ($comm)"
    else
        echo "Killing process $pid ($comm)"
        kill -9 "$pid"
    fi
done

For systems with newer tools, you can combine pgrep with process start time checking:

#!/bin/bash

for pid in $(pgrep -f "myapp"); do
    start_time=$(stat -c %Y /proc/$pid)
    current_time=$(date +%s)
    age_days=$(( (current_time - start_time) / 86400 ))
    
    if [ $age_days -gt 7 ]; then
        echo "Killing old process $pid (running for $age_days days)"
        kill $pid
    fi
done

To automate this in cron, save the script and add to crontab:

# Run daily at 3 AM
0 3 * * * /path/to/cleanup_old_processes.sh
  • Always test with DRY_RUN=true first
  • Consider sending SIGTERM before SIGKILL
  • Log the actions for audit purposes
  • Exclude critical system processes from matching

In Linux systems, particularly long-running servers, you'll often encounter processes that appear stuck in a running state but aren't actually consuming any system resources. These "zombie" processes typically occur when:

  • A parent process fails to properly reap its child processes
  • Network connections timeout without proper cleanup
  • Processes get stuck in I/O wait states indefinitely

The most reliable way to identify these processes is using a combination of ps and awk commands. Here's a comprehensive approach:

# Find processes older than 7 days
ps -eo pid,etimes,cmd | 
awk -v cutoff=$((60*60*24*7)) '$2 > cutoff {print $1}' | 
xargs -r ps -fp

# Alternative using process start time
ps -eo pid,lstart,cmd | 
awk '{
    cmd="date +%s -d \""$2" "$3" "$4" "$5" "$6"\"";
    cmd | getline timestamp;
    close(cmd);
    if (systime() - timestamp > 604800) print $1
}' | 
xargs -r ps -fp

When terminating old processes, it's important to do so systematically:

# First try SIGTERM (15)
ps -eo pid,etimes,comm | 
awk -v cutoff=$((60*60*24*7)) '$2 > cutoff && $3 ~ /your_process_name/ {print $1}' | 
xargs -r kill -15

# Force kill with SIGKILL (9) if needed after delay
sleep 30
ps -eo pid,etimes,comm | 
awk -v cutoff=$((60*60*24*7)) '$2 > cutoff && $3 ~ /your_process_name/ {print $1}' | 
xargs -r kill -9

Here's a production-ready script you can add to cron:

#!/bin/bash

# Configuration
PROCESS_NAME="your_app_name"
MAX_AGE_DAYS=7
LOG_FILE="/var/log/process_cleaner.log"

# Calculate seconds
max_age_seconds=$((MAX_AGE_DAYS * 24 * 60 * 60))

# Log function
log() {
    echo "[$(date '+%Y-%m-%d %H:%M:%S')] $1" >> "$LOG_FILE"
}

# Main logic
log "Starting process cleanup for $PROCESS_NAME older than $MAX_AGE_DAYS days"

# Find and kill processes
ps -eo pid,etimes,comm | 
awk -v cutoff="$max_age_seconds" -v proc="$PROCESS_NAME" \
'$2 > cutoff && $3 ~ proc {print $1}' | 
while read -r pid; do
    log "Terminating PID $pid (SIGTERM)"
    kill -15 "$pid" && log "Successfully terminated PID $pid" || log "Failed to terminate PID $pid"
done

# Verify and force kill if needed
sleep 30
ps -eo pid,etimes,comm | 
awk -v cutoff="$max_age_seconds" -v proc="$PROCESS_NAME" \
'$2 > cutoff && $3 ~ proc {print $1}' | 
while read -r pid; do
    log "Force killing PID $pid (SIGKILL)"
    kill -9 "$pid" && log "Successfully force killed PID $pid" || log "Failed to force kill PID $pid"
done

log "Cleanup completed"

For more advanced process management, consider these alternatives:

  • htop - Interactive process viewer with filtering capabilities
  • pgrep/pkill - Process grepping utilities with pattern matching
  • systemd-cgtop - For systems using systemd

When running this in cron:

  • Add proper locking to prevent multiple instances
  • Consider process trees - sometimes you need to kill parent processes
  • Monitor system load before executing intensive operations
  • Log rotation for the output file