feat: Add stale process monitor, users route, landing page, archive old scripts
- Add backend stale process monitoring API (/api/stale-processes) - Add users management route - Add frontend landing page and stale process monitor UI on /scraper-tools - Move old development scripts to backend/archive/ - Update frontend build with new features 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude <noreply@anthropic.com>
This commit is contained in:
248
scripts/stale-process-monitor.sh
Executable file
248
scripts/stale-process-monitor.sh
Executable file
@@ -0,0 +1,248 @@
|
||||
#!/bin/bash
|
||||
# Stale Process Monitor
|
||||
# Manages and cleans up stale background processes from Claude Code sessions
|
||||
|
||||
set -e
|
||||
|
||||
# Colors for output
|
||||
RED='\033[0;31m'
|
||||
GREEN='\033[0;32m'
|
||||
YELLOW='\033[1;33m'
|
||||
BLUE='\033[0;34m'
|
||||
NC='\033[0m' # No Color
|
||||
|
||||
# Process patterns to monitor
|
||||
STALE_PATTERNS=(
|
||||
"kubectl port-forward"
|
||||
"npm run dev"
|
||||
"npx tsx"
|
||||
"node dist/index.js"
|
||||
"docker push"
|
||||
"kubectl exec"
|
||||
)
|
||||
|
||||
# Maximum age in minutes before a process is considered stale
|
||||
MAX_AGE_MINUTES=${MAX_AGE_MINUTES:-60}
|
||||
|
||||
print_header() {
|
||||
echo -e "${BLUE}========================================${NC}"
|
||||
echo -e "${BLUE} Stale Process Monitor${NC}"
|
||||
echo -e "${BLUE}========================================${NC}"
|
||||
echo ""
|
||||
}
|
||||
|
||||
list_processes() {
|
||||
local pattern="$1"
|
||||
local count=0
|
||||
|
||||
while IFS= read -r line; do
|
||||
if [[ -n "$line" ]]; then
|
||||
((count++))
|
||||
local pid=$(echo "$line" | awk '{print $1}')
|
||||
local start_time=$(ps -o lstart= -p "$pid" 2>/dev/null || echo "unknown")
|
||||
local elapsed=$(ps -o etime= -p "$pid" 2>/dev/null | tr -d ' ' || echo "unknown")
|
||||
local cmd=$(echo "$line" | awk '{$1=""; $2=""; print $0}' | sed 's/^ *//')
|
||||
|
||||
echo -e " ${YELLOW}PID:${NC} $pid ${YELLOW}Elapsed:${NC} $elapsed"
|
||||
echo -e " ${YELLOW}Cmd:${NC} ${cmd:0:80}..."
|
||||
echo ""
|
||||
fi
|
||||
done < <(ps aux | grep -E "$pattern" | grep -v grep | grep -v "stale-process-monitor")
|
||||
|
||||
return $count
|
||||
}
|
||||
|
||||
show_status() {
|
||||
print_header
|
||||
echo -e "${GREEN}Scanning for potentially stale processes...${NC}"
|
||||
echo ""
|
||||
|
||||
local total=0
|
||||
|
||||
for pattern in "${STALE_PATTERNS[@]}"; do
|
||||
local matches=$(ps aux | grep -E "$pattern" | grep -v grep | grep -v "stale-process-monitor" | wc -l)
|
||||
if [[ $matches -gt 0 ]]; then
|
||||
echo -e "${YELLOW}[$pattern]${NC} - $matches process(es) found:"
|
||||
echo ""
|
||||
list_processes "$pattern"
|
||||
((total += matches))
|
||||
fi
|
||||
done
|
||||
|
||||
echo -e "${BLUE}----------------------------------------${NC}"
|
||||
echo -e "${GREEN}Total potentially stale processes: $total${NC}"
|
||||
echo ""
|
||||
|
||||
if [[ $total -eq 0 ]]; then
|
||||
echo -e "${GREEN}No stale processes detected.${NC}"
|
||||
fi
|
||||
}
|
||||
|
||||
kill_pattern() {
|
||||
local pattern="$1"
|
||||
local dry_run="$2"
|
||||
|
||||
# Get PIDs from the second column (proper PID column in ps aux)
|
||||
local pids=$(ps aux | grep -E "$pattern" | grep -v grep | grep -v "stale-process-monitor" | awk '{print $2}')
|
||||
|
||||
if [[ -z "$pids" ]]; then
|
||||
echo -e "${YELLOW}No processes matching '$pattern'${NC}"
|
||||
return 0
|
||||
fi
|
||||
|
||||
for pid in $pids; do
|
||||
# Validate that it's actually a number
|
||||
if [[ "$pid" =~ ^[0-9]+$ ]]; then
|
||||
if [[ "$dry_run" == "true" ]]; then
|
||||
echo -e "${YELLOW}[DRY-RUN] Would kill PID $pid${NC}"
|
||||
else
|
||||
echo -e "${RED}Killing PID $pid...${NC}"
|
||||
kill -9 "$pid" 2>/dev/null || echo -e "${YELLOW} (already dead)${NC}"
|
||||
fi
|
||||
fi
|
||||
done
|
||||
}
|
||||
|
||||
clean_all() {
|
||||
local dry_run="$1"
|
||||
|
||||
print_header
|
||||
|
||||
if [[ "$dry_run" == "true" ]]; then
|
||||
echo -e "${YELLOW}DRY RUN MODE - No processes will be killed${NC}"
|
||||
else
|
||||
echo -e "${RED}CLEANING ALL STALE PROCESSES${NC}"
|
||||
fi
|
||||
echo ""
|
||||
|
||||
for pattern in "${STALE_PATTERNS[@]}"; do
|
||||
echo -e "${BLUE}Processing: $pattern${NC}"
|
||||
kill_pattern "$pattern" "$dry_run"
|
||||
echo ""
|
||||
done
|
||||
|
||||
echo -e "${GREEN}Cleanup complete.${NC}"
|
||||
}
|
||||
|
||||
clean_port_forwards() {
|
||||
local dry_run="$1"
|
||||
|
||||
print_header
|
||||
echo -e "${BLUE}Cleaning kubectl port-forward processes...${NC}"
|
||||
echo ""
|
||||
|
||||
kill_pattern "kubectl port-forward" "$dry_run"
|
||||
|
||||
echo ""
|
||||
echo -e "${GREEN}Port-forward cleanup complete.${NC}"
|
||||
}
|
||||
|
||||
clean_dev_servers() {
|
||||
local dry_run="$1"
|
||||
|
||||
print_header
|
||||
echo -e "${BLUE}Cleaning npm run dev processes...${NC}"
|
||||
echo ""
|
||||
|
||||
kill_pattern "npm run dev" "$dry_run"
|
||||
kill_pattern "vite" "$dry_run"
|
||||
kill_pattern "node.*dist/index.js" "$dry_run"
|
||||
|
||||
echo ""
|
||||
echo -e "${GREEN}Dev server cleanup complete.${NC}"
|
||||
}
|
||||
|
||||
interactive_menu() {
|
||||
while true; do
|
||||
print_header
|
||||
echo "Options:"
|
||||
echo " 1) Show status (list all stale processes)"
|
||||
echo " 2) Clean all stale processes"
|
||||
echo " 3) Clean all (dry-run)"
|
||||
echo " 4) Clean port-forwards only"
|
||||
echo " 5) Clean dev servers only"
|
||||
echo " 6) Clean specific pattern"
|
||||
echo " q) Quit"
|
||||
echo ""
|
||||
read -p "Select option: " choice
|
||||
|
||||
case $choice in
|
||||
1) show_status ;;
|
||||
2) clean_all "false" ;;
|
||||
3) clean_all "true" ;;
|
||||
4) clean_port_forwards "false" ;;
|
||||
5) clean_dev_servers "false" ;;
|
||||
6)
|
||||
read -p "Enter pattern to clean: " pattern
|
||||
kill_pattern "$pattern" "false"
|
||||
;;
|
||||
q|Q) exit 0 ;;
|
||||
*) echo -e "${RED}Invalid option${NC}" ;;
|
||||
esac
|
||||
|
||||
echo ""
|
||||
read -p "Press Enter to continue..."
|
||||
done
|
||||
}
|
||||
|
||||
usage() {
|
||||
echo "Usage: $0 [command]"
|
||||
echo ""
|
||||
echo "Commands:"
|
||||
echo " status Show all potentially stale processes"
|
||||
echo " clean Clean all stale processes"
|
||||
echo " clean-dry Dry-run cleanup (show what would be killed)"
|
||||
echo " ports Clean kubectl port-forward processes only"
|
||||
echo " devs Clean dev server processes only"
|
||||
echo " kill <pat> Kill processes matching pattern"
|
||||
echo " interactive Interactive menu mode"
|
||||
echo ""
|
||||
echo "Environment variables:"
|
||||
echo " MAX_AGE_MINUTES Maximum process age before considered stale (default: 60)"
|
||||
echo ""
|
||||
echo "Examples:"
|
||||
echo " $0 status"
|
||||
echo " $0 clean"
|
||||
echo " $0 kill 'kubectl port-forward'"
|
||||
}
|
||||
|
||||
# Main
|
||||
case "${1:-}" in
|
||||
status)
|
||||
show_status
|
||||
;;
|
||||
clean)
|
||||
clean_all "false"
|
||||
;;
|
||||
clean-dry)
|
||||
clean_all "true"
|
||||
;;
|
||||
ports)
|
||||
clean_port_forwards "false"
|
||||
;;
|
||||
devs)
|
||||
clean_dev_servers "false"
|
||||
;;
|
||||
kill)
|
||||
if [[ -z "${2:-}" ]]; then
|
||||
echo "Error: Pattern required"
|
||||
usage
|
||||
exit 1
|
||||
fi
|
||||
kill_pattern "$2" "false"
|
||||
;;
|
||||
interactive|i)
|
||||
interactive_menu
|
||||
;;
|
||||
help|-h|--help)
|
||||
usage
|
||||
;;
|
||||
"")
|
||||
show_status
|
||||
;;
|
||||
*)
|
||||
echo "Unknown command: $1"
|
||||
usage
|
||||
exit 1
|
||||
;;
|
||||
esac
|
||||
Reference in New Issue
Block a user