Save cron job output to a file

Append stdout and stderr correctly, add dated filenames or timestamps, and preserve the command’s exit status.

Best practices
Illustration of scheduled jobs, logs and Linux operations

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

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