Як перерахувати всі завдання cron для всіх користувачів?


857

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

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

Потім я міг би об'єднати ці списки з декількох серверів, щоб переглянути загальний "графік подій".

Я збирався сам написати такий сценарій, але якщо хтось уже пішов на біду ...


2
Подібне запитання на Unix SE: unix.stackexchange.com/questions/7053/…
maxschlepzig

Відповіді:


1134

Ви повинні запустити це як root, але:

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

буде циклічно над кожним іменем користувача, перелічуючи їх crontab. Crontabs належать відповідним користувачам, тож ви не зможете бачити кронобуму іншого користувача, не будучи ним або коренем.


Відредагуйте, якщо ви хочете знати, якому користувачеві належить crontab, використовуйтеecho $user

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

53
Не працює, коли користувачі визначені в NIS або LDAP. Вам потрібно скористатисяfor user in $(getent passwd | cut -f1 -d: ); do echo $user; crontab -u $user -l; done
Хуберт Каріо

9
Оновлено це, щоб виключити коментарі та придушити повідомлення "немає crontab для користувачів ...":for user in $(cut -f1 -d: /etc/passwd); do crontab -u $user -l 2>/dev/null | grep -v '^#'; done
Джонатан

38
Чи не було б простіше переглянути файли в / var / spool / cron?
сірий

2
Нам LDAP та / etc / passwd потрібно замінити на гетентну команду:for user in $(getent passwd | awk -F : '{print $1}'); do echo $user; crontab -u $user -l; done
Toby Batch

9
Як щодо cronjobs в /etc/cron.hourly/, /etc/cron.daily/, /etc/cron.weekly/, /etc/cron.monthly/...?
Абдул

309

Я закінчив писати сценарій (я намагаюся навчити себе точнішим баш сценаріям, тому тому ви тут не бачите чогось подібного до Perl). Це не зовсім проста справа, але вона робить більшу частину того, що мені потрібно. Він використовує пропозицію Кайла, щоб шукати хронометри окремих користувачів, але також займається /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/. Мій сценарій - це робота з ними та форматування всього в кінці.
юкондуде

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/а потім файл для кожного користувача. Це, звичайно, лише для користувачів, пов'язаних з кронтабом.

Для Redhat 6/7 та Centos кронтаб знаходиться під /var/spool/cron/.


7
Це працює і на RedHat (/ var / spool / cron) і простіше, ніж писати / запускати сценарій, особливо якщо для управління обліковими записами ви використовуєте щось на зразок Ldap. +1
user49913

6
Це було набагато корисніше мені, ніж будь-які інші відповіді. Цей метод дозволяє переглядати кронти користувачів, яких більше не існує, і надає ВСІ завдання cron відповідно до вимог ОП.
Ендрю Енслі

1
Ще одна перевага цього методу: мій сервер використовує LDAP, тому більшість користувачів не входять /etc/passwd. ІМО, це має бути прийнятою відповіддю, а не усіма грубими рішеннями.
Міккель

1
Тут добре з Suse Linux.
Брет

Так, це також стосується встановлення AWS EC2, ця інформація була дуже корисною!
Іван Мар’янович

34

Тут будуть показані всі записи на кронтабелях від усіх користувачів.

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/*'якщо ви не хочете отримувати корінь. Мій OCD змусив мене розслідувати, чому я не можу судити цю команду як написано. Це було тому, що постійні користувачі не мають доступу до / 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 ist відповідно до відповіді Метта / 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
Дивовижно! Я додав невелику варіацію, щоб побачити, під cat /etc/passwd | sed 's/^\([^:]*\):.*$/echo "\ncrontab for \1:"; sudo crontab -u \1 -l 2>\&1/' | grep -v "no crontab for" | sh
ким

9

Мені подобається простий відповідь з однією лінією вище:

для користувача в $ (cut -f1 -d: / etc / passwd); робити 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

Наступні знімають коментарі, порожні рядки та помилки користувачів, які не містять кронт. Все, що вам залишається, - це чіткий список користувачів та їх роботи.

Зверніть увагу на використання sudoу другому рядку. Якщо ви вже користуєтеся коренем, видаліть його.

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

Я не впевнений, що зміни в першій групі є гарною ідеєю, але добре, що цей сценарій був протестований на 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 не пишуть корисних підказок на початку користувальницької кронтабуляції, тому відсікання перших 11 рядків знищить її вміст. Те саме, якщо користувач Ubuntu відредагував власну crontab та видалив усі руки.
Дейл Андерсон


3

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

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 - це зараз:

  • працює набагато швидше
  • має необов'язкові символи прогресу, щоб ви могли додатково покращити швидкість.
  • використовує роздільник для розділення заголовка та виводу.
  • виводи в компактному форматі, коли всі часові інтервали, які не враховуються, можуть бути узагальнені.
  • Приймає січень ... Дескриптори декаптів на місяці року
  • Приймає пн ... Дескриптори сонця для днів тижня
  • намагається обробити демісійний стиль анамрону, коли його немає
  • намагається розібратися з рядками crontab, які запускають файл після попереднього тестування виконуваності, використовуючи "[-x ...]"
  • намагається розібратися з рядками crontab, які запускають файл після попереднього тестування виконуваності, використовуючи "command -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, ви впевнені, що цей сценарій, як написано тут, стабільно працює?
Натан Басанес

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