it-swarm.com.ru

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

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

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

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

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

793
yukondude

В итоге я написал сценарий (я пытаюсь научить себя тонкостям написания сценариев 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}"
300
yukondude

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

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

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


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

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

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

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

172
Matt

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

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

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

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

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

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

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

==> /var/spool/cron/my_user <==
*/10 1 * * * /path/to/script
28
Jørgen

Небольшое уточнение ответа Кайла Бертона с улучшенным форматированием вывода:

#!/bin/bash
for user in $(cut -f1 -d: /etc/passwd)
do echo $user && crontab -u $user -l
echo " "
done
14
sum
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.

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

13
Mithaldu

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

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

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

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

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

для пользователя в $ (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).

8
squarism
for user in $(cut -f1 -d: /etc/passwd); 
do 
    echo $user; crontab -u $user -l; 
done
7
indra bhushan kumar

Получить список от пользователя ROOT.

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

Далее удаляются комментарии, пустые строки и ошибки от пользователей без 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
Dale Anderson

Зависит от вашей версии 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
Daniel Papasian

Спасибо за этот очень полезный скрипт. У меня были небольшие проблемы с запуском его на старых системах (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
jbbarth

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

Sudo crontab -u userName -l

,

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

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

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

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

Здание на вершине @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    
2
Ali

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

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

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

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

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

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

2
david collier

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

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

Поскольку речь идет о циклическом просмотре файла (/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
fedorqui

В 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
armagedescu