Bagaimana cara mendaftar semua pekerjaan cron untuk semua pengguna?

858

Apakah ada perintah atau skrip yang ada yang akan membiarkan saya melihat semua tugas cron terjadwal sistem * NIX sekaligus? Saya ingin memasukkan semua crontab pengguna, juga /etc/crontab, dan apa pun yang ada di dalamnya/etc/cron.d . Ini juga akan baik untuk melihat perintah tertentu dijalankan oleh run-partsdi /etc/crontab.

Idealnya, saya ingin output dalam bentuk kolom yang bagus dan dipesan dengan cara yang bermakna.

Saya kemudian dapat menggabungkan daftar ini dari beberapa server untuk melihat "jadwal acara" secara keseluruhan.

Aku akan menulis skrip semacam itu sendiri, tetapi jika seseorang sudah pergi ke masalah ...

Yukondude
sumber
2
Pertanyaan serupa di Unix SE: unix.stackexchange.com/questions/7053/…
maxschlepzig

Jawaban:

1135

Anda harus menjalankan ini sebagai root, tetapi:

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

akan mengulang setiap nama pengguna yang mencantumkan crontab mereka. Crontab dimiliki oleh masing-masing pengguna sehingga Anda tidak akan dapat melihat crontab pengguna lain tanpa menjadi mereka atau root.


Edit jika Anda ingin tahu milik pengguna crontab mana, gunakanecho $user

for user in $(cut -f1 -d: /etc/passwd); do echo $user; crontab -u $user -l; done
Kyle Burton
sumber
54
Tidak berfungsi saat pengguna didefinisikan dalam NIS atau LDAP. Anda perlu menggunakanfor user in $(getent passwd | cut -f1 -d: ); do echo $user; crontab -u $user -l; done
Hubert Kario
10
Diperbarui untuk mengecualikan komentar dan menekan pesan 'tidak ada crontab untuk pengguna ...':for user in $(cut -f1 -d: /etc/passwd); do crontab -u $user -l 2>/dev/null | grep -v '^#'; done
Jonathan
38
Bukankah lebih mudah untuk melihat file di / var / spool / cron?
graywh
2
Kita kita LDAP dan / etc / passwd perlu diganti dengan perintah getent:for user in $(getent passwd | awk -F : '{print $1}'); do echo $user; crontab -u $user -l; done
Toby Batch
9
Bagaimana dengan cronjobs di /etc/cron.hourly/, /etc/cron.daily/, /etc/cron.weekly/, /etc/cron.monthly/...?
Abdull
309

Saya akhirnya menulis skrip (saya mencoba untuk belajar sendiri poin-poin yang lebih baik dari bash scripting, jadi itu sebabnya Anda tidak melihat sesuatu seperti Perl di sini). Ini sebenarnya bukan urusan yang sederhana, tetapi melakukan sebagian besar dari apa yang saya butuhkan. Menggunakan saran Kyle untuk mencari crontab pengguna individu, tetapi juga berkaitan dengan /etc/crontab(termasuk script diluncurkan oleh run-partsdi /etc/cron.hourly, /etc/cron.daily, dll) dan pekerjaan di /etc/cron.ddirektori. Dibutuhkan semua itu dan menggabungkannya ke tampilan sesuatu seperti berikut:

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

Perhatikan bahwa ini menunjukkan kepada pengguna, dan lebih banyak atau lebih sedikit mengurutkan berdasarkan jam dan menit sehingga saya dapat melihat jadwal harian.

Sejauh ini, saya sudah mengujinya di Ubuntu, Debian, dan 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}"
Yukondude
sumber
38
Tidak ada, tetapi tidak melakukan apa-apa tentang pekerjaan sistem cron di / etc / crontab dan /etc/cron.d/. Berurusan dengan itu, dan memformat semuanya pada akhirnya, adalah apa yang dilakukan skrip saya.
yukondude
10
yukondude - Anda harus mempertimbangkan menempatkan ini di github, bahkan hanya sebagai intisari.
Kyle Burton
3
Mencoba menyalin dan menjalankannya, tetapi gagal: showcrons.sh: baris 59: kesalahan sintaks dekat token yang tak terduga <' showcrons.sh: line 59: dilakukan <<(cut --fields = 1 --delimiter =: / etc / passwd) '
Fraggle
2
@KyleBurton Tampaknya setidaknya 8 gists sudah menyalin ini, gist.github.com/gists/...
Zitrax
9
Peringatan: Skrip ini tidak memiliki acara dari/etc/anacrontab
ck_
191

Di bawah Ubuntu atau debian, Anda dapat melihat crontab oleh /var/spool/cron/crontabs/ dan kemudian file untuk setiap pengguna ada di sana. Itu hanya untuk crontab khusus pengguna saja.

Untuk Redhat 6/7 dan Centos, crontab berada di bawah /var/spool/cron/.

caot
sumber
7
Ini berfungsi pada RedHat juga (/ var / spool / cron) dan lebih mudah daripada menulis / menjalankan skrip terutama jika Anda menggunakan sesuatu seperti Ldap untuk mengelola akun. +1
user49913
6
Ini jauh lebih bermanfaat bagi saya daripada jawaban lain mana pun. Metode ini memungkinkan Anda untuk melihat crontab pengguna yang tidak ada lagi, memberi Anda SEMUA pekerjaan cron seperti yang diminta oleh OP.
Andrew Ensley
1
Manfaat lain untuk metode ini: server saya menggunakan LDAP, jadi sebagian besar pengguna tidak masuk /etc/passwd. IMO ini harus menjadi jawaban yang diterima, daripada semua solusi brute-force.
Mikkel
1
Bagus dengan Suse Linux di sini.
Bret
Terima kasih, ini juga berlaku untuk AWS EC2 instace, info ini sangat membantu!
Ivan Marjanovic
34

Ini akan menampilkan semua entri crontab dari semua pengguna.

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

Tergantung pada versi linux Anda tetapi saya menggunakan:

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

sebagai root. Sangat sederhana dan sangat singkat.

Memberikan saya keluaran seperti:

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

==> /var/spool/cron/my_user <==
*/10 1 * * * /path/to/script
Jørgen
sumber
4
Gunakan tail -n +1 /var/spool/cron/*untuk membuat daftar semua konten file.
Hans Ginzel
4
... atau sudo sh -c 'tail -n +1 /var/spool/cron/*'jika Anda tidak ingin menjadi root. OCD saya memaksa saya untuk menyelidiki mengapa saya tidak bisa menjalankan perintah ini seperti yang tertulis. Itu karena pengguna biasa tidak memiliki akses ke / var / spool / cron dir, dan glob ditafsirkan sebagai karakter bintang literal, yang jelas tidak ada.
Dale Anderson
sebagai alternatif, cd /var/spool/cron/cron/ && grep . *juga akan mencetak nama pengguna yang sesuai di depan setiap pekerjaan cron
Jakub Kukul
15

Penyempurnaan kecil jawaban Kyle Burton dengan pemformatan output yang ditingkatkan:

#!/bin/bash
for user in $(cut -f1 -d: /etc/passwd)
do echo $user && crontab -u $user -l
echo " "
done
jumlah
sumber
Lihat Mengapa Anda tidak membaca baris dengan "untuk" .
fedorqui 'SO stop harming'
14
getent passwd | cut -d: -f1 | perl -e'while(<>){chomp;$l = `crontab -u $_ -l 2>/dev/null`;print "$_\n$l\n" if $l}'

Ini menghindari mengacaukan passwd secara langsung, melompati pengguna yang tidak memiliki entri cron dan bagi mereka yang memilikinya, ia mencetak nama pengguna serta crontab mereka.

Sebagian besar menjatuhkan ini di sini sehingga saya dapat menemukannya nanti kalau-kalau saya perlu mencarinya lagi.

Mithaldu
sumber
1
Ini juga mencantumkan pengguna LDAP yang tidak hadir /etc/passwd. Solusi Matt di atas lebih tepat untuk situasi khusus ini, tetapi ada baiknya mengetahui bahwa perintah itu ada.
Mikkel
11

Jika Anda memeriksa sebuah cluster menggunakan NIS, satu-satunya cara untuk melihat apakah pengguna memiliki entri crontab menurut jawaban Matt / var / spool / cron / tab.

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

Untuk mendapatkan daftar dari pengguna ROOT.

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

Skrip ini berfungsi untuk saya di CentOS untuk mendaftar semua crons di lingkungan:

sudo cat /etc/passwd | sed 's/^\([^:]*\):.*$/sudo crontab -u \1 -l 2>\&1/' | grep -v "no crontab for" | sh
Sam T
sumber
2
Luar biasa! Saya menambahkan sedikit variasi untuk melihat di mana pengguna di mana pekerjaan cron berada di bawah dan memberi sedikit ruang di antara hasil: cat /etc/passwd | sed 's/^\([^:]*\):.*$/echo "\ncrontab for \1:"; sudo crontab -u \1 -l 2>\&1/' | grep -v "no crontab for" | shmenghemat sedikit waktu
jamil
9

Saya suka jawaban satu baris sederhana di atas:

untuk pengguna dalam $ (cut -f1 -d: / etc / passwd); lakukan crontab -u $ user -l; selesai

Tetapi Solaris yang tidak memiliki flag -u dan tidak mencetak pengguna yang sedang diperiksa, Anda dapat memodifikasinya seperti ini:

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

Anda akan mendapatkan daftar pengguna tanpa kesalahan yang dilemparkan oleh crontab ketika akun tidak diizinkan untuk menggunakan cron dll. Perlu diketahui bahwa di Solaris, peran bisa juga di / etc / passwd (lihat / etc / user_attr).

squarism
sumber
1
Lihat Mengapa Anda tidak membaca baris dengan "untuk" .
fedorqui 'SO stop harming'
Keren. TIL tidak digunakan untuk.
squarism
8
for user in $(cut -f1 -d: /etc/passwd); 
do 
    echo $user; crontab -u $user -l; 
done
indra bhushan kumar
sumber
Lihat Mengapa Anda tidak membaca baris dengan "untuk" . Juga, jawaban ini hanya mengulangi yang lain.
fedorqui 'SO stop harming'
7

Berikut menghapus komentar, baris kosong, dan kesalahan dari pengguna tanpa crontab. Yang tersisa hanyalah daftar pengguna dan pekerjaan mereka yang jelas.

Perhatikan penggunaan sudodi baris ke-2. Jika Anda sudah root, hapus itu.

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

Contoh output:

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

Saya menggunakan ini di Ubuntu (12 melalui 16) dan Red Hat (5 melalui 7).

Dale Anderson
sumber
5

Tergantung pada versi cron Anda. Dengan menggunakan Vixie cron di FreeBSD, saya dapat melakukan sesuatu seperti ini:

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

jika saya ingin lebih banyak tab dibatasi, saya mungkin melakukan sesuatu seperti ini:

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

Di mana itu adalah tab literal di bagian pengganti sed.

Ini mungkin lebih sistem independen untuk loop melalui pengguna /etc/passwddan lakukan crontab -l -u $useruntuk masing-masing.

Daniel Papasian
sumber
4

Terima kasih untuk skrip yang sangat berguna ini. Saya memiliki beberapa masalah kecil yang menjalankannya pada sistem lama (Red Hat Enterprise 3, yang menangani egrep dan tab dalam string secara berbeda), dan sistem lain tanpa apa pun di /etc/cron.d/ (skrip kemudian diakhiri dengan kesalahan). Jadi di sini ada tambalan untuk membuatnya berfungsi dalam kasus seperti ini:

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

Saya tidak begitu yakin perubahan pada egrep pertama adalah ide yang bagus, tetapi yah, skrip ini telah diuji pada RHEL3,4,5 dan Debian5 tanpa masalah. Semoga ini membantu!

jbbarth
sumber
3

Membangun di atas @Kyle

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

untuk menghindari komentar yang biasanya ada di bagian atas / etc / passwd,

Dan di macosx

for user in $(dscl . -list /users | cut -f1 -d:); do echo $user; crontab -u $user -l; done    
Ali
sumber
3
Bukankah seharusnya kamu grep -v '^#bukannya mengandalkan angka ajaib 11?
rr-
1
Distro Red Hat / CentOS tidak menulis petunjuk bermanfaat di awal crontab pengguna, jadi memotong 11 baris pertama akan melenyapkan kontennya. Hal yang sama jika pengguna Ubuntu telah mengedit crontab mereka sendiri dan menghapus semua pegangan tangan.
Dale Anderson
Lihat Mengapa Anda tidak membaca baris dengan "untuk" .
fedorqui 'SO stop harming'
3

Saya pikir liner yang lebih baik akan di bawah. Sebagai contoh jika Anda memiliki pengguna di NIS atau LDAP mereka tidak akan berada di / etc / passwd. Ini akan memberi Anda crontab dari setiap pengguna yang telah masuk.

for I in `lastlog | grep -v Never | cut -f1 -d' '`; do echo $I ; crontab -l -u $I ; done
Monte
sumber
Lihat Mengapa Anda tidak membaca baris dengan "untuk" .
fedorqui 'SO stop harming'
3

Anda dapat menulis untuk semua daftar pengguna:

sudo crontab -u userName -l

,

Anda juga bisa pergi ke

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

file ini akan mencantumkan jadwal

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

Dengan permintaan maaf dan terima kasih kepada yukondude.

Saya sudah mencoba untuk meringkas pengaturan waktu untuk membaca mudah, meskipun itu bukan pekerjaan yang sempurna, dan saya tidak menyentuh 'setiap hari Jumat' atau 'hanya pada hari Senin'.

Ini adalah versi 10 - sekarang:

  • berjalan jauh lebih cepat
  • memiliki karakter kemajuan opsional sehingga Anda dapat meningkatkan kecepatan lebih lanjut.
  • menggunakan garis pembagi untuk memisahkan header dan output.
  • output dalam format ringkas saat semua interval waktu yang dihitung dapat dirangkum.
  • Terima Jan ... Des deskriptor selama berbulan-bulan
  • Terima Mon ... deskriptor Sun selama berhari-hari
  • mencoba menangani dummy-up anacron gaya debian ketika hilang
  • mencoba menangani garis-garis crontab yang menjalankan file setelah pra-pengujian eksekusi menggunakan "[-x ...]"
  • mencoba menangani garis-garis crontab yang menjalankan file setelah pra-pengujian kemampuan eksekusi menggunakan "command -v"
  • memungkinkan penggunaan rentang interval dan daftar.
  • mendukung penggunaan run-parts dalam file crontab / var / spool khusus pengguna.

Saya sekarang menerbitkan skrip secara lengkap di sini.

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

david collier
sumber
2

Karena ini adalah masalah pengulangan melalui file ( /etc/passwd) dan melakukan tindakan, saya kehilangan pendekatan yang tepat pada Bagaimana saya bisa membaca file (aliran data, variabel) baris demi baris (dan / atau bidang demi bidang )? :

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

Ini membaca /etc/passwdbaris demi baris menggunakan :sebagai pembatas bidang. Dengan mengatakan read -r user _, kita $usermenahan bidang pertama dan _sisanya (itu hanya variabel sampah untuk mengabaikan bidang).

Dengan cara ini, kita kemudian dapat memanggil crontab -umenggunakan variabel $user, yang kami kutip untuk keselamatan (bagaimana jika itu berisi spasi? Tidak mungkin dalam file tersebut, tetapi Anda tidak pernah tahu).

fedorqui 'SO berhenti merugikan'
sumber
1

Di Solaris, untuk nama pengguna tertentu yang dikenal:

crontab -l username

Semua yang lain * Nix perlu -upengubah:

crontab -u username -l

Untuk mendapatkan semua pekerjaan pengguna sekaligus di Solaris, seperti pos lainnya di atas:

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

Bagi saya melihat / var / spool / cron / crontab adalah cara terbaik

Nic0
sumber
2
ini telah dijawab sebelumnya
bummi
-2

Skrip ini menampilkan Crontab ke file dan juga mencantumkan semua pengguna yang mengonfirmasi mereka yang tidak memiliki entri 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
Rob Frost
sumber
//, RobFrost, apakah Anda yakin skrip ini, seperti yang ditulis di sini, secara konsisten berfungsi?
Nathan Basanese
Lihat Mengapa Anda tidak membaca baris dengan "untuk" . Juga, ini telah dijawab berkali-kali sebelum Anda memposting yang ini.
fedorqui 'SO stop harming'