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.