This Bash workflow syncs a WordPress directory to S3 only after service and page health checks pass. It reduces the chance of syncing broken content and preserves a timestamped audit trail in a local log file.
What This Script Validates Before Sync
- Apache service state
- HTTP 200 response from the site
- Expected marker content on homepage and account page
- Required markers in
.htaccess
Sync Script
#!/bin/bash
log_file="/var/log/s3_sync.log"
site="/var/www/html/site"
s3_bucket="some-s3-bucket-for-backups"
site_url="https://lalalala.net/"
account_url="https://lalalala.net/account/lost-password/"
error_message="There has been a critical error on your website"
# Function to write log with timestamp
log_entry() {
echo "$(date +'%Y-%m-%d %H:%M:%S') - $1" >> "$log_file"
}
# Function to check .htaccess file
check_htaccess() {
local htaccess_file="$site/.htaccess"
local start_marker="# BEGIN WP Rocket"
local end_marker="# END cPanel-generated php ini directives, do not edit"
if [ -f "$htaccess_file" ]; then
local start_found=$(grep -c "$start_marker" "$htaccess_file")
local end_found=$(grep -c "$end_marker" "$htaccess_file")
if [ "$start_found" -eq 0 ] || [ "$end_found" -eq 0 ]; then
log_entry "ERROR: .htaccess file does not have the expected markers"
return 1
else
log_entry ".htaccess file has the expected markers"
return 0
fi
else
log_entry "ERROR: .htaccess file not found"
return 1
fi
}
# Check if Apache2 service is running
apache_status=$(systemctl is-active apache2.service)
if [ "$apache_status" != "active" ]; then
log_entry "ERROR: Apache2 service is not running."
exit 1
else
# Check if the WordPress site is working
site_response=$(curl --silent --max-time 10 --write-out "%{http_code}" "$site_url" --output /dev/null)
if [ "$site_response" == "200" ]; then
log_entry "WordPress site gives $site_response, check if it contains "MY_SITE_WORD""
site_content=$(curl --silent --max-time 10 "$site_url")
account_content=$(curl --silent --max-time 10 "$account_url")
if echo "$site_content" | grep -q "MY_SITE_WORD" && echo "$account_content" | grep -q "Account" && ! echo "$site_content" | grep -q "$error_message"; then
if check_htaccess; then
log_entry "WordPress site contains "MY_SITE_WORD", Account page avalible and hasn't got ERROR message, Syncing with AWS S3 bucket"
/usr/local/bin/aws s3 sync "$site" "s3://$s3_bucket/my_site" --delete >> "$log_file" 2>&1
log_entry "Syncing finished with AWS S3 bucket"
else
log_entry "ERROR: .htaccess file check failed, skipping sync"
exit 1
fi
else
log_entry "ERROR: WordPress site does not contain MY_SITE_WORD or Account or gives ERROR message"
exit 1
fi
else
log_entry "ERROR: WordPress site not working. Response code: $site_response"
exit 1
fi
fi
chown -R www-data:www-data /var/www/html/woocommerce/
chmod -R 775 /var/www/html/woocommerce/wp-content
chmod -R 775 /var/www/html/woocommerce/pages
Operational Notes
- Run with a user that has permission for both WordPress files and S3 operations.
- Store AWS credentials securely (role or restricted credentials file).
- Review log rotation for
/var/log/s3_sync.logto avoid unbounded growth.
Official Documentation
Bash Reference Manual: https://www.gnu.org/software/bash/manual/
