Jak wyświetlić listę wszystkich zadań CRON dla wszystkich użytkowników?

857

Czy istnieje polecenie lub istniejący skrypt, który pozwoli mi jednocześnie wyświetlić wszystkie zaplanowane zadania Crona systemu * NIX? Chciałbym, aby obejmowało wszystkie crontabs użytkownika, a także /etc/crontabcokolwiek w nim jest /etc/cron.d. Byłoby również miło widzieć konkretne polecenia uruchamiane przez run-partsw /etc/crontab.

Idealnie, chciałbym otrzymać wynik w ładnej formie kolumny i uporządkować w jakiś znaczący sposób.

Mógłbym następnie scalić te wykazy z wielu serwerów, aby wyświetlić ogólny „harmonogram wydarzeń”.

Już miałem napisać taki scenariusz, ale jeśli ktoś już zadał sobie trud ...

yukondude
źródło
2
Podobne pytanie dotyczące Unix SE: unix.stackexchange.com/questions/7053/...
maxschlepzig

Odpowiedzi:

1134

Będziesz musiał uruchomić to jako root, ale:

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

zapętli każdą nazwę użytkownika, wyliczając ich crontab. Crontabs są własnością odpowiednich użytkowników, więc nie będzie można zobaczyć crontaba innego użytkownika bez niego lub roota.


Edytuj, jeśli chcesz wiedzieć, do którego użytkownika należy crontab, użyjecho $user

for user in $(cut -f1 -d: /etc/passwd); do echo $user; crontab -u $user -l; done
Kyle Burton
źródło
53
Nie działa, gdy użytkownicy są zdefiniowani w NIS lub LDAP. Musisz użyćfor user in $(getent passwd | cut -f1 -d: ); do echo $user; crontab -u $user -l; done
Hubert Kario
9
Zaktualizowałem to, aby wykluczyć komentarze i ukryć wiadomości „nie ma pliku crontab dla użytkownika ...”:for user in $(cut -f1 -d: /etc/passwd); do crontab -u $user -l 2>/dev/null | grep -v '^#'; done
Jonathan
38
Czy nie byłoby łatwiej patrzeć na pliki w / var / spool / cron?
graywh
2
My, LDAP i / etc / passwd, należy zastąpić poleceniem getent:for user in $(getent passwd | awk -F : '{print $1}'); do echo $user; crontab -u $user -l; done
Toby Batch,
9
Co o cronjobs w /etc/cron.hourly/, /etc/cron.daily/, /etc/cron.weekly/, /etc/cron.monthly/...?
Abdull,
309

Skończyło się na pisaniu scenariusza (staram się nauczyć najdokładniejszych aspektów pisania bashów, dlatego nie widzisz tutaj czegoś takiego jak Perl). To nie do końca prosty romans, ale robi większość tego, czego potrzebuję. Wykorzystuje sugestię Kyle'a dla patrząc crontaby indywidualnych użytkowników, ale również zajmuje się /etc/crontab(w tym skrypty uruchamiane przez run-partsw /etc/cron.hourly, /etc/cron.dailyitp) i pracy w /etc/cron.dkatalogu. Pobiera wszystkie z nich i łączy je w wyświetlacz podobny do następującego:

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

Pamiętaj, że pokazuje użytkownika i mniej więcej sortuje według godziny i minuty, dzięki czemu mogę zobaczyć dzienny harmonogram.

Do tej pory testowałem to na Ubuntu, Debian i 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
źródło
38
Nic, ale nie zrobiło nic z systemowymi zadaniami cron w / etc / crontab i /etc/cron.d/. Zajmowanie się nimi i formatowanie wszystkiego na końcu jest tym, co robi mój skrypt.
yukondude
10
yukondude - powinieneś rozważyć umieszczenie tego na githubie, nawet jako zwykłą istotę.
Kyle Burton,
3
Próbowałem skopiować wklej i uruchomić, ale to się nie udaje: showcrons.sh: linia 59: błąd składni w pobliżu nieoczekiwanego tokena <' showcrons.sh: line 59: wykonano <<(cut --fields = 1 --delimiter =: / etc / passwd) '
Fraggle
2
@KyleBurton Wydaje się, że co najmniej 8 osób już to kopiuje, gist.github.com/gists/…
Zitrax
9
Ostrzeżenie: w tym skrypcie brakuje zdarzeń z/etc/anacrontab
ck_
191

W systemie Ubuntu lub debian możesz wyświetlić crontab, /var/spool/cron/crontabs/a następnie plik dla każdego użytkownika. Oczywiście dotyczy to tylko crontab specyficznych dla użytkownika.

W przypadku Redhat 6/7 i Centos crontab jest poniżej /var/spool/cron/.

caot
źródło
7
Działa to również na RedHat (/ var / spool / cron) i jest łatwiejsze niż pisanie / uruchamianie skryptu, szczególnie jeśli używasz czegoś takiego jak Ldap do zarządzania kontami. +1
użytkownik49913
6
To było dla mnie o wiele bardziej pomocne niż jakakolwiek inna odpowiedź. Ta metoda pozwala ci zobaczyć crontabs użytkowników, którzy już nie istnieją, dając WSZYSTKIE zadania crona zgodnie z żądaniem PO.
Andrew Ensley,
1
Kolejna korzyść z tej metody: mój serwer używa LDAP, więc większość użytkowników nie ma dostępu /etc/passwd. IMO powinna to być zaakceptowana odpowiedź, a nie wszystkie brutalne rozwiązania.
Mikkel
1
Dobrze z Suse Linux tutaj.
Bret,
Dzięki, dotyczy to również instancji AWS EC2, ta informacja była bardzo pomocna!
Ivan Marjanovic
34

Spowoduje to wyświetlenie wszystkich wpisów crontab od wszystkich użytkowników.

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

Zależy od twojej wersji Linux, ale używam:

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

jako root. Bardzo prosty i bardzo krótki.

Daje mi dane wyjściowe takie jak:

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

==> /var/spool/cron/my_user <==
*/10 1 * * * /path/to/script
Jørgen
źródło
4
Służy tail -n +1 /var/spool/cron/*do wyświetlania całej zawartości plików.
Hans Ginzel
4
... lub sudo sh -c 'tail -n +1 /var/spool/cron/*'jeśli nie chcesz zostać rootem. Mój OCD zmusił mnie do zbadania, dlaczego nie mogłem sudo wykonać tego polecenia tak, jak napisano. Stało się tak, ponieważ zwykli użytkownicy nie mają dostępu do katalogu / var / spool / cron dir, a glob był interpretowany jako dosłowna postać gwiazdy, która oczywiście nie istnieje.
Dale Anderson,
alternatywnie cd /var/spool/cron/cron/ && grep . *wydrukuje również odpowiednią nazwę użytkownika przed każdym zadaniem crona
Jakub Kukul
15

Małe udoskonalenie odpowiedzi Kyle'a Burtona z ulepszonym formatowaniem wyjściowym:

#!/bin/bash
for user in $(cut -f1 -d: /etc/passwd)
do echo $user && crontab -u $user -l
echo " "
done
suma
źródło
Zobacz, dlaczego nie czytasz wierszy za pomocą „for” .
fedorqui „SO przestań szkodzić”
14
getent passwd | cut -d: -f1 | perl -e'while(<>){chomp;$l = `crontab -u $_ -l 2>/dev/null`;print "$_\n$l\n" if $l}'

Pozwala to uniknąć bałaganu bezpośrednio w passwd, pomija użytkowników, którzy nie mają wpisów cron, a dla tych, którzy je mają, wypisuje nazwę użytkownika oraz ich crontab.

Przeważnie upuszczam to tutaj, aby móc go później znaleźć na wypadek, gdyby kiedykolwiek musiałem go ponownie szukać.

Mithaldu
źródło
1
Zawiera także listę nieobecnych użytkowników LDAP /etc/passwd. Powyższe rozwiązanie Matta jest bardziej odpowiednie dla tej konkretnej sytuacji, ale dobrze jest wiedzieć, że polecenie istnieje.
Mikkel
11

Jeśli sprawdzasz klaster za pomocą NIS, jedynym sposobem sprawdzenia, czy użytkownik ma wpis crontab, jest odpowiedź Matta / var / spool / cron / tabs.

grep -v "#" -R  /var/spool/cron/tabs
Doris
źródło
11

Aby uzyskać listę od użytkownika ROOT.

for user in $(cut -f1 -d: /etc/passwd); do echo $user; sudo crontab -u $user -l; done
Szejk Abdul Wahid
źródło
10

Ten skrypt działał dla mnie w CentOS, aby wyświetlić listę wszystkich cronów w środowisku:

sudo cat /etc/passwd | sed 's/^\([^:]*\):.*$/sudo crontab -u \1 -l 2>\&1/' | grep -v "no crontab for" | sh
Sam T.
źródło
2
Niesamowite! Dodałem trochę wariacji, aby zobaczyć, który użytkownik wykonuje zadanie crona, i cat /etc/passwd | sed 's/^\([^:]*\):.*$/echo "\ncrontab for \1:"; sudo crontab -u \1 -l 2>\&1/' | grep -v "no crontab for" | sh
zostawić
9

Podoba mi się powyższa prosta linijka:

dla użytkownika w $ (cut -f1 -d: / etc / passwd); wykonaj crontab -u $ user -l; gotowy

Ale Solaris, który nie ma flagi -u i nie drukuje sprawdzanego użytkownika, możesz go zmodyfikować w następujący sposób:

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

Otrzymasz listę użytkowników bez błędów zgłaszanych przez crontab, gdy konto nie może używać crona itp. Pamiętaj, że w Solaris role mogą być również w / etc / passwd (patrz / etc / user_attr).

squarism
źródło
1
Zobacz, dlaczego nie czytasz wierszy za pomocą „for” .
fedorqui „SO przestań szkodzić”
Fajne. TIL nie należy używać.
squarism
8
for user in $(cut -f1 -d: /etc/passwd); 
do 
    echo $user; crontab -u $user -l; 
done
indra bhushan kumar
źródło
Zobacz, dlaczego nie czytasz wierszy za pomocą „for” . Również ta odpowiedź po prostu powtarza inne.
fedorqui „SO przestań szkodzić”
7

Poniżej usuwa komentarze, puste wiersze i błędy od użytkowników bez crontab. Pozostała Ci tylko jasna lista użytkowników i ich zadań.

Zwróć uwagę na użycie sudow 2. linii. Jeśli jesteś już rootem, usuń to.

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

Przykładowe dane wyjściowe:

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

Używam tego na Ubuntu (od 12 do 16) i Red Hat (od 5 do 7).

Dale Anderson
źródło
5

Zależy od twojej wersji crona. Używając Vixie cron na FreeBSD, mogę zrobić coś takiego:

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

jeśli chcę, aby bardziej ograniczać tabulację, mógłbym zrobić coś takiego:

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

Gdzie jest to dosłowna zakładka w części zamiennej sed.

Może być bardziej niezależny od systemu, aby przechodzić między użytkownikami /etc/passwdi robić to crontab -l -u $userdla każdego z nich.

Daniel Papasian
źródło
4

Dzięki za ten bardzo przydatny skrypt. Miałem kilka drobnych problemów z uruchomieniem go na starych systemach (Red Hat Enterprise 3, które inaczej obsługują egrep i tabulacje w łańcuchach), i innych systemach bez niczego w /etc/cron.d/ (skrypt zakończył się błędem). Oto łatka, aby działała w takich przypadkach:

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

Nie jestem pewien, czy zmiany w pierwszym egrep są dobrym pomysłem, ale cóż, ten skrypt został przetestowany na RHEL3,4,5 i Debian5 bez żadnego problemu. Mam nadzieję że to pomoże!

jbbarth
źródło
3

Opierając się na @Kyle

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

aby uniknąć komentarzy zwykle na górze / etc / passwd,

I na macosx

for user in $(dscl . -list /users | cut -f1 -d:); do echo $user; crontab -u $user -l; done    
Ali
źródło
3
Czy nie powinieneś grep -v '^#„polegać na magicznej liczbie 11?
rr-
1
Dystrybutorzy Red Hat / CentOS nie piszą przydatnych wskazówek na początku crontab użytkownika, więc odcięcie pierwszych 11 wierszy zatrze jego zawartość. To samo, jeśli użytkownik Ubuntu dokonał edycji własnego crontabu i usunął cały uchwyt.
Dale Anderson,
Zobacz, dlaczego nie czytasz wierszy za pomocą „for” .
fedorqui „SO przestań krzywdzić”
3

Myślę, że lepsza jedna linijka byłaby poniżej. Na przykład, jeśli masz użytkowników w NIS lub LDAP, nie byliby w / etc / passwd. To da ci crontabs każdego zalogowanego użytkownika.

for I in `lastlog | grep -v Never | cut -f1 -d' '`; do echo $I ; crontab -l -u $I ; done
Monte
źródło
Zobacz, dlaczego nie czytasz wierszy za pomocą „for” .
fedorqui „SO przestań krzywdzić”
3

możesz napisać dla wszystkich list użytkowników:

sudo crontab -u userName -l

,

Możesz także przejść do

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

ten plik zawiera listę harmonogramów

cd /etc/cron.d/
ls -l
cat filename
rkoots
źródło
3

Z przeprosinami i podziękowaniami dla yukondude.

Próbowałem podsumować ustawienia czasu dla łatwego czytania, chociaż nie jest to idealna praca i nie dotykam „każdego piątku” ani „tylko w poniedziałki”.

To jest wersja 10 - teraz:

  • działa znacznie szybciej
  • ma opcjonalne postacie postępu, dzięki czemu można jeszcze bardziej zwiększyć prędkość.
  • używa linii podziału do oddzielenia nagłówka i wyjścia.
  • wyprowadza dane w zwartym formacie, gdy można podsumować wszystkie niezliczone przedziały czasowe.
  • Akceptuje Jan ... Dec deskryptory na miesiące roku
  • Akceptuje Pon ... Deskryptory Sun na dni tygodnia
  • próbuje obsłużyć anakron w stylu Debiana, gdy go brakuje
  • próbuje poradzić sobie z liniami crontab, które uruchamiają plik po wstępnym przetestowaniu wykonywalności za pomocą „[-x ...]”
  • próbuje poradzić sobie z liniami crontab, które uruchamiają plik po wstępnym przetestowaniu wykonywalności za pomocą polecenia „-v”
  • pozwala na użycie przedziałów interwałów i list.
  • obsługuje użycie części roboczych w specyficznych dla użytkownika plikach / var / spool crontab.

Teraz w pełni publikuję skrypt.

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

David Collier
źródło
2

Ponieważ chodzi o zapętlanie pliku ( /etc/passwd) i wykonanie akcji, brakuje mi odpowiedniego podejścia do tego, jak mogę odczytać plik (strumień danych, zmienną) wiersz po wierszu (i / lub pole po polu) )? :

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

Odczytuje /etc/passwdwiersz po wierszu za pomocą :ogranicznika pola. Mówiąc read -r user _, $userwstrzymujemy pierwsze pole i _resztę (jest to tylko śmieciowa zmienna, aby zignorować pola).

W ten sposób możemy wywołać crontab -uzmienną $user, którą podajemy ze względów bezpieczeństwa (co jeśli zawiera spacje? Jest mało prawdopodobne w takim pliku, ale nigdy nie wiadomo).

fedorqui „SO przestań szkodzić”
źródło
1

W systemie Solaris dla konkretnej znanej nazwy użytkownika:

crontab -l username

Wszystkie pozostałe * Nix będą wymagały -umodyfikatora:

crontab -u username -l

Aby uzyskać wszystkie zadania użytkownika jednocześnie w systemie Solaris, podobnie jak inne posty powyżej:

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

Dla mnie spojrzenie na / var / spool / cron / crontabs jest najlepszym sposobem

Nic0
źródło
2
to zostało udzielone wcześniej
bummi
-2

Ten skrypt wysyła Crontab do pliku, a także wyświetla listę wszystkich użytkowników potwierdzających tych, którzy nie mają wpisu 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
źródło
//, RobFrost, czy jesteś pewien, że ten skrypt, tak jak tutaj napisany, konsekwentnie działa?
Nathan Basanese
Zobacz, dlaczego nie czytasz wierszy za pomocą „for” . Odpowiedzi udzielono także wiele razy przed opublikowaniem tego.
fedorqui „SO przestań krzywdzić”