¿Cómo enumero todos los trabajos cron para todos los usuarios?

858

¿Hay un comando o un script existente que me permita ver todos los trabajos cron programados de un sistema * NIX a la vez? Me gustaría que incluyera todos los crontabs de usuario, así como /etc/crontab, y lo que sea que haya /etc/cron.d. También sería bueno ver los comandos específicos ejecutados run-partsen /etc/crontab.

Idealmente, me gustaría la salida en una buena columna y ordenada de alguna manera significativa.

Luego podría fusionar estos listados de múltiples servidores para ver el "cronograma de eventos" general.

Estaba a punto de escribir ese guión yo mismo, pero si alguien ya se ha tomado la molestia ...

yukondude
fuente
2
Pregunta similar sobre Unix SE: unix.stackexchange.com/questions/7053/…
maxschlepzig

Respuestas:

1135

Tendría que ejecutar esto como root, pero:

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

recorrerá cada nombre de usuario con su crontab. Los crontabs son propiedad de los respectivos usuarios, por lo que no podrá ver el crontab de otro usuario sin ser ellos o root.


Edite si desea saber a qué usuario pertenece un crontab, useecho $user

for user in $(cut -f1 -d: /etc/passwd); do echo $user; crontab -u $user -l; done
Kyle Burton
fuente
54
No funciona cuando los usuarios están definidos en NIS o LDAP. Necesitas usarfor user in $(getent passwd | cut -f1 -d: ); do echo $user; crontab -u $user -l; done
Hubert Kario
10
Actualizado esto excluye los comentarios y suprimir 'no crontab para el usuario ...' mensajes:for user in $(cut -f1 -d: /etc/passwd); do crontab -u $user -l 2>/dev/null | grep -v '^#'; done
Jonathan
38
¿No sería más fácil mirar los archivos en / var / spool / cron?
graywh
2
Nosotros, LDAP y / etc / passwd necesitamos ser reemplazados con el comando getent:for user in $(getent passwd | awk -F : '{print $1}'); do echo $user; crontab -u $user -l; done
Toby Batch
99
¿Qué pasa con los cronjobs en /etc/cron.hourly/, /etc/cron.daily/, /etc/cron.weekly/, /etc/cron.monthly/...?
Abdull
309

Terminé escribiendo un guión (estoy tratando de enseñarme a mí mismo los puntos más finos de las secuencias de comandos bash, así que por eso no ves algo como Perl aquí). No es exactamente un asunto simple, pero hace la mayor parte de lo que necesito. Utiliza la sugerencia de Kyle para buscar crontabs de los usuarios individuales, sino que también se ocupa de /etc/crontab(incluyendo las secuencias de comandos lanzados por run-partsen /etc/cron.hourly, /etc/cron.daily, etc.) y los puestos de trabajo en el /etc/cron.ddirectorio. Toma todos esos y los fusiona en una pantalla similar a la siguiente:

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

Tenga en cuenta que muestra al usuario, y más o menos ordena por hora y minuto para que pueda ver la programación diaria.

Hasta ahora, lo he probado en Ubuntu, Debian y 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
fuente
38
Nada, pero no hizo nada sobre los trabajos cron del sistema en / etc / crontab y /etc/cron.d/. Tratar con eso y formatear todo al final es lo que hace mi script.
yukondude
10
yukondude: deberías considerar poner esto en github, incluso solo como una esencia.
Kyle Burton el
3
Intenté copiar y pegar y ejecutarlo, pero falla: showcrons.sh: línea 59: error de sintaxis cerca del token inesperado <' showcrons.sh: line 59: hecho <<(cut --fields = 1 --delimiter =: / etc / passwd) '
Fraggle
2
@KyleBurton Parece que al menos 8 gists ya están copiando esto, gist.github.com/gists/…
Zitrax
99
Advertencia: a este script le faltan eventos de/etc/anacrontab
ck_
191

En Ubuntu o Debian, puede ver crontab por /var/spool/cron/crontabs/ y luego hay un archivo para cada usuario. Eso es solo para crontab específicos del usuario, por supuesto.

Para Redhat 6/7 y Centos, el crontab está debajo /var/spool/cron/.

caotín
fuente
77
Esto también funciona en RedHat (/ var / spool / cron) y es más fácil que escribir / ejecutar un script, especialmente si está utilizando algo como Ldap para administrar cuentas. +1
user49913 el
66
Esto fue mucho más útil para mí que cualquiera de las otras respuestas. Este método le permite ver los crontabs de los usuarios que ya no existen, proporcionándole TODOS los trabajos cron según lo solicite el OP.
Andrew Ensley
1
Otro beneficio de este método: mi servidor usa LDAP, por lo que la mayoría de los usuarios no están /etc/passwd. En mi opinión, esta debería ser la respuesta aceptada, en lugar de todas las soluciones de fuerza bruta.
Mikkel
1
Bien con Suse Linux aquí.
Bret
Gracias, esto también es cierto para la instancia de AWS EC2, ¡esta información fue muy útil!
Ivan Marjanovic
34

Esto mostrará todas las entradas de crontab de todos los usuarios.

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

Depende de tu versión de Linux pero yo uso:

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

como raíz Muy simple y muy corto.

Me da salida como:

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

==> /var/spool/cron/my_user <==
*/10 1 * * * /path/to/script
Jørgen
fuente
44
Use tail -n +1 /var/spool/cron/*para enumerar todo el contenido de los archivos.
Hans Ginzel
44
... o sudo sh -c 'tail -n +1 /var/spool/cron/*'si no quieres convertirte en root. Mi TOC me obligó a investigar por qué no podía sudo este comando tal como está escrito. Fue porque los usuarios habituales no tienen acceso al directorio / var / spool / cron, y el glob se estaba interpretando como un personaje estrella literal, que obviamente no existe.
Dale Anderson
alternativamente, cd /var/spool/cron/cron/ && grep . *también imprimirá el nombre de usuario correspondiente delante de cada trabajo cron
Jakub Kukul
15

Un pequeño refinamiento de la respuesta de Kyle Burton con un formato de salida mejorado:

#!/bin/bash
for user in $(cut -f1 -d: /etc/passwd)
do echo $user && crontab -u $user -l
echo " "
done
suma
fuente
Vea Por qué no lee líneas con "para" .
fedorqui 'así que deja de dañar' el
14
getent passwd | cut -d: -f1 | perl -e'while(<>){chomp;$l = `crontab -u $_ -l 2>/dev/null`;print "$_\n$l\n" if $l}'

Esto evita meterse con passwd directamente, omite a los usuarios que no tienen entradas cron y para aquellos que las tienen, imprime el nombre de usuario y su crontab.

Sin embargo, la mayoría de las veces dejo esto aquí para poder encontrarlo más tarde en caso de que necesite volver a buscarlo.

Mithaldu
fuente
1
También enumera los usuarios de LDAP que no están presentes en /etc/passwd. La solución anterior de Matt es más apropiada para esta situación particular, pero es bueno saber que existe el comando.
Mikkel
11

Si marca un clúster utilizando NIS, la única forma de ver si un usuario tiene una entrada crontab es según la respuesta de Matt / var / spool / cron / tabs.

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

Para obtener la lista del usuario ROOT.

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

Este script funcionó para mí en CentOS para enumerar todos los crons en el entorno:

sudo cat /etc/passwd | sed 's/^\([^:]*\):.*$/sudo crontab -u \1 -l 2>\&1/' | grep -v "no crontab for" | sh
Sam T
fuente
2
¡Increíble! Agregué una pequeña variación para ver en qué usuario se encuentra el trabajo cron y poner algo de espacio entre los resultados: cat /etc/passwd | sed 's/^\([^:]*\):.*$/echo "\ncrontab for \1:"; sudo crontab -u \1 -l 2>\&1/' | grep -v "no crontab for" | shahorra un poco de tiempo
jamil
9

Me gusta la respuesta simple de una sola línea de arriba:

para el usuario en $ (cut -f1 -d: / etc / passwd); do crontab -u $ usuario -l; hecho

Pero Solaris, que no tiene el indicador -u y no imprime al usuario que está comprobando, puede modificarlo así:

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

Obtendrá una lista de usuarios sin los errores arrojados por crontab cuando una cuenta no puede usar cron, etc. Tenga en cuenta que en Solaris, los roles también pueden estar en / etc / passwd (consulte / etc / user_attr).

escuadrón
fuente
1
Vea Por qué no lee líneas con "para" .
fedorqui 'así que deja de dañar' el
Frio. TIL para no usar.
Squarism
8
for user in $(cut -f1 -d: /etc/passwd); 
do 
    echo $user; crontab -u $user -l; 
done
indra bhushan kumar
fuente
Vea Por qué no lee líneas con "para" . Además, esta respuesta es solo repetir otras.
fedorqui 'así que deja de dañar' el
7

Lo siguiente elimina los comentarios, las líneas vacías y los errores de los usuarios sin crontab. Todo lo que le queda es una lista clara de usuarios y sus trabajos.

Tenga en cuenta el uso de sudoen la segunda línea. Si ya eres root, elimina eso.

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

Salida de ejemplo:

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

Lo uso en Ubuntu (12 a 16) y Red Hat (5 a 7).

Dale Anderson
fuente
5

Depende de tu versión de cron. Usando Vixie cron en FreeBSD, puedo hacer algo como esto:

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

si lo quiero más delimitado por tabulaciones, podría hacer algo como esto:

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

Donde esa es una pestaña literal en la porción de reemplazo de sed.

Puede ser más independiente del sistema recorrer a los usuarios /etc/passwdy hacer crontab -l -u $userpor cada uno de ellos.

Daniel Papasian
fuente
4

Gracias por este script muy útil. Tuve algunos pequeños problemas al ejecutarlo en sistemas antiguos (Red Hat Enterprise 3, que manejan de manera diferente egrep y pestañas en cadenas), y otros sistemas sin nada en /etc/cron.d/ (el script terminó con un error). Así que aquí hay un parche para que funcione en tales casos:

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

No estoy realmente seguro de que los cambios en el primer egrep sean una buena idea, pero bueno, este script ha sido probado en RHEL3,4,5 y Debian5 sin ningún problema. ¡Espero que esto ayude!

jbbarth
fuente
3

Construyendo sobre @Kyle

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

para evitar los comentarios generalmente en la parte superior de / etc / passwd,

Y en macosx

for user in $(dscl . -list /users | cut -f1 -d:); do echo $user; crontab -u $user -l; done    
Ali
fuente
3
¿No deberías grep -v '^#'en lugar de confiar en el número mágico 11?
rr-
1
Las distribuciones de Red Hat / CentOS no escriben las sugerencias útiles al comienzo del crontab de un usuario, por lo que cortar las primeras 11 líneas borrará el contenido de la misma. Lo mismo si un usuario de Ubuntu ha editado su propio crontab y eliminado toda la mano.
Dale Anderson
Vea Por qué no lee líneas con "para" .
fedorqui 'así que deja de dañar' el
3

Creo que un mejor revestimiento estaría debajo. Por ejemplo, si tiene usuarios en NIS o LDAP, no estarán en / etc / passwd. Esto le dará los crontabs de cada usuario que haya iniciado sesión.

for I in `lastlog | grep -v Never | cut -f1 -d' '`; do echo $I ; crontab -l -u $I ; done
Monte
fuente
Vea Por qué no lee líneas con "para" .
fedorqui 'así que deja de dañar' el
3

Puedes escribir para toda la lista de usuarios:

sudo crontab -u userName -l

,

También puedes ir a

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

este archivo listará los horarios

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

Con disculpas y gracias a yukondude.

Traté de resumir la configuración de tiempo para una lectura fácil, aunque no es un trabajo perfecto, y no toco 'todos los viernes' o 'solo los lunes'.

Esta es la versión 10, ahora:

  • corre mucho más rápido
  • tiene caracteres de progreso opcionales para que pueda mejorar aún más la velocidad.
  • usa una línea divisoria para separar el encabezado y la salida.
  • salidas en un formato compacto cuando se pueden resumir todos los intervalos de temporización no encontrados.
  • Acepta descriptores de enero ... diciembre para los meses del año
  • Acepta lunes ... Descriptores de sol para los días de la semana
  • trata de manejar el dummying de Anacron cuando falta
  • intenta lidiar con las líneas crontab que ejecutan un archivo después de probar previamente la ejecubilidad usando "[-x ...]"
  • intenta lidiar con las líneas crontab que ejecutan un archivo después de probar previamente la ejecubilidad usando "command -v"
  • permite el uso de intervalos de intervalos y listas.
  • admite el uso de partes de ejecución en archivos crontab / var / spool específicos del usuario.

Ahora estoy publicando el guión completo aquí.

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

David Collier
fuente
2

Como se trata de recorrer un archivo ( /etc/passwd) y realizar una acción, me falta el enfoque adecuado sobre ¿Cómo puedo leer un archivo (flujo de datos, variable) línea por línea (y / o campo por campo)? )? :

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

Esto lee /etc/passwdlínea por línea usando :como delimitador de campo. Al decir read -r user _, hacemos $userretener el primer campo y_ el resto (es solo una variable basura para ignorar los campos).

De esta manera, podemos llamar crontab -uusando la variable $user, que citamos por seguridad (¿qué pasa si contiene espacios? Es poco probable en dicho archivo, pero nunca se puede saber).

fedorqui 'así que deja de dañar'
fuente
1

En Solaris, para un nombre de usuario conocido particular:

crontab -l username

Todos los demás * Nix necesitarán un -umodificador:

crontab -u username -l

Para obtener todos los trabajos de los usuarios a la vez en Solaris, al igual que otras publicaciones anteriores:

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

Para mí, mirar / var / spool / cron / crontabs es la mejor manera

Nic0
fuente
2
esto ha sido respondido antes
bummi
-2

Este script genera el Crontab en un archivo y también enumera todos los usuarios que confirman aquellos que no tienen una entrada 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
fuente
//, RobFrost, ¿estás seguro de que este script, como está escrito aquí, funciona de manera consistente?
Nathan Basanese
Vea Por qué no lee líneas con "para" . Además, esto ha sido respondido muchas veces antes de publicar este.
fedorqui 'así que deja de dañar' el