Как мне перечислить все задания cron для всех пользователей?


858

Есть ли команда или существующий сценарий, который позволит мне просматривать все запланированные задания cron системы * NIX одновременно? Я хотел бы, чтобы он включал все пользовательские crontabs, а также /etc/crontabи все, что в /etc/cron.d. Также было бы неплохо увидеть конкретные команды, запущенные run-partsв /etc/crontab.

В идеале, я хотел бы, чтобы выходные данные были в приятной форме столбца и упорядочены каким-либо осмысленным образом.

Затем я мог бы объединить эти списки с нескольких серверов, чтобы просмотреть общий «график событий».

Я собирался написать такой сценарий сам, но если кто-то уже пошел на неприятности ...


2
Аналогичный вопрос по Unix SE: unix.stackexchange.com/questions/7053/…
maxschlepzig

Ответы:


1135

Вы должны запустить это как root, но:

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

будет зацикливаться на каждом имени пользователя, перечисляя его crontab. Crontabs принадлежат соответствующим пользователям, поэтому вы не сможете увидеть crontab другого пользователя без них или root.


Отредактируйте, если вы хотите знать, какому пользователю принадлежит crontab, используйтеecho $user

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

54
Не работает, когда пользователи определены в NIS или LDAP. Вам нужно использоватьfor user in $(getent passwd | cut -f1 -d: ); do echo $user; crontab -u $user -l; done
Hubert Kario

10
Обновлено это, чтобы исключить комментарии и подавить сообщения «нет crontab для пользователя ...»:for user in $(cut -f1 -d: /etc/passwd); do crontab -u $user -l 2>/dev/null | grep -v '^#'; done
Джонатан

38
Не проще ли будет посмотреть файлы в / var / spool / cron?
Graywh

2
Мы, LDAP и / etc / passwd, должны быть заменены командой getent:for user in $(getent passwd | awk -F : '{print $1}'); do echo $user; crontab -u $user -l; done
Пакет Тоби

9
Как насчет cronjobs в /etc/cron.hourly/, /etc/cron.daily/, /etc/cron.weekly/, /etc/cron.monthly/...?
Абдул

309

В итоге я написал сценарий (я пытаюсь научить себя тонкостям написания сценариев bash, поэтому здесь вы не видите ничего похожего на Perl). Это не совсем простое дело, но оно делает большую часть того, что мне нужно. Он использует предложение Кайла для поиска crontabs отдельных пользователей, но и занимается /etc/crontab( в том числе скрипты , запущенные run-partsв /etc/cron.hourly, /etc/cron.dailyи т.д.) , а также рабочие места в /etc/cron.dкаталоге. Он берет все это и объединяет их в нечто вроде следующего:

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

Обратите внимание, что он показывает пользователя и более-менее сортирует по часам и минутам, чтобы я мог видеть ежедневное расписание.

До сих пор я тестировал его на Ubuntu, Debian и 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}"

38
Ничего, но он ничего не делал с системными заданиями cron в / etc / crontab и /etc/cron.d/. Мой сценарий работает с ними и форматирует все в конце.
yukondude

10
yukondude - вы должны подумать над тем, чтобы выложить это на github, даже просто как суть.
Кайл Бертон

3
Попытка скопировать вставку и запустить его, но это не удается: showcrons.sh: строка 59: синтаксическая ошибка рядом с неожиданным маркером <' showcrons.sh: line 59: сделано <<(cut --fields = 1 --delimiter =: / etc / passwd) '
Fraggle

2
@KyleBurton Кажется, по крайней мере, 8 гистов уже копируют это, gist.github.com/gists/…
Zitrax

9
Предупреждение: в этом сценарии отсутствуют события из/etc/anacrontab
ck_

191

В Ubuntu или Debian вы можете просмотреть crontab, /var/spool/cron/crontabs/а затем файл для каждого пользователя. Это только для пользовательских crontab, конечно.

Для Redhat 6/7 и Centos crontab находится под /var/spool/cron/.


7
Это работает и в RedHat (/ var / spool / cron) и проще, чем написание / запуск скрипта, особенно если вы используете что-то вроде Ldap для управления учетными записями. +1
user49913

6
Это было гораздо более полезным для меня, чем любой другой ответ. Этот метод позволяет вам просматривать crontabs пользователей, которые больше не существуют, и дает вам ВСЕ задания cron в соответствии с запросом OP.
Эндрю Энсли

1
Еще одно преимущество этого метода: мой сервер использует LDAP, поэтому большинство пользователей не работают /etc/passwd. ИМО, это должен быть принятый ответ, а не все грубые решения.
Миккель

1
Хорошо с Suse Linux здесь.
Брет

Спасибо, это также верно для AWS EC2, эта информация была очень полезной!
Иван Марьянович

34

Это покажет все записи crontab от всех пользователей.

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

30

Зависит от вашей версии Linux, но я использую:

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

как корень. Очень просто и очень коротко.

Дает мне вывод, как:

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

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

4
Используйте tail -n +1 /var/spool/cron/*для отображения всего содержимого файлов.
Ганс Гинзель,

4
... или sudo sh -c 'tail -n +1 /var/spool/cron/*'если вы не хотите стать пользователем root. Мой ОКР вынудил меня выяснить, почему я не мог выполнить эту команду, как написано. Это было потому, что обычные пользователи не имеют доступа к / var / spool / cron dir, а глобус интерпретировался как буквальный звездный символ, которого, очевидно, не существует.
Дейл Андерсон

в качестве альтернативы, cd /var/spool/cron/cron/ && grep . *также будет печатать соответствующее имя пользователя перед каждым заданием cron
Jakub Kukul


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

Это позволяет избежать путаницы с passwd напрямую, пропускает пользователей, у которых нет записей cron, и для тех, у кого они есть, выводит имя пользователя и их crontab.

Главным образом, опуская это здесь, так что я могу найти это позже, если мне когда-нибудь понадобится искать его снова.


1
В нем также перечислены пользователи LDAP, которых нет в /etc/passwd. Приведенное выше решение Мэтта больше подходит для этой конкретной ситуации, но полезно знать, что команда существует.
Миккель

11

Если вы проверяете кластер с помощью NIS, единственный способ проверить, есть ли у пользователя запись в crontab, соответствует ответу Matt's / var / spool / cron / tabs.

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


10

Этот скрипт работал для меня в CentOS, чтобы перечислить все кроны в среде:

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

2
Потрясающие! Я добавил небольшой вариант, чтобы увидеть, под каким пользователем находится задание cron, и поместил некоторое пространство между результатами: cat /etc/passwd | sed 's/^\([^:]*\):.*$/echo "\ncrontab for \1:"; sudo crontab -u \1 -l 2>\&1/' | grep -v "no crontab for" | shнемного сэкономил время
jamil

9

Мне нравится простой однострочный ответ выше:

для пользователя в $ (cut -f1 -d: / etc / passwd); do crontab -u $ user -l; сделанный

Но в Solaris, который не имеет флага -u и не печатает проверяемого пользователя, вы можете изменить его следующим образом:

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

Вы получите список пользователей без ошибок, выдаваемых crontab, когда учетной записи не разрешено использовать cron и т. Д. Помните, что в Solaris роли также могут быть в / etc / passwd (см. / Etc / user_attr).



Круто. TIL не использовать для.
Квадрат


7

Следующее удаляет комментарии, пустые строки и ошибки от пользователей без crontab. Все, что вам осталось, это четкий список пользователей и их рабочих мест.

Обратите внимание на использование sudoво 2-й строке. Если вы уже root, удалите это.

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

Пример вывода:

# ------ 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

Я использую это на Ubuntu (с 12 по 16) и Red Hat (с 5 по 7).


5

Зависит от вашей версии cron. Используя Vixie cron во FreeBSD, я могу сделать что-то вроде этого:

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

если я хочу, чтобы вкладка была удалена, я мог бы сделать что-то вроде этого:

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

Где это буквальная вкладка в части замены sed.

Это может быть более системно независимым, чтобы проходить через пользователей /etc/passwdи делать crontab -l -u $userдля каждого из них.


4

Спасибо за этот очень полезный скрипт. У меня были небольшие проблемы с запуском его на старых системах (Red Hat Enterprise 3, которые по-разному обрабатывают egrep и табуляции в строках), а также на других системах, где ничего не было в /etc/cron.d/ (тогда скрипт заканчивался ошибкой). Итак, вот патч, чтобы он работал в таких случаях:

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" |

Я не совсем уверен, что изменения в первом egrep - это хорошая идея, но этот скрипт без проблем протестирован на RHEL3,4,5 и Debian5. Надеюсь это поможет!


3

Здание на вершине @Kyle

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

чтобы избежать комментариев обычно вверху / etc / passwd,

И на macosx

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

3
Разве вы не должны grep -v '^#вместо того, чтобы полагаться на магическое число 11?
rr-

1
Дистрибутивы Red Hat / CentOS не пишут полезных советов в начале пользовательского crontab, поэтому обрезание первых 11 строк уничтожит его содержимое. То же самое, если пользователь Ubuntu отредактировал свой собственный crontab и удалил все удерживающие руки.
Дейл Андерсон


3

Я думаю, что лучший вкладыш будет ниже. Например, если у вас есть пользователи в NIS или LDAP, они не будут в / etc / passwd. Это даст вам crontabs каждого пользователя, который вошел в систему.

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


3

Вы можете написать для всего списка пользователей:

sudo crontab -u userName -l

,

Вы также можете перейти к

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

этот файл будет перечислять расписание

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

3

С извинениями и благодаря юкондуде.

Я попытался суммировать настройки времени для легкого чтения, хотя это не идеальная работа, и я не касаюсь вещей «каждую пятницу» или «только по понедельникам».

Это версия 10 - это сейчас:

  • работает намного быстрее
  • имеет дополнительные символы прогресса, чтобы вы могли улучшить скорость дальше.
  • использует разделительную линию для разделения заголовка и вывода.
  • выводит в компактном формате, когда все временные интервалы без учета могут быть суммированы.
  • Принимает январь ... декабрьские дескрипторы месяцев года
  • Принимает Пн ... Солнечные дескрипторы для дней недели
  • пытается обработать дублирование анакрона в стиле Debian, когда оно отсутствует
  • пытается обработать строки crontab, которые запускают файл после предварительного тестирования исполняемости, используя «[-x ...]»
  • пытается обработать строки crontab, которые запускают файл после предварительного тестирования исполняемости с помощью команды -v
  • позволяет использовать интервалы и списки.
  • поддерживает использование частей выполнения в пользовательских файлах / var / spool crontab.

Сейчас я публикую сценарий полностью здесь.

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


2

Поскольку речь идет о циклическом просмотре файла ( /etc/passwd) и выполнении действия, мне не хватает подходящего подхода к вопросу Как можно прочитать файл (поток данных, переменную) построчно (и / или поле за полем) )? :

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

Это читает /etc/passwdпострочно, используя в :качестве разделителя полей. Говоря read -r user _, мы $userудерживаем первое поле и _остальные (это просто нежелательная переменная, чтобы игнорировать поля).

Таким образом, мы можем затем вызвать crontab -uс помощью переменной$user , которую мы цитируем для безопасности (что, если она содержит пробелы? Это вряд ли в таком файле, но вы никогда не узнаете).


1

В Solaris для определенного известного имени пользователя:

crontab -l username

Всем остальным * Nix понадобится -uмодификатор:

crontab -u username -l

Чтобы получить все пользовательские вакансии одновременно в Solaris, как и в других постах выше:

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

-1

Для меня лучше всего посмотреть на / var / spool / cron / crontabs


2
на это уже отвечали
бумми

-2

Этот скрипт выводит Crontab в файл, а также перечисляет всех пользователей, подтверждающих тех, у кого нет записи в crontab:

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, вы уверены, что этот скрипт, как написано здесь, работает последовательно?
Натан Басанезе

Посмотрите, почему вы не читаете строки с "для" . Кроме того, на этот вопрос было дано много ответов, прежде чем опубликовать этот.
Федорки 'ТАК прекрати вредить'
Используя наш сайт, вы подтверждаете, что прочитали и поняли нашу Политику в отношении файлов cookie и Политику конфиденциальности.
Licensed under cc by-sa 3.0 with attribution required.