web-dev-qa-db-fra.com

Comment répertorier tous les travaux cron pour tous les utilisateurs?

Existe-t-il une commande ou un script existant qui me permette de visualiser simultanément tous les travaux périodiques planifiés d'un système * NIX? Je voudrais qu'il inclue toutes les crontabs utilisateur, ainsi que /etc/crontab et tout ce qui se trouve dans /etc/cron.d. Il serait également agréable de voir les commandes spécifiques exécutées par run-parts dans /etc/crontab.

Idéalement, j'aimerais que la sortie soit sous forme de colonne Nice et ordonnée de manière significative.

Je pourrais ensuite fusionner ces listes de plusieurs serveurs pour afficher le "calendrier des événements".

J'étais sur le point d'écrire moi-même un tel scénario, mais si quelqu'un est déjà pris au piège ...

805
yukondude

J'ai fini par écrire un script (j'essaie de m'apprendre les détails du script bash, c'est pourquoi vous ne voyez pas quelque chose comme Perl ici). Ce n’est pas une affaire simple, mais c’est ce qu’il me faut. Il utilise la suggestion de Kyle pour rechercher les crontabs des utilisateurs individuels, mais traite également de /etc/crontab (y compris les scripts lancés par run-parts dans /etc/cron.hourly, /etc/cron.daily, etc.) et du emplois dans le répertoire /etc/cron.d. Il prend tout cela et les fusionne dans un affichage du type suivant:

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

Notez que cela montre l'utilisateur, et plus ou moins trie par heure et par minute afin que je puisse voir l'horaire quotidien.

Jusqu'à présent, je l'ai testé sous Ubuntu, Debian et 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}"
301
yukondude

Vous devriez l'exécuter en tant que root, mais:

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

passera en boucle sur chaque nom d'utilisateur listant leur crontab. Les crontabs sont la propriété des utilisateurs respectifs, vous ne pourrez donc pas voir la crontab d'un autre utilisateur sans lui ni racine.


Edit Si vous voulez savoir à quel utilisateur appartient une crontab, utilisez echo $user

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

Sous Ubuntu ou Debian, vous pouvez afficher crontab sous /var/spool/cron/crontabs/ puis vous trouverez un fichier pour chaque utilisateur. Cela concerne uniquement les crontab spécifiques à l'utilisateur.

Pour Redhat 6/7 et Centos, la crontab est sous /var/spool/cron/.

174
Matt

Cela affichera toutes les entrées crontab de tous les utilisateurs.

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

Cela dépend de votre version de Linux mais j'utilise:

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

en tant que racine. Très simple et très court.

Me donne la sortie comme:

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

==> /var/spool/cron/my_user <==
*/10 1 * * * /path/to/script
28
Jørgen

Un petit raffinement de la réponse de Kyle Burton avec un formatage de sortie amélioré:

#!/bin/bash
for user in $(cut -f1 -d: /etc/passwd)
do echo $user && crontab -u $user -l
echo " "
done
14
sum
getent passwd | cut -d: -f1 | Perl -e'while(<>){chomp;$l = `crontab -u $_ -l 2>/dev/null`;print "$_\n$l\n" if $l}'

Cela évite de jouer avec passwd directement, ignore les utilisateurs qui n'ont pas d'entrées cron et pour ceux qui les ont, il affiche le nom d'utilisateur ainsi que leur crontab.

Généralement, je laisse tomber ceci ici pour que je puisse le trouver plus tard au cas où je devrais un jour le chercher à nouveau.

13
Mithaldu

Si vous vérifiez un cluster à l'aide de NIS, le seul moyen de savoir si un utilisateur a une entrée crontab est conforme à la réponse de Matt/var/spool/cron/tabs.

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

Ce script a fonctionné pour moi dans CentOS pour lister tous les crons de l'environnement:

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

J'aime la réponse simple en une ligne ci-dessus:

pour l'utilisateur dans $ (cut -f1 -d:/etc/passwd); do crontab -u $ user -l; terminé

Mais Solaris qui n’a pas l’indicateur -u et n’imprime pas l’utilisateur qu’elle vérifie, vous pouvez le modifier comme suit:

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

Vous obtiendrez une liste d'utilisateurs sans les erreurs renvoyées par crontab lorsqu'un compte n'est pas autorisé à utiliser cron, etc. Sachez que sous Solaris, les rôles peuvent également figurer dans/etc/passwd (voir/etc/user_attr).

8
squarism
for user in $(cut -f1 -d: /etc/passwd); 
do 
    echo $user; crontab -u $user -l; 
done
7
indra bhushan kumar

Pour obtenir la liste de l'utilisateur ROOT.

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

Les éléments suivants suppriment les commentaires, les lignes vides et les erreurs d'utilisateurs sans crontab. Tout ce qui vous reste, c'est une liste claire des utilisateurs et de leurs tâches.

Notez l'utilisation de Sudo sur la 2ème ligne. Si vous êtes déjà root, supprimez-le.

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

Exemple de sortie:

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

J'utilise ceci sur Ubuntu (12 à 16) et Red Hat (5 à 7).

5
Dale Anderson

Cela dépend de votre version de cron. En utilisant Vixie cron sur FreeBSD, je peux faire quelque chose comme ceci:

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

si je le veux plus tabulé, je pourrais faire quelque chose comme ceci:

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

Où c'est un onglet littéral dans la partie de remplacement sed.

Il peut être plus indépendant du système de parcourir en boucle les utilisateurs de /etc/passwd et de faire crontab -l -u $user pour chacun d’eux.

4
Daniel Papasian

Merci pour ce script très utile. J'ai eu quelques petits problèmes à l'exécuter sur d'anciens systèmes (Red Hat Enterprise 3, qui traitent différemment les paramètres egrep et tab dans les chaînes) et d'autres systèmes sans rien dans /etc/cron.d/ (le script s'est ensuite terminé avec une erreur). Voici donc un correctif pour le faire fonctionner dans de tels cas:

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

Je ne suis pas vraiment sûr que les changements dans le premier egrep soient une bonne idée, mais bon, ce script a été testé sur RHEL3,4,5 et Debian5 sans aucun problème. J'espère que cela t'aides!

3
jbbarth

vous pouvez écrire pour toutes les listes d'utilisateurs:

Sudo crontab -u userName -l

,

Vous pouvez aussi aller à

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

ce fichier listera les horaires

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

Construire au sommet de @Kyle

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

pour éviter les commentaires qui se trouvent généralement en haut de/etc/passwd,

Et sur macosx

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

Avec mes excuses et merci à yukondude.

J'ai essayé de résumer les paramètres de chronométrage pour faciliter la lecture, bien que ce ne soit pas un travail parfait et que je ne touche pas aux trucs "tous les vendredis" ou "le lundi uniquement".

Ceci est la version 10 - maintenant:

  • court beaucoup plus vite
  • a des caractères de progression facultatifs afin que vous puissiez améliorer encore la vitesse.
  • utilise une ligne de séparation pour séparer l’en-tête et la sortie.
  • sorties dans un format compact lorsque tous les intervalles de temps rencontrés peuvent être résumés.
  • Accepte les descripteurs de décembre ... pour les mois de l'année
  • Accepte Mon ... Descripteurs du soleil pour les jours de la semaine
  • essaie de gérer le dummying-up d'Anacron quand il manque
  • essaie de traiter les lignes de crontab qui exécutent un fichier après le test préalable de l'exécutabilité à l'aide de "[-x ...]"
  • essaie de gérer les lignes crontab qui exécutent un fichier après le test préalable de l'exécutabilité en utilisant "commande -v"
  • permet l'utilisation d'intervalles et de listes d'intervalles.
  • prend en charge l'utilisation des composants d'exécution dans les fichiers crontab/var/spool spécifiques à l'utilisateur.

Je publie maintenant le script dans son intégralité ici.

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

2
david collier

Je pense qu'une meilleure ligne serait en dessous. Par exemple, si vous avez des utilisateurs dans NIS ou LDAP, ils ne seraient pas dans/etc/passwd. Cela vous donnera les crontabs de chaque utilisateur connecté.

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

Puisqu'il s'agit de boucler un fichier (/etc/passwd) et d'effectuer une action, il me manque l'approche appropriée sur Comment puis-je lire un fichier (flux de données, variable) ligne par ligne (et/ou champ par champ)? :

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

Ceci lit /etc/passwd ligne par ligne en utilisant : comme délimiteur de champ. En disant read -r user _, nous obligeons $user à conserver le premier champ et _ le reste (il ne s'agit que d'une variable indésirable pour ignorer les champs).

De cette façon, nous pouvons ensuite appeler crontab -u en utilisant la variable $user, que nous citons pour la sécurité (que faire si elle contient des espaces? Il est peu probable dans un tel fichier, mais vous ne pouvez jamais le savoir).

1
fedorqui

Sous Solaris, pour un nom d'utilisateur connu particulier:

crontab -l username

Tous les autres * Nix auront besoin du modificateur -u:

crontab -u username -l

Pour obtenir les tâches de tous les utilisateurs simultanément sur Solaris, comme dans les autres publications ci-dessus:

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