ChatGPT解决这个技术问题 Extra ChatGPT

How do I list all cron jobs for all users?

Is there a command or an existing script that will let me view all of a *NIX system's scheduled cron jobs at once? I'd like it to include all of the user crontabs, as well as /etc/crontab, and whatever's in /etc/cron.d. It would also be nice to see the specific commands run by run-parts in /etc/crontab.

Ideally, I'd like the output in a nice column form and ordered in some meaningful way.

I could then merge these listings from multiple servers to view the overall "schedule of events."

I was about to write such a script myself, but if someone's already gone to the trouble...

Similar question on Unix SE: unix.stackexchange.com/questions/7053/…

U
User007

You would have to run this as root, but:

for user in $(cut -f1 -d: /etc/passwd); do crontab -u $user -l; done

will loop over each user name listing out their crontab. The crontabs are owned by the respective users so you won't be able to see another user's crontab w/o being them or root.

Edit if you want to know which user a crontab belongs to, use echo $user

for user in $(cut -f1 -d: /etc/passwd); do echo $user; crontab -u $user -l; done

Doesn't work when the users are defined in NIS or LDAP. You need to use for user in $(getent passwd | cut -f1 -d: ); do echo $user; crontab -u $user -l; done
Updated this to exclude comments and suppress 'no crontab for user...' messages: for user in $(cut -f1 -d: /etc/passwd); do crontab -u $user -l 2>/dev/null | grep -v '^#'; done
Wouldn't it be easier to look at the files in /var/spool/cron?
We us LDAP and /etc/passwd needs to be replaced with the getent command: for user in $(getent passwd | awk -F : '{print $1}'); do echo $user; crontab -u $user -l; done
What about the cronjobs in /etc/cron.hourly/, /etc/cron.daily/, /etc/cron.weekly/, /etc/cron.monthly/...?
B
Benjamin W.

I ended up writing a script (I'm trying to teach myself the finer points of bash scripting, so that's why you don't see something like Perl here). It's not exactly a simple affair, but it does most of what I need. It uses Kyle's suggestion for looking up individual users' crontabs, but also deals with /etc/crontab (including the scripts launched by run-parts in /etc/cron.hourly, /etc/cron.daily, etc.) and the jobs in the /etc/cron.d directory. It takes all of those and merges them into a display something like the following:

mi     h    d  m  w  user      command
09,39  *    *  *  *  root      [ -d /var/lib/php5 ] && find /var/lib/php5/ -type f -cmin +$(/usr/lib/php5/maxlifetime) -print0 | xargs -r -0 rm
47     */8  *  *  *  root      rsync -axE --delete --ignore-errors / /mirror/ >/dev/null
17     1    *  *  *  root      /etc/cron.daily/apt
17     1    *  *  *  root      /etc/cron.daily/aptitude
17     1    *  *  *  root      /etc/cron.daily/find
17     1    *  *  *  root      /etc/cron.daily/logrotate
17     1    *  *  *  root      /etc/cron.daily/man-db
17     1    *  *  *  root      /etc/cron.daily/ntp
17     1    *  *  *  root      /etc/cron.daily/standard
17     1    *  *  *  root      /etc/cron.daily/sysklogd
27     2    *  *  7  root      /etc/cron.weekly/man-db
27     2    *  *  7  root      /etc/cron.weekly/sysklogd
13     3    *  *  *  archiver  /usr/local/bin/offsite-backup 2>&1
32     3    1  *  *  root      /etc/cron.monthly/standard
36     4    *  *  *  yukon     /home/yukon/bin/do-daily-stuff
5      5    *  *  *  archiver  /usr/local/bin/update-logs >/dev/null

Note that it shows the user, and more-or-less sorts by hour and minute so that I can see the daily schedule.

So far, I've tested it on Ubuntu, Debian, and Red Hat AS.

#!/bin/bash

# System-wide crontab file and cron job directory. Change these for your system.
CRONTAB='/etc/crontab'
CRONDIR='/etc/cron.d'

# Single tab character. Annoyingly necessary.
tab=$(echo -en "\t")

# Given a stream of crontab lines, exclude non-cron job lines, replace
# whitespace characters with a single space, and remove any spaces from the
# beginning of each line.
function clean_cron_lines() {
    while read line ; do
        echo "${line}" |
            egrep --invert-match '^($|\s*#|\s*[[:alnum:]_]+=)' |
            sed --regexp-extended "s/\s+/ /g" |
            sed --regexp-extended "s/^ //"
    done;
}

# Given a stream of cleaned crontab lines, echo any that don't include the
# run-parts command, and for those that do, show each job file in the run-parts
# directory as if it were scheduled explicitly.
function lookup_run_parts() {
    while read line ; do
        match=$(echo "${line}" | egrep -o 'run-parts (-{1,2}\S+ )*\S+')

        if [[ -z "${match}" ]] ; then
            echo "${line}"
        else
            cron_fields=$(echo "${line}" | cut -f1-6 -d' ')
            cron_job_dir=$(echo  "${match}" | awk '{print $NF}')

            if [[ -d "${cron_job_dir}" ]] ; then
                for cron_job_file in "${cron_job_dir}"/* ; do  # */ <not a comment>
                    [[ -f "${cron_job_file}" ]] && echo "${cron_fields} ${cron_job_file}"
                done
            fi
        fi
    done;
}

# Temporary file for crontab lines.
temp=$(mktemp) || exit 1

# Add all of the jobs from the system-wide crontab file.
cat "${CRONTAB}" | clean_cron_lines | lookup_run_parts >"${temp}" 

# Add all of the jobs from the system-wide cron directory.
cat "${CRONDIR}"/* | clean_cron_lines >>"${temp}"  # */ <not a comment>

# Add each user's crontab (if it exists). Insert the user's name between the
# five time fields and the command.
while read user ; do
    crontab -l -u "${user}" 2>/dev/null |
        clean_cron_lines |
        sed --regexp-extended "s/^((\S+ +){5})(.+)$/\1${user} \3/" >>"${temp}"
done < <(cut --fields=1 --delimiter=: /etc/passwd)

# Output the collected crontab lines. Replace the single spaces between the
# fields with tab characters, sort the lines by hour and minute, insert the
# header line, and format the results as a table.
cat "${temp}" |
    sed --regexp-extended "s/^(\S+) +(\S+) +(\S+) +(\S+) +(\S+) +(\S+) +(.*)$/\1\t\2\t\3\t\4\t\5\t\6\t\7/" |
    sort --numeric-sort --field-separator="${tab}" --key=2,1 |
    sed "1i\mi\th\td\tm\tw\tuser\tcommand" |
    column -s"${tab}" -t

rm --force "${temp}"

Nothing, but it didn't do anything about the system cron jobs in /etc/crontab and /etc/cron.d/. Dealing with those, and formatting everything at the end, is what my script does.
yukondude - you should consider putting this up on github, even just as a gist.
Tried to copy paste and run it, but it fails:showcrons.sh: line 59: syntax error near unexpected token <' showcrons.sh: line 59: done < <(cut --fields=1 --delimiter=: /etc/passwd)'
@KyleBurton There seem to at least 8 gists already copying this, gist.github.com/gists/…
Warning: This script is missing events from /etc/anacrontab
c
caot

Under Ubuntu or debian, you can view crontab by /var/spool/cron/crontabs/ and then a file for each user is in there. That's only for user-specific crontab's of course.

For Redhat 6/7 and Centos, the crontab is under /var/spool/cron/.


This works on RedHat as well (/var/spool/cron) and is easier than writing/running a script especially if you're using something like Ldap to manage accounts. +1
This was much more helpful to me than any of the other answers. This method allows you to view the crontabs of users who no longer exist as well, giving you ALL cron jobs as requested by the OP.
Another benefit to this method: my server uses LDAP, so most of the users aren't in /etc/passwd. IMO this should be the accepted answer, rather than all of the brute-force solutions.
Good with Suse Linux here.
Thx, this is also true for AWS EC2 instace, this info was very helpful!
S
Skeets

This will show all crontab entries from all users.

sed 's/^\([^:]*\):.*$/crontab -u \1 -l 2>\&1/' /etc/passwd | sh | grep -v "no crontab for"

such regex, much prowess. getent passwd | awk -F: '{ print $1 }' | sudo xargs -n1 crontab -l -u
J
Jørgen

Depends on your linux version but I use:

tail -n 1000 /var/spool/cron/*

as root. Very simple and very short.

Gives me output like:

==> /var/spool/cron/root <==
15 2 * * * /bla

==> /var/spool/cron/my_user <==
*/10 1 * * * /path/to/script

Use tail -n +1 /var/spool/cron/* to list all content of the files.
... or sudo sh -c 'tail -n +1 /var/spool/cron/*' if you don't want to become root. My OCD compelled me to investigate why I couldn't sudo this command as written. It was because regular users don't have access to /var/spool/cron dir, and the glob was being interpreted as a literal star character, which obviously doesn't exist.
alternatively, cd /var/spool/cron/cron/ && grep . * will also print corresponding user name in front of every cron job
M
Michael Myers

A small refinement of Kyle Burton's answer with improved output formatting:

#!/bin/bash
for user in $(cut -f1 -d: /etc/passwd)
do echo $user && crontab -u $user -l
echo " "
done

M
Mithaldu
getent passwd | cut -d: -f1 | perl -e'while(<>){chomp;$l = `crontab -u $_ -l 2>/dev/null`;print "$_\n$l\n" if $l}'

This avoids messing with passwd directly, skips users that have no cron entries and for those who have them it prints out the username as well as their crontab.

Mostly dropping this here though so i can find it later in case i ever need to search for it again.


It also lists LDAP users not present in /etc/passwd. Matt's solution above is more appropriate to this particular situation, but it's good to know that the command exists.
S
Sheikh Abdul Wahid

To get list from ROOT user.

for user in $(cut -f1 -d: /etc/passwd); do echo $user; sudo crontab -u $user -l; done

D
Doris

If you check a cluster using NIS, the only way to see if a user has a crontab entry ist according to Matt's answer /var/spool/cron/tabs.

grep -v "#" -R  /var/spool/cron/tabs

S
Sam Arul Raj T

This script worked for me in CentOS to list all crons in the environment:

sudo cat /etc/passwd | sed 's/^\([^:]*\):.*$/sudo crontab -u \1 -l 2>\&1/' | grep -v "no crontab for" | sh

Awesome! I added a little variation to see which user the cron job is under and put some space between results: cat /etc/passwd | sed 's/^\([^:]*\):.*$/echo "\ncrontab for \1:"; sudo crontab -u \1 -l 2>\&1/' | grep -v "no crontab for" | sh saves a little bit of time
such regex, much prowess. getent passwd | awk -F: '{ print $1 }' | sudo xargs -n1 crontab -l -u
s
squarism

I like the simple one-liner answer above:

for user in $(cut -f1 -d: /etc/passwd); do crontab -u $user -l; done

But Solaris which does not have the -u flag and does not print the user it's checking, you can modify it like so:

for user in $(cut -f1 -d: /etc/passwd); do echo User:$user; crontab -l $user 2>&1 | grep -v crontab; done

You will get a list of users without the errors thrown by crontab when an account is not allowed to use cron etc. Be aware that in Solaris, roles can be in /etc/passwd too (see /etc/user_attr).


Cool. TIL not to use for.
T
Tim Santeford
for user in $(cut -f1 -d: /etc/passwd); 
do 
    echo $user; crontab -u $user -l; 
done

See Why you don't read lines with "for". Also, this answer is just repeating others.
D
Dale Anderson

The following strips away comments, empty lines, and errors from users with no crontab. All you're left with is a clear list of users and their jobs.

Note the use of sudo in the 2nd line. If you're already root, remove that.

for USER in $(cut -f1 -d: /etc/passwd); do \
USERTAB="$(sudo crontab -u "$USER" -l 2>&1)";  \
FILTERED="$(echo "$USERTAB"| grep -vE '^#|^$|no crontab for|cannot use this program')";  \
if ! test -z "$FILTERED"; then  \
echo "# ------ $(tput bold)$USER$(tput sgr0) ------";  \
echo "$FILTERED";  \
echo "";  \
fi;  \
done

Example output:

# ------ root ------
0 */6 * * * /usr/local/bin/disk-space-notify.sh
45 3 * * * /opt/mysql-backups/mysql-backups.sh
5 7 * * * /usr/local/bin/certbot-auto renew --quiet --no-self-upgrade

# ------ sammy ------
55 * * * * wget -O - -q -t 1 https://www.example.com/cron.php > /dev/null

I use this on Ubuntu (12 thru 16) and Red Hat (5 thru 7).


Я
Ярослав Рахматуллин

While many of the answers produce useful results, I think the hustle of maintaining a complex script for this task is not worth it. This is mainly because most distros use different cron daemons.

Watch and learn, kids & elders.

$ \cat ~jaroslav/bin/ls-crons 
#!/bin/bash
getent passwd | awk -F: '{ print $1 }' | xargs -I% sh -c 'crontab -l -u % | sed "/^$/d; /^#/d; s/^/% /"' 2>/dev/null
echo
cat /etc/crontab /etc/anacrontab 2>/dev/null | sed '/^$/d; /^#/d;'
echo
run-parts --list /etc/cron.hourly;
run-parts --list /etc/cron.daily;
run-parts --list /etc/cron.weekly;
run-parts --list /etc/cron.monthly;

Run like this

$ sudo ls-cron

Sample output (Gentoo)

$ sudo ~jaroslav/bin/ls-crons 
jaroslav */5 * * * *  mv ~/java_error_in_PHPSTORM* ~/tmp 2>/dev/null
jaroslav 5 */24 * * * ~/bin/Find-home-files
jaroslav * 7 * * * cp /T/fortrabbit/ssh-config/fapps.tsv /home/jaroslav/reference/fortrabbit/fapps
jaroslav */8 1 * * * make -C /T/fortrabbit/ssh-config discover-apps # >/dev/null
jaroslav */7    * * * * getmail -r jazzoslav -r fortrabbit 2>/dev/null
jaroslav */1    * * * * /home/jaroslav/bin/checkmail
jaroslav *    9-18 * * * getmail -r fortrabbit 2>/dev/null

SHELL=/bin/bash
PATH=/sbin:/bin:/usr/sbin:/usr/bin
MAILTO=root
HOME=/
SHELL=/bin/sh
PATH=/sbin:/bin:/usr/sbin:/usr/bin
MAILTO=root
RANDOM_DELAY=45
START_HOURS_RANGE=3-22
1   5   cron.daily      nice run-parts /etc/cron.daily
7   25  cron.weekly     nice run-parts /etc/cron.weekly
@monthly 45 cron.monthly        nice run-parts /etc/cron.monthly

/etc/cron.hourly/0anacron
/etc/cron.daily/logrotate
/etc/cron.daily/man-db
/etc/cron.daily/mlocate
/etc/cron.weekly/mdadm
/etc/cron.weekly/pfl

Sample output (Ubuntu)

SHELL=/bin/sh
PATH=/usr/local/sbin:/usr/local/bin:/sbin:/bin:/usr/sbin:/usr/bin
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 )

/etc/cron.hourly/btrfs-quota-cleanup
/etc/cron.hourly/ntpdate-debian
/etc/cron.daily/apport
/etc/cron.daily/apt-compat
/etc/cron.daily/apt-show-versions
/etc/cron.daily/aptitude
/etc/cron.daily/bsdmainutils
/etc/cron.daily/dpkg
/etc/cron.daily/logrotate
/etc/cron.daily/man-db
/etc/cron.daily/mlocate
/etc/cron.daily/passwd
/etc/cron.daily/popularity-contest
/etc/cron.daily/ubuntu-advantage-tools
/etc/cron.daily/update-notifier-common
/etc/cron.daily/upstart
/etc/cron.weekly/apt-xapian-index
/etc/cron.weekly/man-db
/etc/cron.weekly/update-notifier-common

Pics

Ubuntu:

https://i.stack.imgur.com/fyNiH.png

Gentoo:

https://i.stack.imgur.com/vETIY.png


D
Daniel Papasian

Depends on your version of cron. Using Vixie cron on FreeBSD, I can do something like this:

(cd /var/cron/tabs && grep -vH ^# *) 

if I want it more tab deliminated, I might do something like this:

(cd /var/cron/tabs && grep -vH ^# * | sed "s/:/      /")

Where that's a literal tab in the sed replacement portion.

It may be more system independent to loop through the users in /etc/passwd and do crontab -l -u $user for each of them.


I
Ishita Sinha

you can write for all user list :

sudo crontab -u userName -l

,

You can also go to

cd /etc/cron.daily/
ls -l
cat filename

this file will list the schedules

cd /etc/cron.d/
ls -l
cat filename

This is all I actually needed.
a
armagedescu

On Solaris, for a particular known user name:

crontab -l username

To get all user's jobs at once on Solaris, much like other posts above:

for user in $(cut -f1 -d: /etc/passwd); do crontab -l $user 2>/dev/null; done

https://i.stack.imgur.com/1PT7z.png


j
jbbarth

Thanks for this very useful script. I had some tiny problems running it on old systems (Red Hat Enterprise 3, which handle differently egrep and tabs in strings), and other systems with nothing in /etc/cron.d/ (the script then ended with an error). So here is a patch to make it work in such cases :

2a3,4
> #See:  http://stackoverflow.com/questions/134906/how-do-i-list-all-cron-jobs-for-all-users
>
27c29,30
<         match=$(echo "${line}" | egrep -o 'run-parts (-{1,2}\S+ )*\S+')
---
>         #match=$(echo "${line}" | egrep -o 'run-parts (-{1,2}\S+ )*\S+')
>         match=$(echo "${line}" | egrep -o 'run-parts.*')
51c54,57
< cat "${CRONDIR}"/* | clean_cron_lines >>"${temp}"  # */ <not a comment>
---
> sys_cron_num=$(ls /etc/cron.d | wc -l | awk '{print $1}')
> if [ "$sys_cron_num" != 0 ]; then
>       cat "${CRONDIR}"/* | clean_cron_lines >>"${temp}"  # */ <not a comment>
> fi
67c73
<     sed "1i\mi\th\td\tm\tw\tuser\tcommand" |
---
>     sed "1i\mi${tab}h${tab}d${tab}m${tab}w${tab}user${tab}command" |

I'm not really sure the changes in the first egrep are a good idea, but well, this script has been tested on RHEL3,4,5 and Debian5 without any problem. Hope this helps!


l
linux.cnf

i made below one liner script and it worked for me to list all cron jobs for all users.

cat /etc/passwd |awk -F ':' '{print $1}'|while read a;do crontab -l -u ${a} ; done

A
Ali

Building on top of @Kyle

for user in $(tail -n +11 /etc/passwd | cut -f1 -d:); do echo $user; crontab -u $user -l; done

to avoid the comments usually at the top of /etc/passwd,

And on macosx

for user in $(dscl . -list /users | cut -f1 -d:); do echo $user; crontab -u $user -l; done    

Shouldn't you grep -v '^#' instead of relying on magic number 11?
Red Hat / CentOS distros don't write the helpful hints at the start of a user's crontab, so cutting off the first 11 lines will obliterate the content of it. Same thing if an Ubuntu user has edited their own crontab and removed all the hand holding.
V
Vini.g.fer

I think a better one liner would be below. For example if you have users in NIS or LDAP they wouldnt be in /etc/passwd. This will give you the crontabs of every user that has logged in.

for I in `lastlog | grep -v Never | cut -f1 -d' '`; do echo $I ; crontab -l -u $I ; done

d
david collier

With apologies and thanks to yukondude.

I've tried to summarise the timing settings for easy reading, though it's not a perfect job, and I don't touch 'every Friday' or 'only on Mondays' stuff.

This is version 10 - it now:

runs much much faster

has optional progress characters so you could improve the speed further.

uses a divider line to separate header and output.

outputs in a compact format when all timing intervals uencountered can be summarised.

Accepts Jan...Dec descriptors for months-of-the-year

Accepts Mon...Sun descriptors for days-of-the-week

tries to handle debian-style dummying-up of anacron when it is missing

tries to deal with crontab lines which run a file after pre-testing executability using "[ -x ... ]"

tries to deal with crontab lines which run a file after pre-testing executability using "command -v"

allows the use of interval spans and lists.

supports run-parts usage in user-specific /var/spool crontab files.

I am now publishing the script in full here.

https://gist.github.com/myshkin-uk/d667116d3e2d689f23f18f6cd3c71107


f
fedorqui

Since it is a matter of looping through a file (/etc/passwd) and performing an action, I am missing the proper approach on How can I read a file (data stream, variable) line-by-line (and/or field-by-field)?:

while IFS=":" read -r user _
do
   echo "crontab for user ${user}:"
   crontab -u "$user" -l
done < /etc/passwd

This reads /etc/passwd line by line using : as field delimiter. By saying read -r user _, we make $user hold the first field and _ the rest (it is just a junk variable to ignore fields).

This way, we can then call crontab -u using the variable $user, which we quote for safety (what if it contains spaces? It is unlikely in such file, but you can never know).


M
Manifest Man

I tend to use following small commands to list all jobs for single user and all users on Unix based operating systems with a modern bash console:

1. Single user

 echo "Jobs owned by $USER" && crontab -l -u $USER

2. All users

for wellknownUser in $(cut -f1 -d: /etc/passwd);
   do
      echo "Jobs owned by $wellknownUser";
      crontab -l -u $wellknownUser;
      echo -e "\n";
      sleep 2;  # (optional sleep 2 seconds) while drinking a coffee
   done

N
Nic0

For me look at /var/spool/cron/crontabs is the best way


this has been answered before
F
Flexo

This script outputs the Crontab to a file and also lists all users confirming those which have no crontab entry:

for user in $(cut -f1 -d: /etc/passwd); do 
  echo $user >> crontab.bak
  echo "" >> crontab.bak
  crontab -u $user -l >> crontab.bak 2>> > crontab.bak
done

// , RobFrost, are you sure this script, as written here, consistently works?
See Why you don't read lines with "for". Also, this has been answered many times before you posted this one.