Listing cron jobs in Linux shows which commands still run on a schedule for individual accounts and for the system itself. That visibility matters when checking unexpected cron mail, duplicate maintenance work, recurring load spikes, or automation that survived long after the original change window.
On a current Ubuntu system, cron reads per-user crontabs created with crontab, the system crontab at /etc/crontab, drop-in files under /etc/cron.d/, and the periodic script directories called through run-parts such as /etc/cron.daily. A complete inventory means checking each of those sources instead of assuming every schedule lives in one file.
System-wide cron files require sudo, and /etc/crontab plus files in /etc/cron.d/ include an extra username field before the command. A user account with no saved crontab returns a message such as no crontab for alice, which is normal and only means that account has no personal schedule installed.
$ crontab -l 30 2 * * 1 /home/alice/bin/report.sh
If the account has no installed user crontab, crontab -l returns a message such as no crontab for alice instead of a schedule list.
Related: How to create a cron job in Linux
Related: How to edit a cron job in Linux
Related: How to remove a cron job in Linux
$ sudo ls -1 /var/spool/cron/crontabs alice root
Do not edit files under /var/spool/cron or /var/spool/cron/crontabs directly. Use crontab -e so ownership, permissions, and syntax checks stay intact.
On current Ubuntu systems, per-user crontabs are stored under /var/spool/cron/crontabs. Many other Linux distributions keep them directly under /var/spool/cron instead.
$ sudo crontab -u root -l MAILTO="" 0 5 * * * /usr/local/bin/backup.sh 15 * * * * /usr/local/bin/rotate-logs.sh
Replace root with another account name from the spool listing when a different schedule owner needs inspection.
The -u option changes which account's personal crontab is shown. Confirm the account name before acting on the result so the real owner is not misidentified during an audit.
$ sudo cat /etc/crontab
# /etc/crontab: system-wide crontab
# Unlike any other crontab you don't have to run the `crontab'
# command to install the new version when you edit this file
# and files in /etc/cron.d. These files also have username fields,
# that none of the other crontabs do.
SHELL=/bin/sh
# You can also override PATH, but by default, newer versions inherit it from the environment
#PATH=/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin
# Example of job definition:
# * * * * * user-name command to be executed
17 * * * * root cd / && run-parts --report /etc/cron.hourly
25 6 * * * root test -x /usr/sbin/anacron || { cd / && run-parts --report /etc/cron.daily; }
47 6 * * 7 root test -x /usr/sbin/anacron || { cd / && run-parts --report /etc/cron.weekly; }
52 6 1 * * root test -x /usr/sbin/anacron || { cd / && run-parts --report /etc/cron.monthly; }
Entries in /etc/crontab add a username field between the schedule and the command, unlike per-user crontabs shown with crontab -l.
$ sudo ls -1 /etc/cron.d e2scrub_all
$ sudo cat /etc/cron.d/e2scrub_all 30 3 * * 0 root test -e /run/systemd/system || SERVICE_MODE=1 /usr/lib/aarch64-linux-gnu/e2fsprogs/e2scrub_all_cron 10 3 * * * root test -e /run/systemd/system || SERVICE_MODE=1 /sbin/e2scrub_all -A -r
Replace e2scrub_all with the actual file name from the first command. Files in /etc/cron.d/ use the same schedule + user + command format as /etc/crontab, and package-managed helper paths can differ by build architecture.
$ sudo ls -1 /etc/cron.hourly /etc/cron.daily /etc/cron.weekly /etc/cron.monthly /etc/cron.daily: apt-compat dpkg /etc/cron.hourly: /etc/cron.monthly: /etc/cron.weekly:
A script inside one of these directories is still a cron job because the default /etc/crontab entries call run-parts for each directory on schedule.