Làm cách nào để liệt kê tất cả các công việc định kỳ cho tất cả người dùng?


858

Có một lệnh hoặc một tập lệnh hiện có nào cho phép tôi xem tất cả các công việc định kỳ theo lịch trình của hệ thống * NIX không? Tôi muốn nó bao gồm tất cả các crontabs của người dùng, cũng như /etc/crontab, và bất cứ thứ gì có trong đó /etc/cron.d. Nó cũng sẽ được tốt đẹp để xem các lệnh cụ thể do run-partstrong /etc/crontab.

Lý tưởng nhất, tôi muốn đầu ra ở dạng cột đẹp và được sắp xếp theo một cách có ý nghĩa.

Sau đó tôi có thể hợp nhất các danh sách này từ nhiều máy chủ để xem "lịch trình sự kiện" tổng thể.

Tôi đã định tự viết một kịch bản như vậy, nhưng nếu ai đó đã gặp rắc rối ...


2
Câu hỏi tương tự trên Unix SE: unix.stackexchange.com/questions/7053/ triệt
maxschlepzig

Câu trả lời:


1135

Bạn sẽ phải chạy cái này với quyền root, nhưng:

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

sẽ lặp qua từng tên người dùng liệt kê ra crontab của họ. Các crontab được sở hữu bởi người dùng tương ứng, do đó bạn sẽ không thể thấy crontab của người dùng khác là họ hoặc root.


Chỉnh sửa nếu bạn muốn biết crontab thuộc về người dùng nào, hãy sử dụngecho $user

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

54
Không hoạt động khi người dùng được xác định trong NIS hoặc LDAP. Bạn cần sử dụngfor user in $(getent passwd | cut -f1 -d: ); do echo $user; crontab -u $user -l; done
Hubert Kario

10
Đã cập nhật thông tin này để loại trừ nhận xét và loại bỏ tin nhắn 'không crontab cho người dùng ...':for user in $(cut -f1 -d: /etc/passwd); do crontab -u $user -l 2>/dev/null | grep -v '^#'; done
Jonathan

38
Sẽ không dễ dàng hơn khi xem các tệp trong / var / spool / cron?
Graywh

2
Chúng tôi, chúng tôi cần thay thế LDAP và / etc / passwd bằng lệnh getent:for user in $(getent passwd | awk -F : '{print $1}'); do echo $user; crontab -u $user -l; done
Toby Batch

9
Còn về cronjobs trong /etc/cron.hourly/, /etc/cron.daily/, /etc/cron.weekly/, /etc/cron.monthly/...?
Abdull

309

Cuối cùng tôi đã viết một kịch bản (Tôi đang cố gắng dạy cho mình những điểm tốt hơn của kịch bản bash, vì vậy đó là lý do tại sao bạn không thấy một cái gì đó giống như Perl ở đây). Đó không hẳn là một chuyện đơn giản, nhưng nó làm hầu hết những gì tôi cần. Nó sử dụng gợi ý của Kyle cho nhìn lên crontabs người dùng cá nhân, mà còn giao dịch với /etc/crontab(bao gồm các kịch bản đưa ra bởi run-parts/etc/cron.hourly, /etc/cron.dailyvv) và các công việc trong các /etc/cron.dthư mục. Nó lấy tất cả những thứ đó và hợp nhất chúng vào một màn hình giống như sau:

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

Lưu ý rằng nó hiển thị cho người dùng và sắp xếp ít nhiều theo giờ và phút để tôi có thể xem lịch trình hàng ngày.

Cho đến nay, tôi đã thử nghiệm nó trên Ubuntu, Debian và 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
Không có gì, nhưng nó không làm gì với các công việc cron hệ thống trong / etc / crontab và /etc/cron.d/. Đối phó với những điều đó, và định dạng mọi thứ ở cuối, là những gì kịch bản của tôi làm.
yukondude

10
yukondude - bạn nên xem xét đưa nó lên github, thậm chí chỉ là một ý chính.
Kyle Burton

3
Đã thử sao chép dán và chạy nó, nhưng không thành công: showcrons.sh: dòng 59: lỗi cú pháp gần mã thông báo bất ngờ đã <' showcrons.sh: line 59: thực hiện << (cut --fields = 1 --d006iter =: / etc / passwd) '
Fraggle

2
@KyleBurton Dường như có ít nhất 8 ý chính đã sao chép này, gist.github.com/gists/iêu
Zitrax

9
Cảnh báo: Kịch bản này thiếu các sự kiện từ/etc/anacrontab
ck_

191

Trong Ubuntu hoặc debian, bạn có thể xem crontab trước /var/spool/cron/crontabs/và sau đó một tệp cho mỗi người dùng đang ở đó. Điều đó chỉ dành cho crontab dành riêng cho người dùng.

Đối với Redhat 6/7 và Centos, crontab nằm dưới /var/spool/cron/.


7
Điều này cũng hoạt động trên RedHat (/ var / spool / cron) và dễ dàng hơn so với viết / chạy tập lệnh, đặc biệt nếu bạn đang sử dụng một cái gì đó như Ldap để quản lý tài khoản. +1
user49913

6
Điều này hữu ích với tôi hơn bất kỳ câu trả lời nào khác. Phương pháp này cho phép bạn xem các crontabs của người dùng không còn tồn tại nữa, cung cấp cho bạn TẤT CẢ các công việc định kỳ theo yêu cầu của OP.
Andrew Oblley

1
Một lợi ích khác cho phương pháp này: máy chủ của tôi sử dụng LDAP, vì vậy hầu hết người dùng không tham gia /etc/passwd. IMO đây phải là câu trả lời được chấp nhận, hơn là tất cả các giải pháp vũ phu.
Mikkel

1
Tốt với Suse Linux ở đây.
Bret

Thx, điều này cũng đúng với instace AWS EC2, thông tin này rất hữu ích!
Ivan Marjanovic

34

Điều này sẽ hiển thị tất cả các mục crontab từ tất cả người dùng.

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

30

Phụ thuộc vào phiên bản linux của bạn nhưng tôi sử dụng:

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

làm gốc. Rất đơn giản và rất ngắn.

Cung cấp cho tôi đầu ra như:

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

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

4
Sử dụng tail -n +1 /var/spool/cron/*để liệt kê tất cả nội dung của các tập tin.
Hans Ginzel

4
... Hoặc sudo sh -c 'tail -n +1 /var/spool/cron/*'nếu bạn không muốn trở thành root. OCD của tôi buộc tôi phải điều tra lý do tại sao tôi không thể thực hiện lệnh này bằng văn bản. Đó là bởi vì người dùng thông thường không có quyền truy cập vào / var / spool / cron dir và toàn cầu đã được hiểu là một nhân vật ngôi sao theo nghĩa đen, rõ ràng là không tồn tại.
Dale Anderson

cách khác, cd /var/spool/cron/cron/ && grep . *cũng sẽ in tên người dùng tương ứng trước mỗi công việc định kỳ
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}'

Điều này tránh gây rối với passwd trực tiếp, bỏ qua người dùng không có mục cron và đối với những người có chúng, nó sẽ in tên người dùng cũng như crontab của họ.

Chủ yếu là bỏ cái này ở đây mặc dù vậy tôi có thể tìm thấy nó sau này trong trường hợp tôi cần tìm kiếm lại nó.


1
Nó cũng liệt kê người dùng LDAP không có trong /etc/passwd. Giải pháp của Matt ở trên phù hợp hơn với tình huống cụ thể này, nhưng thật tốt khi biết rằng lệnh tồn tại.
Mikkel

11

Nếu bạn kiểm tra một cụm bằng NIS, cách duy nhất để xem người dùng có mục crontab ist theo câu trả lời / var / spool / cron / tab của Matt không.

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

11

Để có được danh sách từ người dùng ROOT.

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

10

Kịch bản này đã làm việc cho tôi trong CentOS để liệt kê tất cả các crons trong môi trường:

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

2
Tuyệt vời! Tôi đã thêm một biến thể nhỏ để xem người dùng nào đang thực hiện công việc định kỳ và đặt khoảng trống giữa các kết quả: cat /etc/passwd | sed 's/^\([^:]*\):.*$/echo "\ncrontab for \1:"; sudo crontab -u \1 -l 2>\&1/' | grep -v "no crontab for" | shtiết kiệm một chút thời gian
jamil

9

Tôi thích câu trả lời đơn giản ở trên:

cho người dùng bằng $ (cut -f1 -d: / etc / passwd); làm crontab -u $ người dùng -l; làm xong

Nhưng Solaris không có cờ -u và không in người dùng đang kiểm tra, bạn có thể sửa đổi nó như sau:

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

Bạn sẽ nhận được một danh sách người dùng mà không có lỗi do crontab đưa ra khi tài khoản không được phép sử dụng cron, v.v ... Hãy lưu ý rằng trong Solaris, các vai trò cũng có thể nằm trong / etc / passwd (xem / etc / user_attr).



Mát mẻ. TIL không sử dụng cho.
squarism


7

Các phần sau đây loại bỏ các bình luận, dòng trống và lỗi từ người dùng không có crontab. Tất cả những gì bạn còn lại là một danh sách rõ ràng về người dùng và công việc của họ.

Lưu ý việc sử dụng sudotrong dòng thứ 2. Nếu bạn đã root, hãy xóa nó.

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

Ví dụ đầu ra:

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

Tôi sử dụng cái này trên Ubuntu (12 đến 16) và Red Hat (5 đến 7).


5

Phụ thuộc vào phiên bản cron của bạn. Sử dụng Vixie cron trên FreeBSD, tôi có thể làm một cái gì đó như thế này:

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

nếu tôi muốn nó được phân định rõ hơn, tôi có thể làm một cái gì đó như thế này:

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

Trường hợp đó là một thẻ theo nghĩa đen trong phần thay thế sed.

Nó có thể độc lập hơn với hệ thống để lặp qua người dùng /etc/passwdvà thực hiện crontab -l -u $usercho từng người trong số họ.


4

Cảm ơn kịch bản rất hữu ích này. Tôi gặp một số vấn đề nhỏ khi chạy nó trên các hệ thống cũ (Red Hat Enterprise 3, xử lý các egrep và tab khác nhau trong chuỗi) và các hệ thống khác không có gì trong /etc/cron.d/ (đoạn script sau đó bị lỗi). Vì vậy, đây là một bản vá để làm cho nó hoạt động trong những trường hợp như vậy:

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

Tôi không thực sự chắc chắn những thay đổi trong egrep đầu tiên là một ý tưởng hay, nhưng tốt, tập lệnh này đã được thử nghiệm trên RHEL3,4,5 và Debian5 mà không gặp vấn đề gì. Hi vọng điêu nay co ich!


3

Xây dựng trên đỉnh @Kyle

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

để tránh các bình luận thường ở đầu / etc / passwd,

Và trên macosx

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

3
Bạn có nên grep -v '^#thay vì dựa vào số ma thuật 11không?
rr-

1
Các bản phân phối Red Hat / CentOS không viết các gợi ý hữu ích khi bắt đầu crontab của người dùng, do đó, việc cắt 11 dòng đầu tiên sẽ xóa sạch nội dung của nó. Điều tương tự nếu một người dùng Ubuntu đã chỉnh sửa crontab của riêng họ và xóa tất cả các thao tác cầm tay.
Dale Anderson



3

bạn có thể viết cho tất cả danh sách người dùng:

sudo crontab -u userName -l

,

Bạn cũng có thể đi đến

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

tập tin này sẽ liệt kê các lịch trình

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

3

Với lời xin lỗi và cảm ơn yukondude.

Tôi đã cố gắng tóm tắt các cài đặt thời gian để dễ đọc, mặc dù đó không phải là một công việc hoàn hảo và tôi không chạm vào 'mỗi thứ Sáu' hoặc 'chỉ vào thứ Hai'.

Đây là phiên bản 10 - bây giờ:

  • chạy nhanh hơn nhiều
  • có các ký tự tiến trình tùy chọn để bạn có thể cải thiện tốc độ hơn nữa.
  • sử dụng một dòng chia để tách tiêu đề và đầu ra.
  • đầu ra trong một định dạng nhỏ gọn khi tất cả các khoảng thời gian uenc bắt gặp có thể được tóm tắt.
  • Chấp nhận tháng một ... Tháng mười hai mô tả cho tháng của năm
  • Chấp nhận Mon ... Mô tả mặt trời cho các ngày trong tuần
  • cố gắng xử lý anacron theo phong cách debian khi mất tích
  • cố gắng xử lý các dòng crontab chạy tệp sau khi thực thi thử nghiệm trước bằng cách sử dụng "[-x ...]"
  • cố gắng xử lý các dòng crontab chạy tệp sau khi thực thi thử nghiệm trước bằng cách sử dụng "lệnh -v"
  • cho phép sử dụng khoảng thời gian và danh sách.
  • hỗ trợ sử dụng các phần chạy trong các tệp crontab dành riêng cho người dùng / var / spool.

Tôi hiện đang xuất bản các kịch bản đầy đủ ở đây.

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


2

Vì đó là vấn đề lặp qua một tệp ( /etc/passwd) và thực hiện một hành động, tôi thiếu cách tiếp cận đúng về cách tôi có thể đọc từng tệp (luồng dữ liệu, biến) theo từng dòng (và / hoặc trường theo từng trường )? :

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

Điều này đọc /etc/passwdtừng dòng bằng cách sử dụng :như dấu phân cách trường. Bằng cách nói read -r user _, chúng tôi thực hiện $usergiữ trường đầu tiên và _phần còn lại (nó chỉ là một biến rác để bỏ qua các trường).

Bằng cách này, sau đó chúng ta có thể gọi crontab -ubằng cách sử dụng biến $usermà chúng tôi trích dẫn để đảm bảo an toàn (nếu nó chứa khoảng trắng thì không chắc trong tệp đó, nhưng bạn không bao giờ có thể biết).


1

Trên Solaris, đối với một tên người dùng được biết đến cụ thể:

crontab -l username

Tất cả * Nix khác sẽ cần -usửa đổi:

crontab -u username -l

Để có được tất cả các công việc của người dùng cùng một lúc trên Solaris, giống như các bài đăng khác ở trên:

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

-1

Đối với tôi, xem / var / spool / cron / crontabs là cách tốt nhất


2
điều này đã được trả lời trước đây
bummi

-2

Tập lệnh này xuất Crontab thành một tệp và cũng liệt kê tất cả người dùng xác nhận những người không có mục 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, bạn có chắc kịch bản này, như được viết ở đây, luôn hoạt động không?
Nathan Basanese

Xem lý do tại sao bạn không đọc các dòng với "cho" . Ngoài ra, điều này đã được trả lời nhiều lần trước khi bạn đăng bài này.
fedorqui 'SO ngừng làm hại'
Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.