Como criar um crontab por meio de um script

153

Preciso adicionar um trabalho cron através de um script que corro para configurar um servidor. Atualmente, estou usando o Ubuntu. Eu posso usar, crontab -emas isso abrirá um editor para editar o crontab atual. Eu quero fazer isso programaticamente.

É possível fazer isso?

gaurav
fonte
Se você deseja modificar ou excluir uma entrada do crontab, veja minha solução abaixo.
187 Brian Brian

Respostas:

11

Os trabalhos Cron geralmente são armazenados em um arquivo por usuário em /var/spool/cron

A coisa mais simples a fazer é provavelmente apenas criar um arquivo de texto com o trabalho configurado, copiá-lo para a pasta cron spool e verificar se ele possui as permissões corretas (600).

Jason Stelzer
fonte
19
Modificar os arquivos diretamente em / var / spool / cron é desaprovado. De fato, se você olhar para os arquivos, eles geralmente conterão avisos como "NÃO EDITAR ESTE ARQUIVO" como a primeira linha.
Jared
12
@ Jared Embora eu concorde com a idéia, dizer que "ela é mal vista" não ajuda muito. Em vez disso, diga qual outro arquivo deve ser editado, se houver, ou explique os riscos de editar arquivos manualmente. Estou planejando criar alguns trabalhos cron através da linha de comando automatizada, e se a edição deste arquivo é a única opção e sem efeitos colaterais significativos, não vejo por que não devo usá-lo.
precisa
47
Role para baixo para a resposta real.
John Red
1
Na minha opinião, esta resposta é muito melhor: stackoverflow.com/a/610860/2681752
galaux
2
Adotei essa abordagem e me arrependi. No RHEL, o diretório / var / spool / cron não é executável mundialmente, portanto, os usuários não podem percorrer o diretório e editar seus arquivos manualmente. Se você tornar o / var / spool / cron mundial executável, seu administrador de sistema local amigável ficará bravo com você, além da alteração da permissão ser substituída se o pacote cronie for reinstalado ou atualizado.
functionvoid
384

Aqui está uma lista que não usa / requer que o novo trabalho esteja em um arquivo:

(crontab -l 2>/dev/null; echo "*/5 * * * * /path/to/job -with args") | crontab -

O 2>/dev/nullé importante para que você não receba a no crontab for usernamemensagem que alguns * nixes produzem se atualmente não houver entradas crontab.

Joe Casadonte
fonte
14
Essa deve ser a resposta aceita. Só precisa de um caminho agora para verificar se o one-liner eu pretendo adicionar já está lá ou não ...
ChrisPrime
7
... oh espere, aqui está como verificar se há algo no crontab do meu usuário antes de adicioná-lo com um script: stackoverflow.com/a/14451184/3686125 #
ChrisPrime
1
se esse script tiver como objetivo repetir e modificar uma tarefa cron existente, pode ser bom substituir a linha existente no crontab. vários marcadores podem ser usados ​​para controlar tarefas cron diferentes (controle-marcador-1, controle-marcador-2, etc ...): (crontab -l 2> / dev / null | grep -v controle-marcador-1; eco '* / 5 * * * * / caminho / para / job -com args # control-marker-1') | crontab -
chef
7
Achei que isso foi a remoção de entradas crontab existentes e também eu precisava usar um usuário diferente (root), então eu usei o seguinte para manter as entradas existentes: echo -e "$(sudo crontab -u root -l)\n* * * * * echo hello > /home/danny/temp.log 2>&1" | sudo crontab -u root -Espero que isso ajude alguém
Danny
60

Para crontabs de usuário (incluindo root), você pode fazer algo como:

crontab -l -u user | cat - filename | crontab -u user -

onde o arquivo chamado "nome do arquivo" contém itens a serem anexados. Você também pode manipular o texto usando sedou outra ferramenta no lugar de cat. Você deve usar o crontabcomando em vez de modificar diretamente o arquivo.

Uma operação semelhante seria:

{ crontab -l -u user; echo 'crontab spec'; } | crontab -u user -

Se você estiver modificando ou criando crontabs do sistema, eles podem ser manipulados como faria com arquivos de texto comuns. Eles são armazenados nos /etc/cron.d, /etc/cron.hourly, /etc/cron.daily, /etc/cron.weekly, /etc/cron.monthlydiretórios e nos arquivos /etc/crontabe /etc/anacrontab.

Pausado até novo aviso.
fonte
Parecia promissor, mas tentando a segunda abordagem (com echo), recebi "crontab: erro de uso: o nome do arquivo deve ser especificado para substituição". A página do manual Cron mostra a sintaxe como crontab [ -u user ] file, ou seja, com um nome de arquivo obrigatório. Existe algum truque para aceitar os dados canalizados?
Mark Berry
1
@ MarkBerry: Desculpe por isso. Em um canal, um hífen deve ser usado para indicar que a entrada é de stdin. Eu vou corrigir minha resposta.
Pausado até novo aviso.
29

No Ubuntu e em muitas outras distribuições, você pode simplesmente colocar um arquivo no /etc/cron.ddiretório que contém uma única linha com uma entrada válida do crontab . Não há necessidade de adicionar uma linha a um arquivo existente.

Se você só precisa de algo para executar diariamente, basta colocar um arquivo no /etc/cron.daily. Da mesma forma, você também pode soltar arquivos para /etc/cron.hourly, /etc/cron.monthly, e /etc/cron.weekly.

IvanGoneKrazy
fonte
5
Mas você deve ser root para fazer isso.
Keith
17

Uma resposta ainda mais simples para sua pergunta seria:

echo "0 1 * * * /root/test.sh" | tee -a /var/spool/cron/root

Você pode configurar cronjobs em servidores remotos como abaixo:

#!/bin/bash
servers="srv1 srv2 srv3 srv4 srv5"
for i in $servers
  do
  echo "0 1 * * * /root/test.sh" | ssh $i " tee -a /var/spool/cron/root"
done

No Linux, o local padrão do crontabarquivo é /var/spool/cron/. Aqui você pode encontrar os crontabarquivos de todos os usuários. Você só precisa anexar sua entrada do cronjob ao arquivo do respectivo usuário. No exemplo acima, o arquivo crontab do usuário raiz está sendo anexado com um cronjob para ser executado /root/test.shtodos os dias às 01:00.

ganesh pathak
fonte
Isso seria /var/spool/cron/crontabs/rootno Ubuntu.
Íhor Mé 06/06
17

Os arquivos Crontab são simplesmente arquivos de texto e, como tal, podem ser tratados como qualquer outro arquivo de texto. O objetivo do crontabcomando é tornar a edição dos arquivos crontab mais segura. Quando editado por esse comando, o arquivo é verificado quanto a erros e salvo apenas se não houver nenhum.

crontab [path to file]pode ser usado para especificar um crontab armazenado em um arquivo. Assim crontab -e, isso só instalará o arquivo se estiver livre de erros.

Portanto, um script pode gravar diretamente os arquivos da guia cron ou gravá-los em um arquivo temporário e carregá-los com o crontab [path to temp file]comando Escrever diretamente evita a necessidade de gravar um arquivo temporário, mas também evita a verificação de segurança.

cledoux
fonte
2
Para noobs como eu, observe que é crontab [path to file].. Essa foi definitivamente a melhor opção para mim, pois permite um código mais legível. Uso o crontab para rastrear encomendas e alterar meu papel de parede da área de trabalho com o status. Quando não estou esperando encomendas, não é preciso verificar a cada hora. É por isso que eu queria que o script editasse automaticamente a frequência cron.
Rasmus
1
@Rasmus Isso soa como um roteiro incrível que eu adoraria poder roubar. Alguma chance de compartilhar através de uma essência ou similar?
Cledoux
8

(Não tenho reputação suficiente para comentar, por isso estou adicionando como resposta: fique à vontade para adicioná-lo como comentário ao lado da resposta dele)

A linha única de Joe Casadonte é perfeita, exceto se você executar com set -e, ou seja, se o seu script estiver configurado para falhar por erro e se ainda não houver cronjobs. Nesse caso, o one-liner NÃO criará o cronjob, mas NÃO interromperá o script. A falha silenciosa pode ser muito enganadora.

O motivo é que crontab -lretorna com um 1código de retorno, fazendo com que o comando subseqüente (the echo) não seja executado ... portanto, o cronjob não é criado. Mas, como são executados como um subprocesso (por causa dos parênteses), eles não param o script.

(Curiosamente, se você executar o mesmo comando novamente, ele vai trabalhar: depois de ter executado crontab -uma vez, crontab -lainda saídas nada, mas ele não retorna mais um erro (você não obter a no crontab for <user>mensagem mais) para que o posterior. echoÉ executado e o crontab é criado)

De qualquer forma, se você executar com set -e, a linha deverá ser:

(crontab -l 2>/dev/null || true; echo "*/5 * * * * /path/to/job -with args") | crontab -
Faria
fonte
Sim, este é ainda mais perfeito.
Yngve Sneen Lindal
7

Como uma correção para aqueles que sugerem crontab -l | crontab -: Isso não funciona em todos os sistemas. Por exemplo, tive que adicionar um trabalho ao crontab raiz em dezenas de servidores executando uma versão antiga do SUSE (não pergunte o porquê). Os SUSEs antigos acrescentam linhas de comentário à saída de crontab -l, tornando crontab -l | crontab --os não-idempotentes (o Debian reconhece esse problema na página de manual do crontab e corrigiu sua versão do Vixie Cron para alterar o comportamento padrão de crontab -l).

Para editar programaticamente os crontabs em sistemas onde crontab -ladiciona comentários, você pode tentar o seguinte:

EDITOR=cat crontab -e > old_crontab; cat old_crontab new_job | crontab -

EDITOR=catdiz ao crontab para usar catcomo editor (não o vi padrão usual), que não altera o arquivo, mas o copia para o stdout. Isso ainda pode falhar se crontab -espera entrada em um formato diferente do que crontab -esai. Não tente substituir a final crontab -por crontab -e- ela não funcionará.

user2845840
fonte
4

Bem, /etc/crontabapenas um arquivo ascii, então o mais simples é apenas

 echo "*/15 * * * *   root     date" >> /etc/crontab

que adicionará um trabalho que enviará um e-mail a cada 15 minutos. Ajuste de acordo com o gosto e teste por grepmeios ou outros meios se a linha já foi adicionada para tornar seu script idempotente.

No Ubuntu et al, você também pode soltar arquivos nos /etc/cron.*quais é mais fácil fazer e testar --- além de não mexer com arquivos de configuração (sistema) como /etc/crontab.

Dirk Eddelbuettel
fonte
1
Eu acho que tecnicamente não é necessário monitorar as alterações no crontab, mesmo que, na realidade, a maioria das implementações o faça, então eu recomendaria uma chamada para crontab -e posteriormente para produzi-lo. O crontab -e honra a variável EDITOR se a memória servir, portanto, defini-la como / bin / true no momento deve forçar apenas o crontab a ser relido.
Ulrich Schwarz
1
Ainda é verdade em qualquer sistema Linux recente crond que monitora, e certamente na plataforma declarada do OP.
Dirk Eddelbuettel 02/02
Somente se você é root e deseja que o script seja executado como root. Isso pode não ser desejável no caso dos POs.
Keith
Não é assim, tenho muitas entradas não raiz no / etc / crontab. Você 'meramente' precisa do sudo para anexar ao arquivo. De qualquer forma, como afirmei, também há /etc/cron.*/, mas você também precisa ser root para escrever lá.
Dirk Eddelbuettel 02/02
2

Aqui está como modificar uma entrada do cron sem editar diretamente o arquivo cron (que é desaprovado).

crontab -l -u <user> | sed 's/find/replace/g' | crontab -u <user> -

Se você deseja remover uma entrada cron, use este:

crontab -l -u <user> | sed '/find/d' | crontab -u <user> -

Sei que não é isso que gaurav estava pedindo, mas por que não ter todas as soluções em um só lugar?

Brian Smith
fonte
1

Eu escrevi uma ferramenta de implantação do crontab em python: https://github.com/monklof/deploycron

pip install deploycron

Instalar o seu crontab é muito fácil, isso irá mesclar o crontab no crontab existente do sistema.

from deploycron import deploycron
deploycron(content="* * * * * echo hello > /tmp/hello")
monklof
fonte
1

É uma abordagem para adicionar incrementalmente o trabalho cron:

  ssh USER_NAME@$PRODUCT_IP nohup "echo '*/2 * * * * ping -c2 PRODUCT_NAME.com >> /var/www/html/test.html' | crontab -u USER_NAME -"
Oleksii Kyslytsyn
fonte