What you will learn
Let a script install and keep its own crontab entry up to date, idempotently, using a marker comment — so deployment doesn't require a separate manual crontab -e step that's easy to forget or duplicate.
Before you begin
This edits the crontab of whichever user runs the installer — run it as the intended service account, not root, unless the job genuinely needs root.
1. Define the desired entry with a unique marker
#!/usr/bin/env bash
set -Eeuo pipefail
MARKER="# managed-by:myapp-nightly-backup"
SCHEDULE="0 3 * * *"
COMMAND="/opt/myapp/bin/nightly-backup.sh >> /var/log/myapp/backup.log 2>&1"
DESIRED_LINE="${SCHEDULE} ${COMMAND} ${MARKER}"
Appending a unique, greppable marker comment to the line — rather than trying to match the command text alone — makes it possible to find and update this exact managed entry even if the command or schedule changes later.
2. Install or update, never duplicate
install_cron_entry() {
local current
current="$(crontab -l 2>/dev/null || true)"
if grep -qF "$MARKER" <<< "$current"; then
if grep -qF "$DESIRED_LINE" <<< "$current"; then
echo "cron entry already up to date"
return 0
fi
# Replace the existing managed line, leave everything else untouched.
current="$(grep -vF "$MARKER" <<< "$current")"
echo "updating existing cron entry"
else
echo "installing new cron entry"
fi
{ printf '%s\n' "$current" | grep -v '^$' || true; echo "$DESIRED_LINE"; } | crontab -
}
install_cron_entry
Filtering out only lines containing $MARKER before re-adding the desired line — rather than overwriting the whole crontab — preserves any unrelated entries a human or another tool has installed for the same user.
3. Provide a matching removal path
remove_cron_entry() {
local current
current="$(crontab -l 2>/dev/null || true)"
if ! grep -qF "$MARKER" <<< "$current"; then
echo "no managed entry found, nothing to remove"
return 0
fi
grep -vF "$MARKER" <<< "$current" | crontab -
echo "removed managed cron entry"
}
# Usage: ./install-cron.sh remove
[[ "${1:-}" == "remove" ]] && { remove_cron_entry; exit 0; }
Example output
$ ./install-cron.sh
installing new cron entry
$ ./install-cron.sh
cron entry already up to date
$ ./install-cron.sh remove
removed managed cron entry
Verify the result
Run the installer twice and confirm crontab -l shows exactly one managed line, not two. Add an unrelated manual entry to the crontab first and confirm it survives both install and remove.
Troubleshooting
If crontab -l returns an error on a user with no existing crontab, the 2>/dev/null || true fallback is what prevents that from aborting the script under set -e — don't remove it.
Next steps
Call this as the final stage of idempotent-user-provisioner so a freshly provisioned service account has its schedule registered automatically.