Save cron job output to a file
Append stdout and stderr correctly, add dated filenames or timestamps, and preserve the command’s exit status.
Append >> logfile 2>&1 to a cron command to save both standard output and standard error:
0 3 * * * /opt/jobs/backup.sh >> /var/log/jobs/backup.log 2>&1
The job account must be able to write the file and traverse its parent directories. The shell opens the destination before running the command, so a failed redirection can prevent the job from starting.
Choose the redirection you need
| Form | Effect |
|---|---|
> file |
Replace the file's contents with standard output |
>> file |
Append standard output |
2>> file |
Append standard error |
>> file 2>&1 |
Append both streams to one file |
> /dev/null 2>&1 |
Discard both streams |
Redirections are processed in order. In 2>&1 >> file, standard error is first pointed at the original standard-output destination; subsequently redirecting stdout does not move stderr into the file.
Appending is usually appropriate for a running history. Overwriting can be deliberate when you only want the latest run, but it discards the previous contents. Neither form records a completion status unless the program or a wrapper emits one.
Create a dated log
In a crontab command, escape percent signs even inside quoted strings:
0 3 * * * /opt/jobs/daily.sh >> /var/log/jobs/daily-$(date +\%Y\%m\%d).log 2>&1
Use a script instead if the date and path logic becomes complicated. Inside a normal script, write %Y%m%d without cron's backslashes. Align the naming timezone with your operational expectations.
Add timestamps without hiding failures
The ts utility from moreutils can prefix each output line with a timestamp. Put the pipeline in a Bash wrapper so percent signs avoid crontab parsing and the job's exit status can be preserved:
#!/bin/bash
/opt/jobs/task.sh 2>&1 | ts '[%Y-%m-%d %H:%M:%S]' >> /var/log/jobs/task.log
results=("${PIPESTATUS[@]}")
if (( results[1] != 0 )); then
printf 'Timestamp/log pipeline failed: %s\n' "${results[1]}" >&2
fi
exit "${results[0]}"
Install ts and set a suitable PATH. This wrapper reports the job's status and emits a separate message for a pipeline failure. A timestamp added by the pipe reflects when output was read, which can differ from event time because of application buffering.
Keep the evidence usable
Cron normally sends unredirected output through its mail transport. If mail is absent or disabled, that output may be lost. A file is one output strategy; a configured journal or logging pipeline is another.
Rotate logs and set a retention policy. Configure ownership for files recreated by rotation, and account for long-running writers that keep old file descriptors open. Guance file log collection can collect the resulting paths; test success, failure and rotation rather than assuming a configured path proves delivery.
Common questions
Why is the file empty? Check that the job ran, the account could open the file, and the program actually writes to stdout or stderr. Some applications write separate files internally.
Can I put successes and failures in separate files? You can separate stdout and stderr with >> stdout.log 2>> stderr.log, but those streams are not inherently success and failure. Use exit status and explicit result records for that distinction.
Can I just discard everything? Only if another mechanism retains the results you need. Discarding output also discards useful diagnostics.
References
Contact us
Join the community
to join the community
Try Guance
Start online and pay only for what you use.
Get startedChoose a Guance plan