Record cron job output and completion status

Capture stdout and stderr, preserve exit codes, and keep application results distinct from cron scheduler events.

Best practices
Illustration of scheduled jobs, logs and Linux operations

A useful cron log tells you which run started, what it produced, and how it finished. Cron's own log usually records scheduling events; your script needs its own output and result records.

Append both output streams

*/5 * * * * /opt/jobs/task.sh >> /var/log/jobs/task.log 2>&1

Create the directory and arrange write permissions for the job account. >> appends standard output, then 2>&1 directs standard error to the same destination. Reversing that order does not combine both streams in the file.

Output alone does not define success: a command can fail silently or print a warning and still exit zero.

Add start and finish records

Keep shell logic in an executable wrapper rather than a long crontab line:

#!/bin/sh
run_id="$(date -u +%Y%m%dT%H%M%SZ)-$$"
printf 'job=task run=%s event=start time=%s\n' "$run_id" "$(date -u +%Y-%m-%dT%H:%M:%SZ)"
/opt/jobs/task.sh
status=$?
printf 'job=task run=%s event=finish status=%s time=%s\n' \
    "$run_id" "$status" "$(date -u +%Y-%m-%dT%H:%M:%SZ)"
exit "$status"

Schedule the wrapper with output redirected to the log. Percent signs inside the script are ordinary shell characters; directly in a crontab command they require escaping. Include a host or scheduler identifier when correlating runs across machines.

A finish line is emitted only if the wrapper reaches it. A process killed with SIGKILL, a host failure, or a crash can leave a start without a finish. Detect overdue completion separately, using the job's expected duration and the health of log collection.

Send output to syslog when appropriate

A pipeline to logger can tag messages, but its default exit status may conceal a failed job. In a Bash wrapper, preserve the job's result explicitly:

#!/bin/bash
/opt/jobs/task.sh 2>&1 | logger -t scheduled-task
results=("${PIPESTATUS[@]}")
if (( results[1] != 0 )); then
    printf 'logger failed with status %s\n' "${results[1]}" >&2
fi
exit "${results[0]}"

This requires Bash. The logger status covers its local submission, not guaranteed remote delivery or storage. Log routing determines whether records appear in the journal, /var/log/syslog, or another destination.

Retain and collect the logs

Configure rotation and retention. If rotation creates a new file, ensure its owner and mode still allow the job to write. Long-running writers may continue using the old file until they reopen it; verify that the collector follows the rotation method you use.

Guance file log collection can collect the application log alongside the scheduler log. Test a successful run, a failed run and rotation, then search by job and run identifier. Missing centralized records can indicate an execution problem or a collection problem.

Common questions

Where is cron's own log? Common locations include /var/log/syslog on Debian/Ubuntu and /var/log/cron on RHEL-family systems, but routing varies. On systemd hosts, inspect the cron or crond service journal too.

Can a pipeline change the reported result? Yes. A shell normally reports the last pipeline command's status. Preserve the job status when it matters.

Does a launch entry prove success? No. Use completion status and, where relevant, a business-level result such as a verified backup artifact.

References

Get a tailored plan

Contact us

Join the community

Scan with WeChat
to join the community

Try Guance

Start online and pay only for what you use.

Get started

Choose a Guance plan

Code hosting