cleanup.sh

Download
bash 319 lines 8.6 KB
  1#!/usr/bin/env bash
  2set -euo pipefail
  3
  4# Cleanup and Signal Handling Patterns
  5# Demonstrates proper cleanup of resources and graceful shutdown
  6
  7# ============================================================================
  8# Color definitions for output
  9# ============================================================================
 10
 11readonly RED='\033[0;31m'
 12readonly GREEN='\033[0;32m'
 13readonly YELLOW='\033[1;33m'
 14readonly BLUE='\033[0;34m'
 15readonly CYAN='\033[0;36m'
 16readonly NC='\033[0m' # No Color
 17
 18# ============================================================================
 19# Global Variables for Cleanup Tracking
 20# ============================================================================
 21
 22# Track temporary files and directories
 23declare -a TEMP_FILES=()
 24declare -a TEMP_DIRS=()
 25
 26# Lock file location
 27LOCK_FILE=""
 28
 29# Background process PID
 30BG_PROCESS_PID=""
 31
 32# ============================================================================
 33# Cleanup Functions
 34# ============================================================================
 35
 36# Cleanup function called on script exit
 37cleanup_on_exit() {
 38    local exit_code=$?
 39
 40    echo
 41    echo -e "${CYAN}=== Cleanup Handler (EXIT) ===${NC}"
 42    echo "Exit code: $exit_code"
 43
 44    # Clean up temporary files
 45    if [[ ${#TEMP_FILES[@]} -gt 0 ]]; then
 46        echo "Removing temporary files..."
 47        for file in "${TEMP_FILES[@]}"; do
 48            if [[ -f "$file" ]]; then
 49                rm -f "$file"
 50                echo -e "  ${GREEN}${NC} Removed: $file"
 51            fi
 52        done
 53    fi
 54
 55    # Clean up temporary directories
 56    if [[ ${#TEMP_DIRS[@]} -gt 0 ]]; then
 57        echo "Removing temporary directories..."
 58        for dir in "${TEMP_DIRS[@]}"; do
 59            if [[ -d "$dir" ]]; then
 60                rm -rf "$dir"
 61                echo -e "  ${GREEN}${NC} Removed: $dir"
 62            fi
 63        done
 64    fi
 65
 66    # Remove lock file
 67    if [[ -n "$LOCK_FILE" && -f "$LOCK_FILE" ]]; then
 68        rm -f "$LOCK_FILE"
 69        echo -e "  ${GREEN}${NC} Released lock: $LOCK_FILE"
 70    fi
 71
 72    # Kill background processes
 73    if [[ -n "$BG_PROCESS_PID" ]] && kill -0 "$BG_PROCESS_PID" 2>/dev/null; then
 74        echo "Terminating background process (PID $BG_PROCESS_PID)..."
 75        kill "$BG_PROCESS_PID" 2>/dev/null || true
 76        wait "$BG_PROCESS_PID" 2>/dev/null || true
 77        echo -e "  ${GREEN}${NC} Background process terminated"
 78    fi
 79
 80    echo -e "${GREEN}Cleanup complete${NC}"
 81}
 82
 83# Handle interrupt signal (Ctrl+C)
 84cleanup_on_interrupt() {
 85    echo
 86    echo -e "${YELLOW}=== Cleanup Handler (SIGINT) ===${NC}"
 87    echo "Caught interrupt signal (Ctrl+C)"
 88    echo "Performing graceful shutdown..."
 89
 90    # Exit will trigger cleanup_on_exit
 91    exit 130
 92}
 93
 94# Handle termination signal
 95cleanup_on_terminate() {
 96    echo
 97    echo -e "${YELLOW}=== Cleanup Handler (SIGTERM) ===${NC}"
 98    echo "Caught termination signal"
 99    echo "Performing graceful shutdown..."
100
101    exit 143
102}
103
104# Handle hangup signal
105cleanup_on_hangup() {
106    echo
107    echo -e "${YELLOW}=== Cleanup Handler (SIGHUP) ===${NC}"
108    echo "Caught hangup signal"
109    echo "Performing graceful shutdown..."
110
111    exit 129
112}
113
114# ============================================================================
115# Setup Signal Handlers
116# ============================================================================
117
118setup_traps() {
119    echo -e "${CYAN}Setting up signal handlers...${NC}"
120
121    # EXIT: Always called when script exits (success or failure)
122    trap cleanup_on_exit EXIT
123
124    # SIGINT: Interrupt from keyboard (Ctrl+C)
125    trap cleanup_on_interrupt INT
126
127    # SIGTERM: Termination signal
128    trap cleanup_on_terminate TERM
129
130    # SIGHUP: Hangup detected on controlling terminal
131    trap cleanup_on_hangup HUP
132
133    echo -e "${GREEN}${NC} Signal handlers installed: EXIT, INT, TERM, HUP"
134    echo
135}
136
137# ============================================================================
138# Resource Management Functions
139# ============================================================================
140
141# Create a temporary file and register it for cleanup
142create_temp_file() {
143    local prefix="${1:-temp}"
144    local temp_file
145
146    temp_file=$(mktemp "/tmp/${prefix}.XXXXXX")
147    TEMP_FILES+=("$temp_file")
148
149    echo -e "${GREEN}${NC} Created temp file: $temp_file"
150    echo "$temp_file"
151}
152
153# Create a temporary directory and register it for cleanup
154create_temp_dir() {
155    local prefix="${1:-tempdir}"
156    local temp_dir
157
158    temp_dir=$(mktemp -d "/tmp/${prefix}.XXXXXX")
159    TEMP_DIRS+=("$temp_dir")
160
161    echo -e "${GREEN}${NC} Created temp directory: $temp_dir"
162    echo "$temp_dir"
163}
164
165# Acquire a lock file
166acquire_lock() {
167    local lock_name="${1:-script}"
168    LOCK_FILE="/tmp/${lock_name}.lock"
169
170    if [[ -f "$LOCK_FILE" ]]; then
171        local lock_pid
172        lock_pid=$(cat "$LOCK_FILE")
173
174        if kill -0 "$lock_pid" 2>/dev/null; then
175            echo -e "${RED}${NC} Lock already held by process $lock_pid"
176            return 1
177        else
178            echo -e "${YELLOW}${NC} Stale lock file found, removing..."
179            rm -f "$LOCK_FILE"
180        fi
181    fi
182
183    echo $$ > "$LOCK_FILE"
184    echo -e "${GREEN}${NC} Lock acquired: $LOCK_FILE"
185    return 0
186}
187
188# Start a background process that will be cleaned up
189start_background_process() {
190    echo "Starting background process..."
191
192    (
193        echo "Background process started (PID $$)"
194        for i in {1..30}; do
195            echo "  [BG] Working... ($i/30)"
196            sleep 1
197        done
198        echo "Background process completed"
199    ) &
200
201    BG_PROCESS_PID=$!
202    echo -e "${GREEN}${NC} Background process started (PID $BG_PROCESS_PID)"
203}
204
205# ============================================================================
206# Demo Functions
207# ============================================================================
208
209demo_temp_file_cleanup() {
210    echo -e "${BLUE}=== Temporary File Management Demo ===${NC}\n"
211
212    # Create several temp files
213    local file1 file2 file3
214    file1=$(create_temp_file "demo1")
215    file2=$(create_temp_file "demo2")
216    file3=$(create_temp_file "demo3")
217
218    # Write some data
219    echo "Data in file 1" > "$file1"
220    echo "Data in file 2" > "$file2"
221    echo "Data in file 3" > "$file3"
222
223    echo
224    echo "Temporary files created and will be cleaned up on exit"
225    echo "Total temp files: ${#TEMP_FILES[@]}"
226    echo
227}
228
229demo_temp_dir_cleanup() {
230    echo -e "${BLUE}=== Temporary Directory Management Demo ===${NC}\n"
231
232    # Create temp directory
233    local temp_dir
234    temp_dir=$(create_temp_dir "workspace")
235
236    # Create some files in it
237    touch "$temp_dir/file1.txt"
238    touch "$temp_dir/file2.txt"
239    mkdir -p "$temp_dir/subdir"
240    touch "$temp_dir/subdir/file3.txt"
241
242    echo "Created directory structure:"
243    ls -R "$temp_dir" | sed 's/^/  /'
244    echo
245}
246
247demo_lock_file() {
248    echo -e "${BLUE}=== Lock File Demo ===${NC}\n"
249
250    if acquire_lock "cleanup_demo"; then
251        echo "Performing work while holding lock..."
252        sleep 1
253        echo -e "${GREEN}${NC} Work completed"
254    else
255        echo -e "${RED}${NC} Could not acquire lock"
256        return 1
257    fi
258    echo
259}
260
261demo_background_process_cleanup() {
262    echo -e "${BLUE}=== Background Process Cleanup Demo ===${NC}\n"
263
264    start_background_process
265
266    echo
267    echo "Background process running..."
268    echo "Script will clean it up on exit"
269    sleep 2
270    echo
271}
272
273demo_graceful_shutdown() {
274    echo -e "${BLUE}=== Graceful Shutdown Demo ===${NC}\n"
275
276    echo "This demo shows cleanup on interrupt"
277    echo -e "${YELLOW}Press Ctrl+C to trigger graceful shutdown${NC}"
278    echo "Or wait 5 seconds for normal exit..."
279    echo
280
281    # Simulate long-running work
282    for i in {1..5}; do
283        echo "Working... ($i/5)"
284        sleep 1
285    done
286
287    echo -e "${GREEN}${NC} Work completed normally"
288    echo
289}
290
291# ============================================================================
292# Main Execution
293# ============================================================================
294
295main() {
296    echo -e "${BLUE}╔════════════════════════════════════════════╗${NC}"
297    echo -e "${BLUE}║     Cleanup & Signal Handling Demo        ║${NC}"
298    echo -e "${BLUE}╚════════════════════════════════════════════╝${NC}"
299    echo
300
301    # Setup cleanup handlers
302    setup_traps
303
304    # Run demos
305    demo_temp_file_cleanup
306    demo_temp_dir_cleanup
307    demo_lock_file
308    demo_background_process_cleanup
309    demo_graceful_shutdown
310
311    echo -e "${GREEN}=== Demo Complete ===${NC}"
312    echo "Cleanup will run automatically on exit..."
313    echo
314
315    # EXIT trap will handle cleanup
316}
317
318main "$@"