Como listar todos os trabalhos cron para todos os usuários?

858

Existe um comando ou um script existente que permita visualizar todos os trabalhos agendados do sistema * NIX de uma só vez? Gostaria que ele incluísse todos os crontabs do usuário, bem como o que /etc/crontabquer que esteja /etc/cron.d. Também seria bom ver os comandos específicos executados run-partsem /etc/crontab.

Idealmente, eu gostaria da saída em uma boa forma de coluna e ordenada de alguma maneira significativa.

Eu poderia então mesclar essas listagens de vários servidores para visualizar a "agenda de eventos" geral.

Eu estava prestes a escrever um roteiro assim, mas se alguém já se deu ao trabalho ...

yukondude
fonte
2
Pergunta semelhante no Unix SE: unix.stackexchange.com/questions/7053/…
maxschlepzig

Respostas:

1135

Você precisaria executar isso como root, mas:

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

fará um loop sobre cada nome de usuário listando seu crontab. Os crontabs são de propriedade dos respectivos usuários, portanto você não poderá ver o crontab de outro usuário sem eles ou com raiz.


Edite se quiser saber a qual usuário um crontab pertence, useecho $user

for user in $(cut -f1 -d: /etc/passwd); do echo $user; crontab -u $user -l; done
Kyle Burton
fonte
54
Não funciona quando os usuários são definidos no NIS ou LDAP. Você precisa usarfor user in $(getent passwd | cut -f1 -d: ); do echo $user; crontab -u $user -l; done
Hubert Kario
10
Atualizado para excluir comentários e suprimir mensagens 'no crontab for user ...':for user in $(cut -f1 -d: /etc/passwd); do crontab -u $user -l 2>/dev/null | grep -v '^#'; done
Jonathan
38
Não seria mais fácil olhar para os arquivos em / var / spool / cron?
graywh
2
Nós, LDAP e / etc / passwd, precisamos ser substituídos pelo comando getent:for user in $(getent passwd | awk -F : '{print $1}'); do echo $user; crontab -u $user -l; done
Toby Batch
9
E sobre as cronjobs em /etc/cron.hourly/, /etc/cron.daily/, /etc/cron.weekly/, /etc/cron.monthly/...?
Abdull
309

Acabei escrevendo um script (estou tentando me ensinar os pontos mais sutis do script bash, é por isso que você não vê algo como Perl aqui). Não é exatamente um caso simples, mas faz a maior parte do que eu preciso. Ele usa a sugestão de Kyle para procurar crontabs de usuários individuais, mas também lida com /etc/crontab(incluindo os scripts lançados por run-partsem /etc/cron.hourly, /etc/cron.dailyetc.) e os postos de trabalho no /etc/cron.ddiretório. Ele pega todos eles e os mescla em uma exibição, algo como o seguinte:

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

Observe que ele mostra o usuário e classifica mais ou menos por hora e minuto, para que eu possa ver a programação diária.

Até agora, eu testei no Ubuntu, Debian e 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
fonte
38
Nada, mas não fez nada sobre os trabalhos do cron do sistema em / etc / crontab e /etc/cron.d/. Lidar com eles e formatar tudo no final é o que meu script faz.
yukondude 26/09/08
10
yukondude - você deve considerar colocar isso no github, mesmo como uma essência.
Kyle Burton
3
Tentei copiar e colar e executá-lo, mas falhou: showcrons.sh: linha 59: erro de sintaxe próximo ao token inesperado <' showcrons.sh: line 59: feito <<(cut --fields = 1 --delimiter =: / etc / passwd) '
Fraggle
2
@KyleBurton Parece que há pelo menos 8 GIST já copiando isso, gist.github.com/gists/...
Zitrax
9
Aviso: faltam eventos neste script de/etc/anacrontab
ck_
191

No Ubuntu ou debian, você pode visualizar o crontab /var/spool/cron/crontabs/e, em seguida, um arquivo para cada usuário. Isso é apenas para crontabs específicos do usuário, é claro.

Para Redhat 6/7 e Centos, o crontab está abaixo /var/spool/cron/.

caot
fonte
7
Isso funciona também no RedHat (/ var / spool / cron) e é mais fácil do que escrever / executar um script, especialmente se você estiver usando algo como o Ldap para gerenciar contas. 1
user49913 4/11/2009
6
Isso foi muito mais útil para mim do que qualquer outra resposta. Esse método permite visualizar as crontabs de usuários que não existem mais, fornecendo TODAS as tarefas agendadas conforme solicitado pelo OP.
Andrew Ensley
1
Outro benefício desse método: meu servidor usa LDAP, para que a maioria dos usuários não esteja /etc/passwd. Na IMO, essa deve ser a resposta aceita, e não todas as soluções de força bruta.
Mikkel
1
Bom com o Suse Linux aqui.
187 de Bret
Thx, isso também é verdade para a instalação do AWS EC2, essas informações foram muito úteis!
Ivan Marjanovic
34

Isso mostrará todas as entradas do crontab de todos os usuários.

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

Depende da sua versão Linux, mas eu uso:

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

como raiz. Muito simples e muito curto.

Dá-me saída como:

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

==> /var/spool/cron/my_user <==
*/10 1 * * * /path/to/script
Jørgen
fonte
4
Use tail -n +1 /var/spool/cron/*para listar todo o conteúdo dos arquivos.
Hans Ginzel 27/05
4
... ou sudo sh -c 'tail -n +1 /var/spool/cron/*'se você não quiser se tornar root. Meu TOC me obrigou a investigar por que não consegui executar esse comando como está escrito. Isso porque os usuários comuns não têm acesso a / var / spool / cron dir e a glob estava sendo interpretada como um caractere estrela literal, o que obviamente não existe.
Dale Anderson
Alternativamente, cd /var/spool/cron/cron/ && grep . *também irá imprimir o nome de usuário correspondente na frente de cada trabalho cron
Jakub Kukul
15

Um pequeno refinamento da resposta de Kyle Burton com melhor formatação de saída:

#!/bin/bash
for user in $(cut -f1 -d: /etc/passwd)
do echo $user && crontab -u $user -l
echo " "
done
soma
fonte
Consulte Por que você não lê linhas com "for" .
fedorqui 'Então, pare de prejudicar'
14
getent passwd | cut -d: -f1 | perl -e'while(<>){chomp;$l = `crontab -u $_ -l 2>/dev/null`;print "$_\n$l\n" if $l}'

Isso evita mexer diretamente com o passwd, ignora os usuários que não possuem entradas cron e, para os que os possuem, imprime o nome de usuário e seu crontab.

Principalmente largando isso aqui, para que eu possa encontrá-lo mais tarde, caso eu precise procurá-lo novamente.

Mithaldu
fonte
1
Ele também lista os usuários LDAP não presentes no /etc/passwd. A solução de Matt acima é mais apropriada para essa situação específica, mas é bom saber que o comando existe.
Mikkel
11

Se você verificar um cluster usando o NIS, a única maneira de verificar se um usuário tem uma entrada no crontab é de acordo com as respostas / var / spool / cron / tab de Matt.

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

Para obter a lista do usuário ROOT.

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

Este script funcionou para mim no CentOS para listar todos os crons no ambiente:

sudo cat /etc/passwd | sed 's/^\([^:]*\):.*$/sudo crontab -u \1 -l 2>\&1/' | grep -v "no crontab for" | sh
Sam T
fonte
2
Impressionante! Eu adicionei uma pequena variação para ver qual usuário o trabalho cron está sob e colocar algum espaço entre resultados: cat /etc/passwd | sed 's/^\([^:]*\):.*$/echo "\ncrontab for \1:"; sudo crontab -u \1 -l 2>\&1/' | grep -v "no crontab for" | shsalva um pouco de tempo
Jamil
9

Gosto da resposta simples de uma linha acima:

para usuário em $ (cut -f1 -d: / etc / passwd); faça crontab -u $ user -l; feito

Mas o Solaris que não possui o sinalizador -u e não imprime o usuário que está verificando, é possível modificá-lo da seguinte forma:

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

Você obterá uma lista de usuários sem os erros gerados pelo crontab quando uma conta não tiver permissão para usar o cron etc. Esteja ciente de que no Solaris, as funções também podem estar no / etc / passwd (consulte / etc / user_attr).

esquarismo
fonte
1
Consulte Por que você não lê linhas com "for" .
fedorqui 'Então, pare de prejudicar'
Legal. ATÉ NÃO USAR.
squarism
8
for user in $(cut -f1 -d: /etc/passwd); 
do 
    echo $user; crontab -u $user -l; 
done
indra bhushan kumar
fonte
Consulte Por que você não lê linhas com "for" . Além disso, esta resposta está apenas repetindo outras.
fedorqui 'Então, pare de prejudicar'
7

A seguir, os comentários, as linhas vazias e os erros são removidos dos usuários sem crontab. Tudo o que resta é uma lista clara de usuários e seus trabalhos.

Observe o uso de sudona 2ª linha. Se você já é root, remova-o.

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

Exemplo de saída:

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

Eu uso isso no Ubuntu (12 a 16) e Red Hat (5 a 7).

Dale Anderson
fonte
5

Depende da sua versão do cron. Usando o Vixie cron no FreeBSD, posso fazer algo assim:

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

se eu quiser que ele seja mais delimitado por tabulação, posso fazer algo assim:

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

Onde essa é uma guia literal na parte de substituição sed.

Pode ser mais independente do sistema fazer um loop entre os usuários /etc/passwde fazer crontab -l -u $userpor cada um deles.

Daniel Papasian
fonte
4

Obrigado por este script muito útil. Eu tive alguns pequenos problemas ao executá-lo em sistemas antigos (Red Hat Enterprise 3, que manipulam egrep e tabs de maneira diferente em strings) e outros sistemas sem nada no /etc/cron.d/ (o script terminou com um erro). Então, aqui está um patch para fazê-lo funcionar nesses 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" |

Não tenho muita certeza de que as mudanças no primeiro egrep sejam uma boa idéia, mas esse script foi testado no RHEL3,4,5 e Debian5 sem nenhum problema. Espero que isto ajude!

jbbarth
fonte
3

Construindo em cima de @Kyle

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

para evitar os comentários geralmente na parte superior de / etc / passwd,

E no macosx

for user in $(dscl . -list /users | cut -f1 -d:); do echo $user; crontab -u $user -l; done    
Todos
fonte
3
Você não deveria grep -v '^#'em vez de confiar no número mágico 11?
precisa
1
As distros do Red Hat / CentOS não escrevem as dicas úteis no início do crontab de um usuário, portanto, cortar as 11 primeiras linhas obliterará o conteúdo dele. A mesma coisa se um usuário do Ubuntu editou seu próprio crontab e removeu toda a mão.
Dale Anderson
Consulte Por que você não lê linhas com "for" .
fedorqui 'Então pare de prejudicar'
3

Eu acho que um liner melhor estaria abaixo. Por exemplo, se você tiver usuários no NIS ou LDAP, eles não estariam no / etc / passwd. Isso fornecerá as crontabs de todos os usuários que efetuaram login.

for I in `lastlog | grep -v Never | cut -f1 -d' '`; do echo $I ; crontab -l -u $I ; done
Monte
fonte
Consulte Por que você não lê linhas com "for" .
fedorqui 'Então, pare de prejudicar'
3

você pode escrever para toda a lista de usuários:

sudo crontab -u userName -l

,

Você também pode ir para

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

esse arquivo listará os agendamentos

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

Com desculpas e obrigado a yukondude.

Tentei resumir as configurações de tempo para facilitar a leitura, apesar de não ser um trabalho perfeito, e não toco em 'toda sexta-feira' ou 'apenas nas segundas-feiras'.

Esta é a versão 10 - agora:

  • corre muito, muito mais rápido
  • possui caracteres de progresso opcionais para que você possa melhorar ainda mais a velocidade.
  • usa uma linha divisória para separar o cabeçalho e a saída.
  • saídas em um formato compacto quando todos os intervalos de tempo encontrados podem ser resumidos.
  • Aceita Jan ... Dec descritores para os meses do ano
  • Aceita Mon ... Descritores do sol para dias da semana
  • tenta lidar com o dianmying-style do anacron no estilo debian quando ele está ausente
  • tenta lidar com as linhas crontab que executam um arquivo após pré-testar a executabilidade usando "[-x ...]"
  • tenta lidar com as linhas crontab que executam um arquivo após pré-testar a executabilidade usando "command -v"
  • permite o uso de intervalos e listas de intervalos.
  • suporta o uso de peças de execução em arquivos / var / spool crontab específicos do usuário.

Agora estou publicando o script completo aqui.

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

David Collier
fonte
2

Como é uma questão de percorrer um arquivo ( /etc/passwd) e executar uma ação, estou perdendo a abordagem adequada em Como posso ler um arquivo (fluxo de dados, variável) linha por linha (e / ou campo por campo) )? :

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

Isso lê /etc/passwdlinha por linha usando :como delimitador de campo. Ao dizer read -r user _, fazemos $usersegurar o primeiro campo e_ o restante (é apenas uma variável de lixo eletrônico a ignorar).

Dessa forma, podemos chamar crontab -uusando a variável $user, que citamos por segurança (e se ela contiver espaços? É improvável nesse arquivo, mas você nunca pode saber).

fedorqui 'Então pare de prejudicar'
fonte
1

No Solaris, para um nome de usuário conhecido específico:

crontab -l username

Todos os outros * Nix precisarão de -umodificador:

crontab -u username -l

Para obter todos os trabalhos do usuário de uma vez no Solaris, assim como outras postagens acima:

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

Para mim, veja / var / spool / cron / crontabs é a melhor maneira

Nic0
fonte
2
isso já foi respondido antes
bummi
-2

Esse script gera o Crontab em um arquivo e também lista todos os usuários que confirmam aqueles que não têm entrada no 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
fonte
//, RobFrost, você tem certeza de que este script, conforme escrito aqui, funciona consistentemente?
Nathan Basanese 24/03
Consulte Por que você não lê linhas com "for" . Além disso, isso foi respondido várias vezes antes de você postar este.
fedorqui 'Então, pare de prejudicar'