📘 Running Scripts
🎯 What You Will Learn
- Understand interactive vs non-interactive script execution.
- Learn to grant execution permission using
chmod +x. - Execute Bash scripts safely in a VPS environment.
- Automate WordPress tasks (backups, updates, database exports).
- Send status notifications via Email (SMTP/Gmail) and Webhook (n8n/ActivePieces).
- Apply logging, error handling, and scheduling (cron/systemd).
🧭 5W + 1H Framework
| Element | Description |
| What | Running a Bash script means executing a text file containing shell commands. |
| Why | Automates repetitive maintenance, reducing human error and saving time. |
| Who | System admins, DevOps engineers, or WordPress VPS owners. |
| Where | In an SSH terminal or automated context (cron, CI/CD pipeline). |
| When | For scheduled operations – backups, updates, or reports. |
| How | Create a .sh file, set execute permission (chmod +x), and run it interactively or through automation. |
⚙️ Prerequisites
- Familiarity with
pwd,cd,ls. - Access to a Linux VPS with sudo rights.
- Installed utilities:
curl,jq,tar,mailxormsmtp. - Optional cron enabled for non-interactive execution.
Core Structure & Commands
1️⃣ Create a Basic Script
nano backup.sh
Content
#!/bin/bash
# WordPress backup example
echo "Starting backup..."
tar -czf /home/backup/wp_backup_$(date +%F).tar.gz /var/www/html
echo "Backup complete."
2️⃣ Make Executable and Run
chmod +x backup.sh
./backup.sh
Expected Output
Starting backup...
Backup complete.
Interactive vs Non-Interactive
| Mode | Command | Output | Use Case |
| Interactive | ./backup.sh | Printed live | Manual execution |
| Non-Interactive | bash backup.sh or cron | Logged output | Automated tasks |
Adding Notifications
A. Send Email (Using Gmail or Your Own SMTP)
1️⃣ Install msmtp + mailx
sudo apt install msmtp msmtp-mta mailutils -y
2️⃣ Configure msmtp (SMTP Relay)
Edit /etc/msmtprc
defaults
auth on
tls on
tls_trust_file /etc/ssl/certs/ca-certificates.crt
logfile /var/log/msmtp.log
account default
host smtp.gmail.com
port 587
from [email protected]
user [email protected]
passwordeval "cat /root/.secrets/gmail_pass"
(For your own SMTP server, replace host, user, and from accordingly.)
3️⃣ Create Notification Script
#!/bin/bash
SUBJECT="[WP Backup] $(hostname) $(date +%F_%H%M)"
BODY="Backup completed successfully at $(date +%T)"
printf "Subject: %s\nTo: %s\n\n%s\n" "$SUBJECT" "$TO" "$BODY" | msmtp -t
Expected Output
# No terminal output on success
$ echo $?
0
Expected Log (/var/log/msmtp.log)
msmtp: host=smtp.gmail.com tls=on auth=on [email protected] recipients=1 sent
B. Send Webhook (Using n8n / ActivePieces / Other 3rd Party)
1️⃣ Webhook Payload Example
#!/bin/bash
WEBHOOK_URL="https://n8n.yourdomain.com/webhook/wp_backup"
payload=$(jq -n \
--arg host "$(hostname)" \
--arg status "success" \
--arg time "$(date --iso-8601=seconds)" \
'{event:"backup_complete",host:$host,status:$status,time:$time}')
code=$(curl -sS -X POST "$WEBHOOK_URL" \
-H "Content-Type: application/json" \
-d "$payload" \
-w "%{http_code}" -o /tmp/resp.json --max-time 10)
echo "Webhook response code: $code"
cat /tmp/resp.json
Expected Output
Webhook response code: 200
{"ack":"ok"}
2️⃣ Webhook Example for ActivePieces
WEBHOOK_URL="https://cloud.activepieces.com/api/v1/webhooks/abcdef123456"
Both platforms accept JSON POST; ActivePieces flows auto-parse keys (event, status, host).
C. Combine Backup + Email + Webhook
#!/bin/bash
set -euo pipefail
SITE_PATH="/var/www/html"
ARCHIVE="/home/backup/wp_backup_$(date +%F_%H%M).tar.gz"
WEBHOOK_URL="https://n8n.yourdomain.com/webhook/wp_backup"
echo "Starting backup..."
tar -czf "$ARCHIVE" "$SITE_PATH"
echo "Backup complete: $ARCHIVE"
# Send Email
SUBJECT="[WP Backup OK] $(hostname)"
BODY="Backup successful for $(hostname) at $(date)\nFile: $ARCHIVE"
printf "Subject: %s\nTo: %s\n\n%s\n" "$SUBJECT" "$EMAIL_TO" "$BODY" | msmtp -t
# Send Webhook
payload=$(jq -n --arg host "$(hostname)" --arg file "$ARCHIVE" --arg status "success" '{event:"backup_ok",host:$host,file:$file,status:$status}')
curl -sS -X POST "$WEBHOOK_URL" -H "Content-Type: application/json" -d "$payload" --max-time 10 -w "%{http_code}\n"
Expected Output
Starting backup...
Backup complete: /home/backup/wp_backup_2025-10-06_1410.tar.gz
200
🧾 Scheduling (Non-Interactive Execution)
Add to cron:
0 2 * * * /home/user/scripts/wp_backup.sh >> /var/log/wp_backup.log 2>&1
Runs every day at 2 AM and logs to file.
Best Practices
| Practice | Explanation |
Use #!/bin/bash shebang | Ensures execution under Bash interpreter. |
| Absolute paths in cron | Avoids PATH mismatch issues. |
| Log stdout and stderr | Use >> /var/log/task.log 2>&1. |
| Secure SMTP passwords | Store in root-only file and use passwordeval. |
| Use timeouts on curl | Prevents hangs from down services. |
Static vs Dynamic Framing
| Context | Static (Manual) | Dynamic (Auto) |
| Trigger | User runs script | Cron or remote event |
| Output | Live terminal | Logged file + notifications |
| Use case | Testing, troubleshooting | Production automation |
Troubleshooting Matrix
| Issue | Cause | Solution |
Permission denied | Script not executable | chmod +x script.sh |
command not found | Missing shebang or path | Add #!/bin/bash, use full paths |
| Email not sent | msmtp not configured | Verify /etc/msmtprc and log |
| Webhook fails | Wrong URL or SSL issue | Check endpoint, add --insecure for testing |
| Cron runs but no mail / webhook | Missing absolute paths | Use /usr/bin/msmtp, /usr/bin/curl explicitly |
Quick Lab – WP Update Notifier
#!/bin/bash
set -e
WP_PATH="/var/www/html"
WEBHOOK_URL="https://cloud.activepieces.com/api/v1/webhooks/xyz123"
wp plugin update --all --path=$WP_PATH
wp theme update --all --path=$WP_PATH
wp core update --path=$WP_PATH
printf "Subject: [WP Update] $(hostname)\nTo: %s\n\nPlugins/themes/core updated on $(hostname)\n" "$EMAIL" | msmtp -t
payload=$(jq -n --arg host "$(hostname)" --arg event "wp_update_ok" '{host:$host,event:$event}')
curl -sS -X POST "$WEBHOOK_URL" -H "Content-Type: application/json" -d "$payload" -w "%{http_code}\n"
Expected
200
Both email and webhook confirm success.
Cheat Sheet
| Task | Command |
| Make script executable | chmod +x file.sh |
| Run interactively | ./file.sh |
| Send email via msmtp | `printf "Subject: S\nTo: you@x\n\nBody\n" |
| Send JSON to webhook | curl -X POST -H "Content-Type: application/json" -d '{"key":"val"}' $URL |
| Check HTTP code | curl -w "%{http_code}" -o resp.json -sS |
| Log output | >> /var/log/file.log 2>&1 |
| Cron edit | crontab -e |
Mini-Quiz
| # | Question | Answer |
| 1 | Which command adds execute permission to a script? | chmod +x filename.sh |
| 2 | What interpreter line must be at the top of a Bash script? | #!/bin/bash |
| 3 | Which tool sends email using SMTP/Gmail? | msmtp |
| 4 | Which command sends JSON data to n8n or ActivePieces? | curl -X POST -H "Content-Type: application/json" |
| 5 | Why use absolute paths in cron jobs? | Cron uses limited environment PATH variables. |