1#!/bin/sh
2
3# Script for atomic update of a configuration file.
4# Writes to a temp file, validates, then atomically replaces the original.
5
6# --- Configuration ---
7CONFIG_FILE="/etc/myapp/config.conf"
8TEMP_SUFFIX=".tmp_update"
9BACKUP_SUFFIX=".bak_"
10
11# --- Helper Functions ---
12
13# Function to perform a syntax check on the configuration file.
14# Replace with actual validation logic for your config file format.
15_validate_config() {
16local file_to_validate="$1"
17echo "Validating configuration file: $file_to_validate..."
18# Example: Check if the file contains a specific keyword (replace with real validation)
19if grep -q "^# END_CONFIG_SECTION$" "$file_to_validate"; then
20echo "Configuration syntax check passed."
21return 0
22else
23echo "Error: Configuration syntax check failed for '$file_to_validate'. Missing '# END_CONFIG_SECTION'." >&2
24return 1
25fi
26}
27
28# Function to create a backup of the original configuration file.
29_create_backup() {
30local original_file="$1"
31local timestamp=$(date +"%Y%m%d_%H%M%S")
32local backup_file="$original_file$BACKUP_SUFFIX$timestamp"
33echo "Creating backup: $backup_file"
34cp "$original_file" "$backup_file"
35if [ $? -ne 0 ]; then
36echo "Error: Failed to create backup of '$original_file'." >&2
37return 1
38fi
39echo "Backup created successfully."
40echo "$backup_file" # Return the backup file name
41return 0
42}
43
44# --- Main Execution ---
45
46# Ensure the configuration file exists before attempting to update.
47if [ ! -f "$CONFIG_FILE" ]; then
48echo "Error: Configuration file '$CONFIG_FILE' not found." >&2
49exit 1
50fi
51
52# Generate a unique temporary file name.
53TEMP_CONFIG_FILE="$CONFIG_FILE$TEMP_SUFFIX.$$"
54
55echo "Starting atomic update of '$CONFIG_FILE'"
56
57# --- Step 1: Write new content to temporary file ---
58# In a real scenario, you would generate the new content here.
59# For demonstration, we'll just append a line and the end marker.
60# IMPORTANT: Replace this with your actual new configuration content generation.
61{
62cat "$CONFIG_FILE" # Copy existing content first
63echo "# New setting added by update script"
64echo "some_new_key=some_value"
65echo "# END_CONFIG_SECTION"
66} > "$TEMP_CONFIG_FILE"
67
68if [ $? -ne 0 ]; then
69echo "Error: Failed to write new content to temporary file '$TEMP_CONFIG_FILE'." >&2
70rm -f "$TEMP_CONFIG_FILE"
71exit 1
72fi
73
74# --- Step 2: Validate the temporary file ---
75if ! _validate_config "$TEMP_CONFIG_FILE"; then
76echo "Configuration update aborted due to validation failure." >&2
77rm -f "$TEMP_CONFIG_FILE"
78exit 1
79fi
80
81# --- Step 3: Create a backup of the original file ---
82# This is a safety measure in case the atomic replace fails or the new file is corrupted.
83BACKUP_FILE=$(_create_backup "$CONFIG_FILE")
84if [ $? -ne 0 ]; then
85echo "Configuration update aborted due to backup failure." >&2
86rm -f "$TEMP_CONFIG_FILE"
87exit 1
88fi
89
90# --- Step 4: Atomically replace the original file ---
91# The 'mv' command is atomic on the same filesystem.
92if mv "$TEMP_CONFIG_FILE" "$CONFIG_FILE"; then
93echo "Configuration file '$CONFIG_FILE' updated successfully."
94echo "Backup created at: $BACKUP_FILE"
95# Optional: remove backup if update is confirmed successful after a delay or manual check
96# echo "Removing backup file: $BACKUP_FILE after a short delay..."
97# sleep 5 # Give time to verify
98# rm -f "$BACKUP_FILE"
99else
100echo "Error: Failed to atomically replace '$CONFIG_FILE' with '$TEMP_CONFIG_FILE'." >&2
101echo "Attempting to restore from backup: $BACKUP_FILE"
102# Attempt to restore from backup
103if mv "$BACKUP_FILE" "$CONFIG_FILE"; then
104echo "Successfully restored '$CONFIG_FILE' from backup."
105else
106echo "Error: Failed to restore '$CONFIG_FILE' from backup. Manual intervention required!" >&2
107fi
108exit 1
109fi
110
111exit 0