#!/bin/bash # Kill orphaned Claude processes (no TTY or parent is init) # An orphaned Claude process is one where: # - TTY is "?" (no terminal attached), OR # - Parent PID is 1 (adopted by init) LOG_TAG="orphan-claude-killer" # Find all claude processes CLAUDE_PIDS=$(pgrep -x claude 2>/dev/null) if [ -z "$CLAUDE_PIDS" ]; then exit 0 fi for PID in $CLAUDE_PIDS; do # Get TTY and PPID for this process PROC_INFO=$(ps -o tty=,ppid= -p "$PID" 2>/dev/null) if [ -z "$PROC_INFO" ]; then # Process already gone continue fi PROC_TTY=$(echo "$PROC_INFO" | awk '{print $1}') PARENT_PID=$(echo "$PROC_INFO" | awk '{print $2}') ORPHANED=false REASON="" # Check if TTY is "?" (no terminal) if [ "$PROC_TTY" = "?" ]; then ORPHANED=true REASON="no TTY attached" fi # Check if parent PID is 1 (adopted by init) if [ "$PARENT_PID" = "1" ]; then ORPHANED=true REASON="parent is init (PPID=1)" fi if [ "$ORPHANED" = true ]; then # Get process start time for logging START_TIME=$(ps -o lstart= -p "$PID" 2>/dev/null) CPU=$(ps -o %cpu= -p "$PID" 2>/dev/null) MEM=$(ps -o %mem= -p "$PID" 2>/dev/null) logger "$LOG_TAG: Killing orphaned claude process PID=$PID ($REASON) started='$START_TIME' cpu=$CPU% mem=$MEM%" # Kill the process tree (claude may have child processes) pkill -9 -P "$PID" 2>/dev/null kill -9 "$PID" 2>/dev/null fi done