Write your first shell script for your server
A shell script is a text file full of commands that you run as one program. Scripts save you from typing the same steps again and again, such as a nightly backup or a cleanup. This guide walks through a small, safe backup script, and explains the building blocks: variables, conditions, and exit codes.
Before you begin
- A VPS running Ubuntu 24.04 LTS and SSH access as a regular user, such as alex. The script runs as you, so it does not need sudo.
- A folder to back up. This guide uses
~/site, which you can create for practice. - A text editor. This guide uses nano.
Step 1: Create a practice folder
Make a folder with a sample file so the backup has something to copy. The ~ symbol is a shortcut for your home folder.
mkdir -p ~/site ~/scripts
echo "hello" > ~/site/index.html
Step 2: Write the script
Create the file backup-site.sh in your scripts folder:
nano ~/scripts/backup-site.sh
Paste this content and save with Ctrl+O, Enter, then exit with Ctrl+X:
#!/usr/bin/env bash
# Back up ~/site into a timestamped archive in ~/backups.
set -euo pipefail
SRC="$HOME/site"
DEST="$HOME/backups"
STAMP="$(date +%F-%H%M)"
FILE="$DEST/site-$STAMP.tar.gz"
if [ ! -d "$SRC" ]; then
echo "Source folder $SRC does not exist" >&2
exit 1
fi
mkdir -p "$DEST"
tar -czf "$FILE" -C "$HOME" site
echo "Backup written to $FILE"
Here is what each part does:
#!/usr/bin/env bashis the shebang line. It tells the system to run the file with bash.set -euo pipefailmakes the script stop at the first error, instead of pushing on with broken data.SRC="..."sets a variable. Use$SRCto read it back. Quotes keep paths with spaces safe.$(date +%F-%H%M)runs a command and inserts its output, here a timestamp such as 2026-10-31-0930.if [ ! -d "$SRC" ]is a condition. It is true when the folder does not exist, and the script then exits with an error.>&2sends the error message to the error stream, where people will see it.tar -czfcreates a compressed archive, and-C "$HOME"keeps paths inside it tidy.
Step 3: Make it executable and run it
A script needs the execute permission before you can run it directly. Add it with chmod +x, then run the script by its path. The ./ tells the shell to use the file in the current folder, not a system program with the same name.
chmod +x ~/scripts/backup-site.sh
~/scripts/backup-site.sh
Backup written to /home/alex/backups/site-2026-10-31-0930.tar.gz
Check the archive is there and contains your file:
ls -lh ~/backups
tar -tzf ~/backups/site-*.tar.gz
Step 4: Read the exit code
Every command returns an exit code: 0 means success, and anything else means failure. The special variable $? holds the code of the last command. Test the error branch by pointing the script at a folder that does not exist:
mv ~/site ~/site-away
~/scripts/backup-site.sh
echo "Exit code: $?"
mv ~/site-away ~/site
Source folder /home/alex/site does not exist
Exit code: 1
Exit codes are how cron, systemd, and other tools decide whether a job worked, so always end your scripts with a meaningful code.
bash -n ~/scripts/backup-site.sh to check a script for syntax errors without running it. Add -x to the run command, as in bash -x script.sh, to see every command as it executes.Troubleshooting
- "Permission denied" when you run the script. You skipped
chmod +x. Run it again and retry. - "bad interpreter: No such file or directory" or strange characters. The file has Windows line endings. Fix them with
sed -i 's/\r$//' ~/scripts/backup-site.sh. - "unbound variable". You used a variable that was never set, and
set -ucaught it. Check the spelling of the variable name. - "command not found". The script is running a program that is not installed, or the path to it is wrong. Use
which tarto check an install.
Next steps
Once a script works by hand, you can run it automatically. Add it to your crontab with crontab -e, or wrap it in a systemd timer as shown in the uptime checks guide. Next, try adding a line that deletes backups older than 14 days, and test it with find and -print before adding -delete.
Something not working? Chat or email our support team and we will help you get unstuck.
Contact support