Skip to main content

📘 Running Scripts


🎯 What You Will Learn

  1. Understand interactive vs non-interactive script execution.
  2. Learn to grant execution permission using chmod +x.
  3. Execute Bash scripts safely in a VPS environment.
  4. Automate WordPress tasks (backups, updates, database exports).
  5. Send status notifications via Email (SMTP/Gmail) and Webhook (n8n/ActivePieces).
  6. Apply logging, error handling, and scheduling (cron/systemd).

🧭 5W + 1H Framework

ElementDescription
WhatRunning a Bash script means executing a text file containing shell commands.
WhyAutomates repetitive maintenance, reducing human error and saving time.
WhoSystem admins, DevOps engineers, or WordPress VPS owners.
WhereIn an SSH terminal or automated context (cron, CI/CD pipeline).
WhenFor scheduled operations – backups, updates, or reports.
HowCreate 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, mailx or msmtp.
  • 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

ModeCommandOutputUse Case
Interactive./backup.shPrinted liveManual execution
Non-Interactivebash backup.sh or cronLogged outputAutomated 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
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

PracticeExplanation
Use #!/bin/bash shebangEnsures execution under Bash interpreter.
Absolute paths in cronAvoids PATH mismatch issues.
Log stdout and stderrUse >> /var/log/task.log 2>&1.
Secure SMTP passwordsStore in root-only file and use passwordeval.
Use timeouts on curlPrevents hangs from down services.

Static vs Dynamic Framing

ContextStatic (Manual)Dynamic (Auto)
TriggerUser runs scriptCron or remote event
OutputLive terminalLogged file + notifications
Use caseTesting, troubleshootingProduction automation

Troubleshooting Matrix

IssueCauseSolution
Permission deniedScript not executablechmod +x script.sh
command not foundMissing shebang or pathAdd #!/bin/bash, use full paths
Email not sentmsmtp not configuredVerify /etc/msmtprc and log
Webhook failsWrong URL or SSL issueCheck endpoint, add --insecure for testing
Cron runs but no mail / webhookMissing absolute pathsUse /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

TaskCommand
Make script executablechmod +x file.sh
Run interactively./file.sh
Send email via msmtp`printf "Subject: S\nTo: you@x\n\nBody\n"
Send JSON to webhookcurl -X POST -H "Content-Type: application/json" -d '{"key":"val"}' $URL
Check HTTP codecurl -w "%{http_code}" -o resp.json -sS
Log output>> /var/log/file.log 2>&1
Cron editcrontab -e

Mini-Quiz

#QuestionAnswer
1Which command adds execute permission to a script?chmod +x filename.sh
2What interpreter line must be at the top of a Bash script?#!/bin/bash
3Which tool sends email using SMTP/Gmail?msmtp
4Which command sends JSON data to n8n or ActivePieces?curl -X POST -H "Content-Type: application/json"
5Why use absolute paths in cron jobs?Cron uses limited environment PATH variables.