Как я могу перечислить все задания cron для всех пользователей?
Есть ли команда или существующий script, который позволит мне просмотреть все заданные задачи cron в системе * NIX сразу? Я бы хотел, чтобы он включал все пользовательские crontabs, а также /etc/crontab
и все в /etc/cron.d
. Также было бы неплохо увидеть, что конкретные команды выполняются run-parts
в /etc/crontab
.
В идеале я хотел бы получить результат в хорошей форме столбца и упорядоченно каким-то значимым образом.
Затем я мог объединить эти списки с нескольких серверов, чтобы просмотреть общее "расписание событий".
Я собирался написать такой script сам, но если кто-то уже попал в беду...
Ответы
Ответ 1
Я закончил писать script (я пытаюсь научить себя более тонким сценариям bash, поэтому почему вы не видите что-то вроде Perl здесь). Это не совсем простое дело, но оно делает большую часть того, что мне нужно. Он использует предложение Kyle для поиска 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 crontab (if it exists). Insert the user 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}"
Ответ 2
Вам нужно будет запустить это как root, но:
for user in $(cut -f1 -d: /etc/passwd); do crontab -u $user -l; done
будет зацикливаться на каждом имени пользователя, перечисляя их crontab. Кронтабы принадлежат соответствующим пользователям, поэтому вы не сможете увидеть другого пользователя crontab без его или root.
Edit
если вы хотите узнать, к какому пользователю принадлежит crontab, используйте echo $user
for user in $(cut -f1 -d: /etc/passwd); do echo $user; crontab -u $user -l; done
Ответ 3
В Ubuntu или Debian вы можете просмотреть crontab в /var/spool/cron/crontabs/
а затем файл для каждого пользователя. Это только для пользовательского crontab конечно.
Для Redhat 6/7 и Centos crontab находится в /var/spool/cron/
.
Ответ 4
Здесь будут показаны все записи crontab от всех пользователей.
sed 's/^\([^:]*\):.*$/crontab -u \1 -l 2>\&1/' /etc/passwd | grep -v "no crontab for" | sh
Ответ 5
Зависит от вашей версии linux, но я использую:
tail -n 1000 /var/spool/cron/*
как root. Очень простой и очень короткий.
Дает мне вывод вроде:
==> /var/spool/cron/root <==
15 2 * * * /bla
==> /var/spool/cron/my_user <==
*/10 1 * * * /path/to/script
Ответ 6
Небольшое уточнение ответа Кайла Бертона с улучшенным форматированием вывода:
#!/bin/bash
for user in $(cut -f1 -d: /etc/passwd)
do echo $user && crontab -u $user -l
echo " "
done
Ответ 7
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.
В основном, отбрасывая это, хотя я могу найти его позже, если мне когда-нибудь понадобится его снова найти.
Ответ 8
Если вы проверяете кластер с использованием NIS, единственный способ проверить, есть ли у пользователя запись crontab ist в соответствии с ответом Matt/var/spool/cron/tabs.
grep -v "#" -R /var/spool/cron/tabs
Ответ 9
Этот script работал у меня в CentOS, чтобы перечислять все crons в среде:
sudo cat /etc/passwd | sed 's/^\([^:]*\):.*$/sudo crontab -u \1 -l 2>\&1/' | grep -v "no crontab for" | sh
Ответ 10
Мне нравится простой однострочный ответ выше:
для пользователя в $(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).
Ответ 11
for user in $(cut -f1 -d: /etc/passwd);
do
echo $user; crontab -u $user -l;
done
Ответ 12
Следующие строки удаляют комментарии, пустые строки и ошибки от пользователей без crontab. Все, что у вас осталось, - это четкий список пользователей и их рабочие места.
Обратите внимание на использование sudo
во второй строке. Если вы уже 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).
Ответ 13
Зависит от вашей версии 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
для каждого из них.
Ответ 14
Спасибо за этот очень полезный script. У меня были небольшие проблемы с запуском на старых системах (Red Hat Enterprise 3, которые обрабатывают по-разному egrep и вкладки в строках), а также другие системы, в которых ничего нет в файле/etc/cron.d/(затем script с ошибкой), Итак, вот патч, чтобы заставить его работать в таких случаях:
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 - хорошая идея, но хорошо, этот script был протестирован на RHEL3,4,5 и Debian5 без каких-либо проблем. Надеюсь, это поможет!
Ответ 15
Построение поверх @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
Ответ 16
Я думаю, что лучший лайнер будет ниже. Например, если у вас есть пользователи в NIS или LDAP, они не будут в /etc/passwd. Это даст вам crontabs каждого пользователя, который вошел в систему.
for I in `lastlog | grep -v Never | cut -f1 -d' '`; do echo $I ; crontab -l -u $I ; done
Ответ 17
вы можете написать для всего списка пользователей:
sudo crontab -u userName -l
,
Вы также можете перейти на
cd /etc/cron.daily/
ls -l
cat filename
В этом файле будут перечислены расписания
cd /etc/cron.d/
ls -l
cat filename
Ответ 18
Получить список от пользователя ROOT.
for user in $(cut -f1 -d: /etc/passwd); do echo $user; sudo crontab -u $user -l; done
Ответ 19
Поскольку речь идет о переходе через файл (/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
, которую мы укажем для обеспечения безопасности (что, если оно содержит пробелы? В этом файле маловероятно, но вы никогда не узнаете).
Ответ 20
Извиняясь за yukondude, я добавил обработку для anacron в его работу, но я изменил стиль в наших домашних условиях.
Я попытался суммировать настройки времени для легкого чтения, хотя это не идеальная работа, и я не касаюсь материала "каждую пятницу".
Это версия 6 - это сейчас:
- проверяет вызванные исполняемые файлы и флаги, отсутствующие или неисполняемые.
- делает лучшую работу по отчетности задач анакрона.
- проверяет столбец "user" записей, которые имеют один против пользователей на машине. Имеет побочный эффект от ловли некоторых ошибок форматирования, которые искажают количество столбцов.
- Принимает вс... СБ дескрипторы для дней недели
- ограничивает ширину вывода для пользовательского терминала.
#!/bin/bash
# @file showCronJobs.sh
#
# version 6
#
# @param Any parameter suppresses 'helpful output' and so emits only the result table.
#
# @copyright None asserted
#
# @author DGC after yukondude
#
# @FIXME DGC 8-Jan-2019
# This file is based on a much simpler example picked up from
# https://stackoverflow.com/questions/134906/how-do-i-list-all-cron-jobs-for-all-users/53892185#53892185
# authored by yukondude.
#
# It has now evolved into a perfect example of tasks which should not be done in bash.
#
# It uses a pile of intermediate temporary files, which we do our best to clear up on exit
# but may still be left cluttering the place up after errors and problems.
#
# The right way to do it is to store the info about tasks in an array of structs.
# The bash code could be improved to use a one-dimensional array, but it can't go that far.
#
# This really needs re-writing in a more capable language.
if [ "root" != "$(whoami)" ]
then
echo "This script can only run as root - quitting."
exit
fi
# Any parameter on the command line requests quiet mode.
#
quiet=false
if [ '0' != "$#" ]
then
quiet=true
fi
#set -e
#set -x
screenColumns="$(tput cols )"
screenRows="$( tput lines)"
if ! ${quiet}
then
cat << EOS
WARNING - this script is clever, but not as clever as you might hope.
It now examines the executables invoked by each cron line, and tries to warn you if they are
not executable.
not present where they are expected to be.
Now there is another thing which can go wrong we we do not yet check,
which is that the executable may be present and executable by root
but not by the user which is scheduled to run it.
You might hope that something on the lines of:
if [ 'yes' = "\$(sudo -u ${user} bash -c "if [ -x ${executableAPAFN} ] ; then echo 'yes' ; else echo 'no'; fi")" ]
would accomplish the required test. But it doesn't.
It turns out that [ -x ] only ever tests the permission bit, and ignores the directory and file rights
to say nothing of the fact that entire filesystems can be mounted as 'non-executable'.
So it is not within our reasonable aspirations to spot a situation where a cron task cannot run for
anything but the simplest reasons.
=============================================================================================================
EOS
fi
# System-wide crontab file and cron job directory. Should be standard.
#
mainCrontabAPAFN='/etc/crontab'
cronAdditionsAPADN='/etc/cron.d'
# Single tab character.
tab=$(echo -en "\t")
# Given a stream of crontab lines:
# replace whitespace characters with a single space
# remove any spaces from the beginning of each line.
# exclude non-cron job lines
# replace '@monthly' and 'Wed' type of tokens with corresponding numeric sequences
# so they can be processed by the rest of the code.
#
# Reads from stdin, and writes to stdout.
# SO DO NOT INSERT ECHO STATEMENTS FOR DEBUGGING HERE!!
#
# @param prefix A string to be prepended to each line we output.
#
function cleanCronLines()
{
prefix="$1"; shift
# @FIXME DGC 28-Jan-2019
# I think we should drop all leading whitespace - this just seems to do one.
while read line
do
# sed "s/\s+/ /g" convert all multiple-spaces to single space
# sed "s/^ //" remove any leading whitespace
#
# grep
# --invert-match emit only lines NOT matching the following pattern...
# ^(|||) match any of these alternatives, but only at start of line
# $ blank line
# # comment line [ disregard leading whitespace. ]
# [[:alnum:]_]+= <identifier>= line [ disregard leading whitespace. ]
#
# sed "s/^@xxxx/0 0 1 1 9/" convert the conventional @xxx tags
# to roughly corresponding 'standard' timing settings.
# the '9' in reboot will be spotted later, and treated specially.
#
# sed "s/ ... Mon /... 1/"
# convert day-of-week tokens in the 5th column into numeric equivalents
#
# sed "s/ ... 0) /... 7/"
# force Sunday to be represented by 7, not zero, as it helps during sorting later.
#
# insert the required prefix.
#
echo "${line}" |
sed -r "s/\s+/ /g" |
sed -r "s/^ //" |
grep -E -v '^$|#|[[:alnum:]_]+=' |
sed -r "s/^@reboot/0 0 1 1 9/" |
sed -r "s/^@hourly/0 * * * */" |
sed -r "s/^@daily/0 0 * * */" |
sed -r "s/^@weekly/0 0 * * 0/" |
sed -r "s/^@monthly/0 0 1 * */" |
sed -r "s/^@annually/0 0 1 1 */" |
sed -r "s/^@yearly/0 0 1 1 */" |
sed -r "s/^([\*/[0-9]+|[\*/[0-9]+|\*) ([\*/[0-9]+|[\*/[0-9]+|\*) ([\*/[0-9]+|[\*/[0-9]+|\*) ([\*/[0-9]+|[\*/[0-9]+|\*) Mon /\1 \2 \3 \4 1 /" |
sed -r "s/^([\*/[0-9]+|[\*/[0-9]+|\*) ([\*/[0-9]+|[\*/[0-9]+|\*) ([\*/[0-9]+|[\*/[0-9]+|\*) ([\*/[0-9]+|[\*/[0-9]+|\*) Tue /\1 \2 \3 \4 2 /" |
sed -r "s/^([\*/[0-9]+|[\*/[0-9]+|\*) ([\*/[0-9]+|[\*/[0-9]+|\*) ([\*/[0-9]+|[\*/[0-9]+|\*) ([\*/[0-9]+|[\*/[0-9]+|\*) Wed /\1 \2 \3 \4 3 /" |
sed -r "s/^([\*/[0-9]+|[\*/[0-9]+|\*) ([\*/[0-9]+|[\*/[0-9]+|\*) ([\*/[0-9]+|[\*/[0-9]+|\*) ([\*/[0-9]+|[\*/[0-9]+|\*) Thu /\1 \2 \3 \4 4 /" |
sed -r "s/^([\*/[0-9]+|[\*/[0-9]+|\*) ([\*/[0-9]+|[\*/[0-9]+|\*) ([\*/[0-9]+|[\*/[0-9]+|\*) ([\*/[0-9]+|[\*/[0-9]+|\*) Fri /\1 \2 \3 \4 5 /" |
sed -r "s/^([\*/[0-9]+|[\*/[0-9]+|\*) ([\*/[0-9]+|[\*/[0-9]+|\*) ([\*/[0-9]+|[\*/[0-9]+|\*) ([\*/[0-9]+|[\*/[0-9]+|\*) Sat /\1 \2 \3 \4 6 /" |
sed -r "s/^([\*/[0-9]+|[\*/[0-9]+|\*) ([\*/[0-9]+|[\*/[0-9]+|\*) ([\*/[0-9]+|[\*/[0-9]+|\*) ([\*/[0-9]+|[\*/[0-9]+|\*) Sun /\1 \2 \3 \4 7 /" |
sed -r "s/^([\*/[0-9]+|[\*/[0-9]+|\*) ([\*/[0-9]+|[\*/[0-9]+|\*) ([\*/[0-9]+|[\*/[0-9]+|\*) ([\*/[0-9]+|[\*/[0-9]+|\*) 0 /\1 \2 \3 \4 7 /" |
sed -r "s/^/${prefix} | /"
done;
}
# Given a stream of cleaned crontab lines,
# if they don't include the run-parts command
# echo unchanged
# if they do
# show each job file in the run-parts directory as if it were scheduled explicitly.
#
# Reads from stdin, and writes to stdout.
# SO DO NOT INSERT ECHO STATEMENTS FOR DEBUGGING HERE!!
#
function lookupRunParts()
{
while read line
do
match=$(echo "${line}" | egrep -o 'run-parts (-{1,2}\S+ )*\S+' )
if [ -z "${match}" ]
then
echo "${line}"
else
# This is awkward code - it needs to know how many fields there are on the line.
# It would be better to split the line in two at the token "run-parts"
#
cronFields=$(echo "${line}" | cut -f1-8 -d' ' )
cronJobDir=$(echo "${match}" | awk '{print $NF}')
#echo "expanding run-parts in '${line}' with cron fields '${cronFields}'"
if [ -d "${cronJobDir}" ]
then
for cronJobFile in "${cronJobDir}"/*
do
if [ -f "${cronJobFile}" ]
then
echo "${cronFields} ${cronJobFile}"
fi
done
fi
fi
done
}
# Temporary files for crontab lines.
#
# The following lines must match the deletion lines in the function below.
#
# A better scheme which created them in a subdirectory,
# and set an exit trap to remove the directory and contents,
# would be better.
#
cronLinesAPAFN="$(mktemp)" || exit 1
cronForUserAPAFN="$(mktemp)" || exit 1
sortedLinesAPAFN="$(mktemp)" || exit 1
annotatedSortedLinesAPAFN="$(mktemp)" || exit 1
deleteTempFiles()
{
# The following lines must match the four creation lines above.
# We delete the files even if they were never created.
#
rm -f "${cronLinesAPAFN}"
rm -f "${cronForUserAPAFN}"
rm -f "${sortedLinesAPAFN}"
rm -f "${annotatedSortedLinesAPAFN}"
}
trap deleteTempFiles EXIT
# Add all of the jobs from the main crontab file.
cat "${mainCrontabAPAFN}" | cleanCronLines "main-crontab" | lookupRunParts > "${cronLinesAPAFN}"
# Add all of the jobs from files in the system-wide cron.d directory.
for cronDotDFileAPAFN in "${cronAdditionsAPADN}"/*
do
fileName="$(basename ${cronDotDFileAPAFN})"
cat ${cronDotDFileAPAFN} | cleanCronLines "cron.d-${fileName}" | lookupRunParts >> "${cronLinesAPAFN}"
done
#echo "Main crontab and cron.d files contain:"
#cat ${cronLinesAPAFN}
#echo "-----------"
#echo
usesAnacron=false
if cat "${cronLinesAPAFN}" | grep -qP "root.*etc/cron\.hourly/0anacron" \
&& [ -f /etc/anacrontab ]
then
usesAnacron=true
# Remove the line which invokes anacron hourly - that isn't a task we need to report.
sed -i '/0anacron/d' "${cronLinesAPAFN}"
if cat "${cronLinesAPAFN}" | grep -qP "root.*etc/cron\.*/0anacron"
then
echo "This script has detected that anacron has been altered to run at some other interval than 'hourly'."
echo "It would be a simple extension of the script to handle this, but we have not written it."
echo "Script will quit."
exit
fi
fi
# Get a list of users on this machine.
declare -a users
knownUsers=0
while read user
do
users[${knownUsers}]="${user}"
(( knownUsers++ ))
done < <(cut --fields=1 --delimiter=: /etc/passwd)
# This only works because user names cannot contain spaces.
#
# sevUsers means "semicolon-encapulated-values"
# the list starts with, ends with, and is separated using, semicolons.
#
sevUsers=";${users[@]};"; sevUsers="${sevUsers// /;}"
# debug.
#echo "sevUsers = '${sevUsers}'"
# Examine each user crontab (if it exists). Insert the user name between the
# five time fields and the command.
checkUser=0
while [ "${checkUser}" -lt "${knownUsers}" ]
do
user="${users[${checkUser}]}"
# Note that this edit will fail on a malformed line.
#
crontab -l -u "${user}" 2>/dev/null | \
cleanCronLines "${user}-crontab" | \
sed -r "s/^(\S+) \| ((\S+ +){5})(.+)$/\1 | \2 ${user} \4/" \
> ${cronForUserAPAFN}
while IFS= read -r cronLine
do
echo "${cronLine}" >> "${cronLinesAPAFN}"
done < ${cronForUserAPAFN}
(( checkUser++ ))
done
#echo "Main crontab plus user crontabs contain:"
#cat ${cronLinesAPAFN}
#echo "-----------"
#echo
# The following section simply assumes that no-one has altered the standard /etc/anacrontab file
# We do not completely deal with the
# START_HOURS_RANGE
# and
# RANDOM_DELAY
# parameters.
# However we do now carry them through, and print them rather cryptically on the output.
#
# I think each task can set a further timing setting ( called 'base delay' below )
# which we have not read up about, and completely ignore.
#
# Use of the START_HOURS_RANGE setting
# makes the assumption that jobs run under this system are limited to 'regular housekeeping'
# tasks which it is reasonable to suppress or put-off-till-later during certain periods of the day.
#
# That file on a server we looked at read:
#
# # /etc/anacrontab: configuration file for anacron
#
# # See anacron(8) and anacrontab(5) for details.
#
# SHELL=/bin/sh
# PATH=/sbin:/bin:/usr/sbin:/usr/bin
# MAILTO=root
# # the maximal random delay added to the base delay of the jobs
# RANDOM_DELAY=45
# # the jobs will be started during the following hours only
# START_HOURS_RANGE=3-22
#
# #period in days delay in minutes job-identifier command
# 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
#
if ${usesAnacron}
then
rangeSetting="$(cat /etc/anacrontab | grep "START_HOURS_RANGE" | sed 's/START_HOURS_RANGE=//')"
delaySetting="$(cat /etc/anacrontab | grep "RANDOM_DELAY" | sed 's/RANDOM_DELAY=//' )"
if [ -n "${rangeSetting}" ]
then
anacronPrefix="anacron_${rangeSetting}"
else
anacronPrefix="anacron"
fi
if [ -n "${delaySetting}" ]
then
anacronPrefix="${anacronPrefix}[~${delaySetting}]"
fi
# The following code inserts strings including '98',
# which will sort anacron tasks after non-anacron tasks
# in the task list we print out.
# ( you could try using -1 to sort them 'before'. )
#
# We expect to spot those impossible values and replace them in the final output.
# In a non-systemd unit, apparently anacron is only run daily.
# ( which of course is good enough to run it sub-tasks daily/weekly/monthly )
# In a systemd machine it is run hourly. See:
# https://unix.stackexchange.com/questions/478803/is-it-true-that-cron-daily-runs-anacron-everyhour
# However even if run hourly it does not take control of other tasks inj /etc/cron.hourly.
# Apparently all anacron tasks run as root.
if [ -d /etc/cron.daily ]
then
if find /etc/cron.daily -mindepth 1 -type f | read
then
for file in $(ls /etc/cron.daily/* )
do
echo "${anacronPrefix} | 98 98 * * * root ${file}" >> "${cronLinesAPAFN}"
done
fi
fi
if [ -d /etc/cron.weekly ]
then
if find /etc/cron.weekly -mindepth 1 -type f | read
then
for file in $(ls /etc/cron.weekly/* )
do
echo "${anacronPrefix} | 98 98 * * 98 root ${file}" >> "${cronLinesAPAFN}"
done
fi
fi
if [ -d /etc/cron.monthly ]
then
if find /etc/cron.weekly -mindepth 1 -type f | read
then
for file in $(ls /etc/cron.monthly/* )
do
echo "${anacronPrefix} | 98 98 1 * * root ${file}" >> "${cronLinesAPAFN}"
done
fi
fi
fi
#echo "All cron lines from all sources:"
#cat ${cronLinesAPAFN} | sed -r "s/\t/->/g"
#echo "-----------"
#echo
#
# cron lines consist of six fields with predictable formats, followed by a command line with optional embedded spaces.
#
# Output the collected crontab lines.
# Replace the single spaces between the 6 fields with tab characters.
# Sort the lines by hour and minute.
# Insert the header line.
# Format the results as a table.
#
#example:
# root-crontab | 10 1 * * * /usr/local/sbin/hostmaker fred george
tabbedLines=$(cat "${cronLinesAPAFN}" | \
sed -r "s/^(\S+) \| (\S+) +(\S+) +(\S+) +(\S+) +(\S+) +(\S+) +(\S+) *(.*)$/\1 |\t\2\t\3\t\4\t\5\t\6\t\7\t\8 \9/" \
)
#echo "tabbedLines ="
#echo "${tabbedLines}"| cut -d"${tab}" -f6 # sed -r "s/\t/->/g"
#echo "-------------------"
# Replace asteisk values with 99 - which is normally bigger than any legal value
#
# We expect to spot those impossible values and replace them in the final output
# usually with a meaningful work like 'weekly' but failing that, back to asterisk.
#
echo "${tabbedLines}" | \
sed -r "s/\*\t/99\t/" | \
sort -t"${tab}" -k6,6n -k5,5n -k4,4n -k3,3n -k2,2n | \
sed -r "s/99\t/*\t/" \
> ${sortedLinesAPAFN}
#echo "Sorted lines ="
#cat "${sortedLinesAPAFN}"
#echo "-------------------"
#echo "users and executables="
#cat "${sortedLinesAPAFN}" | cut -d"$tab" -f 7- | cut -d' ' -f1-2
#echo "-------------------"
: > ${annotatedSortedLinesAPAFN}
while read sortedLine
do
user=$( echo -e "${sortedLine}" | cut -d"$tab" -f 7 )
executable=$(echo -e "${sortedLine}" | cut -d"$tab" -f 8 | cut -d' ' -f1)
#debug
# echo
# echo "'${sevUsers}'"
# echo "';${user};'"
# echo
# We will label the lines 'MALFORMED' so they shouldn't be missed,
# the moans here are suppressed by the 'quiet' flag.
if [ -z "${executable}" ]
then
if ! ${quiet}
then
echo
echo "ERROR!!!!! A cron entry is malformed - probably too few fields - making it seem to have no executable command."
echo "The line was ( similar to ): '${sortedLine}'"
echo
fi
executableTag="MALFORMED\t"
elif [ "${user}" = "*" ]
then
if ! ${quiet}
then
echo "ERROR!!!!! A cron entry is malformed - probably too many fields - making it seem to use a user of star."
echo "The line was ( similar to ): '${sortedLine}'"
echo
fi
executableTag="MALFORMED\t"
elif [[ ! "${sevUsers}" =~ ";${user};" ]] # See if ;<user>; is anywhere in the list of known users.
then
if ! ${quiet}
then
echo
echo "ERROR!!!!! User '${user}' given in a cron entry is not a known user on this machine."
echo "The line was ( similar to ): '${sortedLine}'"
echo
fi
executableTag="MALFORMED\t"
elif [ "/" = "${executable:0:1}" ]
then
executableAPAFN="${executable}"
if [ -f "${executableAPAFN}" ]
then
# See comment at the top of the file about how we would like to know if $user can execute this
# but testing that is too difficult to try here.
#
if [ -x "${executable}" ]
then
executableTag="executable\t"
else
executableTag="DISABLED !!!\t"
fi
else
executableTag="MISSING !!!\t"
fi
else
if which ${executable} > /dev/nul 2>&1
then
executableTag="executable\t"
else
executableTag="MISSING OR DISABLED !!!\t"
fi
fi
# echo "${executableTag} '${sortedLine}'"
echo "${annotatedSortedLines}${executableTag}| ${sortedLine}" >> ${annotatedSortedLinesAPAFN}
done < ${sortedLinesAPAFN}
#echo "annotatedSortedLines ="
#cat "${annotatedSortedLinesAPAFN}"
#echo "-------------------"
# We treat a repeat at any number of minutes past the hour as 'hourly' for our purposes.
# These lines convert
# executable | anacron_3-22[~45] | daily at 98:98 root /etc/cron.daily/logrotate
# into
# executable | anacron_3-22[~45] | daily root /etc/cron.daily/logrotate
#
# It would be more sophisticated to convert them to
# executable | anacron | daily < 45 mins after 03:00 root /etc/cron.daily/logrotate
# Remove all leading zeroes on numbers
# Substitute human-radable versiosn of common numeric sequences.
#
sortedLinesTranslated=$(cat "${annotatedSortedLinesAPAFN}" |
sed -r "s/ 0([0-9])/ \1/" |
sed -r "s/\t0([0-9])\t/\t\1\t/" |
sed -r "s/\t0\t0\t1\t1\t9/ on reboot\t\t\t\t/" |
sed -r "s/\t\*\/([0-9]*)\t\*\t\*\t\*\t\*/ every \1 minutes\t\t\t\t/" |
sed -r "s/\t\*\t\*\t\*\t\*\t\*/ each minute\t\t\t\t/" |
sed -r "s/\t[0-9][0-9]?\t\*\t\*\t\*\t\*/ hourly\t\t\t\t/" |
sed -r "s/\t([0-9]*)\t([0-9]*)\t\*\t\*\t\*/ daily at \2:\1\t\t\t\t/" |
sed -r "s/daily at 98:98/daily/" |
sed -r "s/\t0\t0\t\*\t\*\t0/ start of week\t\t\t\t/" |
sed -r "s/\t98\t98\t\*\t\*\t0/ weekly\t\t\t\t/" |
sed -r "s/\t0\t0\t1\t\*\t\*/ start of month\t\t\t\t/" |
sed -r "s/\t98\t98\t1\t\*\t\*/ monthly\t\t\t\t/" |
sed -r "s/\t([0-9]*)\t([0-9]*)\t([0-9]*)\t\*\t\*/ \3 of month at \2:\1\t\t\t\t/" |
sed -r "s/\t([0-9]*)\t([0-9]*)\t\*\t\*\t0*1/ Monday at \2:\1\t\t\t\t/" |
sed -r "s/\t([0-9]*)\t([0-9]*)\t\*\t\*\t0*2/ Tuesday at \2:\1\t\t\t\t/" |
sed -r "s/\t([0-9]*)\t([0-9]*)\t\*\t\*\t0*3/ Wednesday at \2:\1\t\t\t\t/" |
sed -r "s/\t([0-9]*)\t([0-9]*)\t\*\t\*\t0*4/ Thursday at \2:\1\t\t\t\t/" |
sed -r "s/\t([0-9]*)\t([0-9]*)\t\*\t\*\t0*5/ Friday at \2:\1\t\t\t\t/" |
sed -r "s/\t([0-9]*)\t([0-9]*)\t\*\t\*\t0*6/ Saturday at \2:\1\t\t\t\t/" |
sed -r "s/\t([0-9]*)\t([0-9]*)\t\*\t\*\t0*7/ Sunday at \2:\1\t\t\t\t/" |
sed -r "s/\t0\t0\t1\t1\t\*/ yearly\t\t\t\t/" )
#echo "sortedLinesTranslated ="
#echo -e "${sortedLinesTranslated}"
#echo "-------------------"
if ! ${quiet}
then
cat <<EOS
Common timing intervals below are converted to more readable form.
However some more obscure possible combinations
( such as "run at 3AM on the first Friday of each month" )
are not handled, and will show using the original
min hour day-of-month month day-of-week
format"
Anacron timings are printed in a rather cryptic code.
executable | anacron_3-22[~45] | daily root /etc/cron.daily/logrotate
( meaning tasks can only start between 03:00 and 22:00 hours,
and will be randomly delayed up to 45 minutes ).
If we are only using daily/weekly/monthly anacron lists.
you would think tasks would start somewhere near the beginning of the permitted window.
( which is what we observe ) so it isnt clear what the 22:00 info could be useful for.
We think it may relate to the per-anacron-task delay we currently ignore.
should be read as:
executable | anacron | daily < 45 mins after 03:00 root /etc/cron.daily/logrotate
------------------------------ Cron tasks on this machine ------------------------------
EOS
fi
sortedLinesXlHdr="$(echo " \t| \t| min\thr\tdom\tmo\tdow\tuser\tcommand" ; \
echo -e "${sortedLinesTranslated}" )"
#echo "sortedLinesXlHdr ="
#echo -e "${sortedLinesXlHdr}"
#echo "-------------------"
echo ""
echo -e "${sortedLinesXlHdr}" |
sed 's/ | /\t| /g' |
column -s"${tab}" -t |
cut -c1-${screenColumns}
echo
Ответ 21
В 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
Ответ 22
Для меня лучше всего смотреть/var/spool/cron/crontabs
Ответ 23
Этот script выводит 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