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

StackOverflow https://stackoverflow.com/questions/134906

  •  02-07-2019
  •  | 
  •  

Вопрос

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

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

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

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

Это было полезно?

Решение 2

В итоге я написал сценарий (я пытаюсь научиться тонкостям написания сценариев на bash, поэтому вы не видите здесь чего-то вроде Perl).Это не совсем простое дело, но оно делает большую часть того, что мне нужно.Он использует предложение Кайла для поиска crontab отдельных пользователей, но также имеет дело с /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}"

Другие советы

Вам придется запустить это как root, но:

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

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


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

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

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

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

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

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

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

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

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

Дает мне вывод вроде:

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

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

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

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

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

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

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

Этот скрипт работал у меня в CentOS для вывода списка всех cron в среде:

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

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

для пользователя в $(cut -f1 -d:/etc/пароль);сделать 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).

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

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

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

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

Зависит от вашей версии 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 для каждого из них.

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

Опираясь на @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    

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

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

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

sudo crontab -u userName -l

,

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

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

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

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

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

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

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

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

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

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

Поскольку речь идет о циклическом переборе файла (/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, который мы цитируем для безопасности (что, если он содержит пробелы?В таком файле это вряд ли, но никогда не узнаешь).

В 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

Для меня лучший способ посмотреть /var/spool/cron/crontabs

Этот скрипт выводит 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
Лицензировано под: CC-BY-SA с атрибуция
Не связан с StackOverflow
scroll top