#!/bin/bash # Ensure logs and locks directories exist BASE_DIR="/home/shane/foodie_automator" LOG_DIR="$BASE_DIR/logs" LOCK_DIR="$BASE_DIR/locks" mkdir -p "$LOG_DIR" "$LOCK_DIR" || { echo "Error: Failed to create $LOG_DIR or $LOCK_DIR"; exit 1; } # Log function log() { echo "$(date '+%Y-%m-%d %H:%M:%S') - $1" >> "$LOG_FILE" echo "$1" } # Directory to monitor CHECKSUM_FILE="$BASE_DIR/.file_checksum" LOG_FILE="$BASE_DIR/logs/manage_scripts.log" VENV_PYTHON="$BASE_DIR/venv/bin/python" LOCK_DIR="$BASE_DIR/locks" # Calculate checksum of files (excluding logs, JSON files, and venv) calculate_checksum() { find "$BASE_DIR" -type f \ -not -path "$BASE_DIR/logs/*" \ -not -path "$BASE_DIR/*.json" \ -not -path "$BASE_DIR/.file_checksum" \ -not -path "$BASE_DIR/venv/*" \ -not -path "$BASE_DIR/locks/*" \ -exec sha256sum {} \; | sort | sha256sum | awk '{print $1}' } # Check if a script is running (using lock file) check_running() { local script_name="$1" local lock_file="$LOCK_DIR/${script_name}.lock" if [ -f "$lock_file" ]; then local pid=$(cat "$lock_file") if ps -p "$pid" > /dev/null; then log "$script_name is already running (PID: $pid)" return 0 else log "Stale lock file found for $script_name, removing" rm -f "$lock_file" fi fi return 1 } # Run a script and extract sleep_time run_script() { local script="$1" local script_name="${script%.py}" local script_log="$BASE_DIR/logs/${script_name}.log" if check_running "$script_name"; then return 1 fi log "Running $script..." "$VENV_PYTHON" "$script" >> "$script_log" 2>&1 & local pid=$! echo "$pid" > "$LOCK_DIR/${script_name}.lock" wait "$pid" local exit_code=$? if [ $exit_code -eq 0 ]; then log "$script completed successfully" else log "$script failed with exit code $exit_code" fi sleep_time=$(grep "sleep_time:" "$script_log" | tail -n 1 | grep -oP 'sleep_time: \K[0-9]+' || echo $((RANDOM % 601 + 1200))) log "$script completed, sleep_time: $sleep_time seconds" rm -f "$LOCK_DIR/${script_name}.lock" echo "$sleep_time" } # Stop scripts stop_scripts() { log "Stopping scripts..." for script in foodie_automator_*.py; do if [ -f "$script" ] && [ "$script" != "foodie_weekly_thread.py" ] && [ "$script" != "foodie_engagement_tweet.py" ]; then local script_name="${script%.py}" if pkill -TERM -f "$VENV_PYTHON.*$script_name"; then log "Sent TERM to $script_name" sleep 2 pkill -9 -f "$VENV_PYTHON.*$script_name" || true else log "No running $script_name found" fi rm -f "$LOCK_DIR/${script_name}.lock" log "Removed lock file for $script_name" fi done # Mark all running scripts as stopped in system_activity.json "$VENV_PYTHON" -c " import json, os f = '/home/shane/foodie_automator/system_activity.json' if os.path.exists(f): with open(f, 'r') as fh: data = json.load(fh) changed = False for entry in data: if entry.get('status') == 'running': entry['status'] = 'stopped' entry['stop_time'] = __import__('datetime').datetime.now(__import__('datetime').timezone.utc).isoformat() entry['pid'] = None changed = True if changed: with open(f, 'w') as fh: json.dump(data, fh, indent=2) " log "Marked all running scripts as stopped in system_activity.json" log "Scripts stopped." } # Update dependencies update_dependencies() { log "Updating dependencies..." cd "$BASE_DIR" || { log "Failed to change to $BASE_DIR"; exit 1; } if [ ! -d "venv" ]; then python3 -m venv venv log "Created new virtual environment" fi source "$BASE_DIR/venv/bin/activate" # Commenting out dependency installation since packages are already installed and working # "$VENV_PYTHON" -m pip install --upgrade pip # if [ -f "requirements.txt" ]; then # "$VENV_PYTHON" -m pip install -r requirements.txt || { # log "Failed to install requirements.txt, attempting core dependencies" # "$VENV_PYTHON" -m pip install requests openai beautifulsoup4 feedparser praw duckduckgo_search selenium Pillow pytesseract webdriver-manager tweepy python-dotenv flickr-api filelock requests-oauthlib psutil # log "Fallback: Installed core dependencies" # } # else # log "Error: requirements.txt not found, installing core dependencies" # "$VENV_PYTHON" -m pip install requests openai beautifulsoup4 feedparser praw duckduckgo_search selenium Pillow pytesseract webdriver-manager tweepy python-dotenv flickr-api filelock requests-oauthlib psutil # fi log "Dependencies updated." } # Handle stop command if [ "$1" == "stop" ]; then log "Received stop command, stopping all scripts..." stop_scripts if pkill -TERM -f "$VENV_PYTHON.*foodie_engagement_generator"; then log "Sent TERM to foodie_engagement_generator.py" sleep 2 pkill -9 -f "$VENV_PYTHON.*foodie_engagement_generator" || true else log "No running foodie_engagement_generator.py found" fi rm -f "$LOCK_DIR/foodie_engagement_generator.lock" || log "Failed to remove foodie_engagement_generator.lock" log "Stopped foodie_engagement_generator.py" if pkill -TERM -f "$VENV_PYTHON.*foodie_weekly_thread"; then log "Sent TERM to foodie_weekly_thread.py" sleep 2 pkill -9 -f "$VENV_PYTHON.*foodie_weekly_thread" || true else log "No running foodie_weekly_thread.py found" fi rm -f "$LOCK_DIR/foodie_weekly_thread.lock" || log "Failed to remove foodie_weekly_thread.lock" log "Stopped foodie_weekly_thread.py" log "All scripts stopped. Reminder: Disable cron jobs to prevent automatic restarts (crontab -e)." exit 0 fi # Handle start command if [ "$1" == "start" ]; then log "Received start command, starting all scripts..." cd "$BASE_DIR" || { log "Failed to change to $BASE_DIR"; exit 1; } source "$BASE_DIR/venv/bin/activate" || { log "Failed to activate virtual environment"; exit 1; } if [ -f "$BASE_DIR/.env" ]; then while IFS='=' read -r key value; do if [[ ! -z "$key" && ! "$key" =~ ^# ]]; then export "$key=$value" fi done < <(grep -v '^#' "$BASE_DIR/.env") log ".env variables loaded" else log "Error: .env file not found at $BASE_DIR/.env" exit 1 fi for script in foodie_automator_rss.py foodie_automator_reddit.py foodie_automator_google.py; do if [ -f "$script" ]; then sleep_time=$(run_script "$script" | tail -n 1) if [ -n "$sleep_time" ]; then log "Sleeping for $sleep_time seconds after $script" sleep "$sleep_time" fi else log "Script $script not found" exit 1 fi done if [ -f "foodie_engagement_generator.py" ]; then if ! check_running "foodie_engagement_generator"; then log "Running foodie_engagement_generator.py..." "$VENV_PYTHON" "foodie_engagement_generator.py" >> "$BASE_DIR/logs/foodie_engagement_generator.log" 2>&1 log "foodie_engagement_generator.py completed" fi else log "Script foodie_engagement_generator.py not found" fi log "All scripts started. Ensure cron jobs are enabled for automatic scheduling (crontab -l)." exit 0 fi # Main logic log "Checking for file changes..." CURRENT_CHECKSUM=$(calculate_checksum) if [ -f "$CHECKSUM_FILE" ]; then PREVIOUS_CHECKSUM=$(cat "$CHECKSUM_FILE") else PREVIOUS_CHECKSUM="" fi if [ "$CURRENT_CHECKSUM" != "$PREVIOUS_CHECKSUM" ]; then log "File changes detected. Previous checksum: $PREVIOUS_CHECKSUM, Current checksum: $CURRENT_CHECKSUM" if pgrep -f "$VENV_PYTHON.*foodie_automator" > /dev/null; then stop_scripts fi update_dependencies echo "$CURRENT_CHECKSUM" > "$CHECKSUM_FILE" log "Checksum updated." fi cd "$BASE_DIR" || { log "Failed to change to $BASE_DIR"; exit 1; } source "$BASE_DIR/venv/bin/activate" if [ -f "$BASE_DIR/.env" ]; then while IFS='=' read -r key value; do if [[ ! -z "$key" && ! "$key" =~ ^# ]]; then export "$key=$value" fi done < <(grep -v '^#' "$BASE_DIR/.env") log ".env variables loaded" else log "Error: .env file not found at $BASE_DIR/.env" exit 1 fi for script in foodie_automator_rss.py foodie_automator_reddit.py foodie_automator_google.py; do if [ -f "$script" ]; then sleep_time=$(run_script "$script" | tail -n 1) if [ -n "$sleep_time" ]; then log "Sleeping for $sleep_time seconds after $script" sleep "$sleep_time" fi else log "Script $script not found" exit 1 fi done log "All scripts processed." exit 0