Como criar um trabalho cron usando o Bash automaticamente sem o editor interativo?

395

O crontab tem um argumento para criar trabalhos cron sem usar o editor (crontab -e). Em caso afirmativo, qual seria o código para criar um cronjob a partir de um script Bash?

Raúl Roa
fonte
5
Infelizmente, a maioria das principais respostas aqui estão apenas mostrando como modificar o crontab - embora de maneiras razoavelmente seguras - mas acho que é a abordagem errada em geral. Melhor, mais seguro e mais simples é soltar um arquivo no {{cron.d}}, e há (atualmente) respostas com baixa votação explicando como fazer isso se você olhar mais para baixo.
gregmac

Respostas:

539

Você pode adicionar ao crontab da seguinte maneira:

#write out current crontab
crontab -l > mycron
#echo new cron into cron file
echo "00 09 * * 1-5 echo hello" >> mycron
#install new cron file
crontab mycron
rm mycron

Explicação da linha Cron

* * * * * "command to be executed"
- - - - -
| | | | |
| | | | ----- Day of week (0 - 7) (Sunday=0 or 7)
| | | ------- Month (1 - 12)
| | --------- Day of month (1 - 31)
| ----------- Hour (0 - 23)
------------- Minute (0 - 59)

Fonte nixCraft .

dogbane
fonte
14
Você deve usar tempfile ou mktemp
Paweł Polewicz
166
(crontab -l; eco "00 09 * * 1-5 eco olá") | crontab -
Edo
32
(crontab -l ; echo "00 09 * * 1-5 echo hello") | crontab -- mais fácil copiar answear de Edo
WBAR
8
Eu sugiro mudar isso ;com &&como um guarda de segurança contra a caso, se crontab -lfalhar. então, como:(crontab -l && echo "0 0 0 0 0 some entry") | crontab -
MacUsers
12
@MacUsers, crontab -lfalha se não houver crontab, portanto, o uso &&torna impossível para o script adicionar a primeira entrada ao crontab.
precisa saber é o seguinte
312

Você pode fazer isso on-the-fly

crontab -l | { cat; echo "0 0 0 0 0 some entry"; } | crontab -

crontab -llista os trabalhos atuais do crontab, catimprime, echoimprime o novo comando e crontab -adiciona todo o material impresso ao arquivo crontab. Você pode ver o efeito fazendo um novo crontab -l.

TheBonsai
fonte
3
obrigado, você poderia explicar a sintaxe ou apontar para um URL que explica isso?
sites
9
crontab -llista os trabalhos atuais do crontab, catimprime, echoimprime o novo comando e crontab -adiciona todo o material impresso ao arquivo crontab. Você pode ver o efeito fazendo um novocrontab -l
nha
3
Funciona um prazer para mim. Se o usuário não tiver um crontab existente, você verá no crontab for <username>, mas funcionará assim mesmo.
Fazy
21
não funciona na minha instância do Amazon EC2. Em vez disso, (crontab -l ; echo "00 09 * * 1-5 echo hello") | crontab -funciona.
Stéphane Bruckert 4/11
11
Parece um candidato a um UUcatA .
ceving
86

Este menor não requer arquivo temporário, é imune a várias inserções e permite alterar a programação de uma entrada existente.

Digamos que você tenha estes:

croncmd="/home/me/myfunction myargs > /home/me/myfunction.log 2>&1"
cronjob="0 */15 * * * $croncmd"

Para adicioná-lo ao crontab, sem duplicação:

( crontab -l | grep -v -F "$croncmd" ; echo "$cronjob" ) | crontab -

Para removê-lo do crontab, qualquer que seja sua programação atual:

( crontab -l | grep -v -F "$croncmd" ) | crontab -

Notas:

  • grep -F corresponde literalmente à string, pois não queremos interpretá-la como uma expressão regular
  • Também ignoramos o agendamento de horário e procuramos apenas o comando. Por aqui; o cronograma pode ser alterado sem o risco de adicionar uma nova linha ao crontab
MoonCactus
fonte
@ moeseth: você pode elaborar?
MoonCactus 31/12/16
você deve experimentá-lo em seu computador
moeseth
2
@ moeseth: Eu obviamente tentei no meu computador (linux). Eu não sugeriria coisas aleatórias que não funcionavam: /
MoonCactus 1/17/17
2
A propósito, 27 pessoas não podem estar erradas (a partir de hoje). Portanto, descreva por que não está funcionando na sua configuração, para que possamos ajudar.
MoonCactus
2
Pode ser um problema OSX.
moeseth
40

Obrigado a todos por sua ajuda. Reunindo o que encontrei aqui e em outros lugares, vim com isso:

O código

command="php $INSTALL/indefero/scripts/gitcron.php"
job="0 0 * * 0 $command"
cat <(fgrep -i -v "$command" <(crontab -l)) <(echo "$job") | crontab -

Não consegui descobrir como eliminar a necessidade das duas variáveis ​​sem me repetir.

commandé obviamente o comando que eu quero agendar. jobpega $commande adiciona os dados de agendamento. Eu precisava das duas variáveis ​​separadamente na linha de código que faz o trabalho.

Detalhes

  1. Crédito para duckyflip, eu uso esse pequeno redirecionamento ( <(*command*)) para transformar a saída de crontab -lem input para o fgrepcomando.
  2. fgrepfiltra todas as correspondências de $command( -vopção), sem distinção entre maiúsculas e minúsculas ( -iopção).
  3. Novamente, o pequeno redirecionamento ( <(*command*)) é usado para transformar o resultado novamente em entrada para o catcomando.
  4. O catcomando também recebe echo "$job"(auto-explicativo), novamente, através do uso do redirecionamento (<(*command*) ).
  5. Portanto, a saída filtrada crontab -le a simples echo "$job", combinadas, são canalizadas ('|') crontab -para finalmente serem gravadas.
  6. E todos eles viveram felizes para sempre!

Em poucas palavras:

Essa linha de código filtra todos os trabalhos cron que correspondem ao comando e, em seguida, grava os trabalhos cron restantes com o novo, atuando efetivamente como uma função "adicionar" ou "atualizar". Para utilizar este, tudo que você tem a fazer é trocar o valores para o commande jobvariáveis.

Stoutie
fonte
5
Para o benefício de outras pessoas que leem, a vantagem dessa abordagem é que você pode executá-la várias vezes sem se preocupar com entradas duplicadas no crontab (ao contrário de todas as outras soluções). Isso é por causa dofgrep -v
aleemb
5
Se você preferir a maneira tradicional da esquerda para a direita de canalizar as coisas, substitua a última linha por: crontab -l | fgrep -i -v "$command" | { cat; echo "$job"; } | crontab -l
Antoine Lizée
11
@ AntoineLizée, você responde que tem um "l" extra no final, que não deveria estar lá.
Henry
26

EDIT (substituição fixa):

cat <(crontab -l) <(echo "1 2 3 4 5 scripty.sh") | crontab -
duckyflip
fonte
Isso irá substituir qualquer conteúdo crontab
TheBonsai
11
@TheBonsai oh eu vejo, eu fixa-lo agora por isso deve anexar o novo comando para o conteúdo crontab existentes
duckyflip
3
Lembre-se de que a substituição do processo do Bash engole erros. Se crontab -lfalhar, mas crontab -for bem-sucedido, seu crontab será de uma linha.
ceving
13

Houve muitas boas respostas sobre o uso do crontab, mas nenhuma menção a um método mais simples, como o uso cron.

A utilização cronaproveitaria os arquivos e diretórios do sistema localizados em /etc/crontab, /etc/cron.daily,weekly,hourlyou /etc/cron.d/:

cat > /etc/cron.d/<job> << EOF
SHELL=/bin/bash 
PATH=/sbin:/bin:/usr/sbin:/usr/bin 
MAILTO=root HOME=/  
01 * * * * <user> <command>
EOF

Neste exemplo acima, criamos um arquivo /etc/cron.d/, fornecemos as variáveis ​​de ambiente para que o comando seja executado com êxito e fornecemos usero comando e o commandpróprio. Este arquivo não deve ser executável e o nome deve conter apenas alfanumérico e hífens (mais detalhes abaixo).

Para dar uma resposta completa, porém, vejamos as diferenças entre crontabvs cron/crond:

crontab -- maintain tables for driving cron for individual users

Para aqueles que desejam executar o trabalho no contexto de seu usuário no sistema, o uso crontabpode fazer todo o sentido.

cron -- daemon to execute scheduled commands

Para aqueles que usam o gerenciamento de configuração ou desejam gerenciar trabalhos para outros usuários, nesse caso, devemos usar cron .

Um rápido trecho das páginas de manual fornece alguns exemplos do que fazer e não fazer:

O arquivo / etc / crontab e os arquivos em /etc/cron.d devem pertencer ao root e não devem ser graváveis ​​em grupo ou outros. Ao contrário da área de spool, os arquivos em /etc/cron.d ou em /etc/cron.hourly, /etc/cron.daily, /etc/cron.weekly e /etc/cron.monthly também podem ser links simbólicos, desde que o link simbólico e o arquivo para o qual ele aponta sejam de propriedade da raiz. Os arquivos em /etc/cron.d não precisam ser executáveis, enquanto os arquivos em /etc/cron.hourly, /etc/cron.daily, /etc/cron.weekly e /etc/cron.monthly, como eles são executados por peças executadas (consulte peças executadas (8) para obter mais informações).

Fonte: http://manpages.ubuntu.com/manpages/trusty/man8/cron.8.html

Gerenciar crons dessa maneira é mais fácil e escalável da perspectiva do sistema, mas nem sempre será a melhor solução.

Mike Mackintosh
fonte
11
Vale ressaltar que <job>não deve incluir uma extensão de arquivo.
JWW
7

Provavelmente, você está automatizando isso e não deseja que um único trabalho seja adicionado duas vezes. Nesse caso, use:

__cron="1 2 3 4 5 /root/bin/backup.sh"
cat <(crontab -l) |grep -v "${__cron}" <(echo "${__cron}")

Isso só funciona se você estiver usando o BASH. Não estou ciente da shsintaxe correta DASH ( ).

Atualização: isso não funciona se o usuário ainda não tiver um crontab. Uma maneira mais confiável seria:

(crontab -l ; echo "1 2 3 4 5 /root/bin/backup.sh") | sort - | uniq - | crontab - 

Como alternativa, se sua distribuição suportar, você também pode usar um arquivo separado:

echo "1 2 3 4 5 /root/bin/backup.sh" |sudo tee /etc/crond.d/backup

Encontrei aqueles em outra questão SO .

kvz
fonte
Usando sh em vez de bash, talvez?
Kvz
Ainda estou sh: 1: Syntax error: "(" unexpectedusando sh .
Batandwa
Isso só funciona se você estiver usando o BASH. Não estou ciente da sintaxe correta do DASH (sh). Também
atualizou
11
fwiw, eu recebo esse erro usando o bash se houver um espaço entre o <e (. Isso significa < (falha, mas <(trabalhos, a menos que haja asteriscos na sua agenda ...
doublesharp
Eu acredito que esta é a maneira correta:cat <(crontab -l |grep -v "${CRON}") <(echo "${CRON}") | crontab -
Stanislav
5

Para uma criação / substituição rápida e suja agradável de um crontab de um script BASH, usei esta notação:

crontab <<EOF
00 09 * * 1-5 echo hello
EOF
Gibbsoft
fonte
5

Uma variante que apenas edita o crontab se a string desejada não for encontrada lá:

CMD="/sbin/modprobe fcpci"
JOB="@reboot $CMD"
TMPC="mycron"
grep "$CMD" -q <(crontab -l) || (crontab -l>"$TMPC"; echo "$JOB">>"$TMPC"; crontab "$TMPC")
Gerald Schade
fonte
3

Se você estiver usando o Vixie Cron, por exemplo, na maioria das distribuições Linux, basta colocar um arquivo em /etc/cron.d com o cronjob individual.

Isso funciona apenas para a raiz, é claro. Se o seu sistema suportar isso, você deverá ver vários exemplos. (Observe o nome de usuário incluído na linha, na mesma sintaxe do antigo / etc / crontab)

É uma triste característica no cron que não há como lidar com isso como um usuário comum e que tantas implementações do cron não têm como lidar com isso.

mandril
fonte
2

Então, no Debian, Ubuntu e em muitas distros similares baseadas no Debian ...

Existe um mecanismo de concatenação de tarefas cron que pega um arquivo de configuração, os agrupa e os adiciona ao seu serviço cron em execução.

Você pode colocar um arquivo em /etc/cron.d/somefilename, em que somefilename é o que você deseja.

sudo echo "0,15,30,45 * * * * ntpdate -u time.nist.gov" >> /etc/cron.d/vmclocksync

Vamos desmontar isso:

sudo - porque você precisa de privilégios elevados para alterar as configurações do cron no diretório / etc

eco - um veículo para criar saída em saída padrão. printf, cat ... funcionaria bem

"- use aspas duplas no início da sua string, você é um profissional

0,15,30,45 * * * * - o cronograma padrão de execução do cron, que é executado a cada 15 minutos

ntpdate -u time.nist.gov - o comando real que quero executar

"- porque minhas primeiras aspas duplas precisam de um amigo para fechar a linha que está sendo impressa

>> - o redirecionamento duplo é anexado em vez de substituído *

/etc/cron.d/vmclocksync - vmclocksync é o nome do arquivo que eu escolhi, ele entra em /etc/cron.d/


* se usássemos o redirecionamento>, poderíamos garantir que tivéssemos apenas uma entrada de tarefa. Porém, estaríamos correndo o risco de descartar outras regras em um arquivo existente. Você pode decidir por si próprio se uma possível destruição com> está correta ou possíveis duplicatas com >> são para você. Como alternativa, você pode fazer algo complicado ou envolvido para verificar se o nome do arquivo existe, se existe algo nele e se você está adicionando algum tipo de duplicata - mas, tenho algo a fazer e não posso fazer isso por você agora.

BradChesney79
fonte
2

Script bash para adicionar tarefa cron sem o editor interativo. O código abaixo ajuda a adicionar um cronjob usando arquivos linux.

#!/bin/bash

cron_path=/var/spool/cron/crontabs/root

#cron job to run every 10 min.
echo "*/10 * * * * command to be executed" >> $cron_path

#cron job to run every 1 hour.
echo "0 */1 * * * command to be executed" >> $cron_path
akash
fonte
11
Sei que já faz muito tempo, mas essa ainda é a única resposta boa, já que todos os mais votados removem os velhos crons em vez de apenas acrescentar o novo.
28/08/19
11
Este não instala um cron. Apenas o anexa a um arquivo. Você precisará, de alguma forma, notificar o processo cron para instalar a nova entrada.
Apoorv Parijat
1

Aqui está uma função bash para adicionar um comando crontabsem duplicação

function addtocrontab () {
  local frequency=$1
  local command=$2
  local job="$frequency $command"
  cat <(fgrep -i -v "$command" <(crontab -l)) <(echo "$job") | crontab -
}
addtocrontab "0 0 1 * *" "echo hello"
Klas Mellbourn
fonte
1
CRON="1 2 3 4 5 /root/bin/backup.sh" 
cat < (crontab -l) |grep -v "${CRON}" < (echo "${CRON}")

adicione o parâmetro -w ao comando grep exato, sem que o parâmetro -w inclua o cronjob "testing" causa a exclusão do trabalho cron "testing123"

função de script para adicionar / remover cronjobs. sem entradas de duplicação:

cronjob_editor () {         
# usage: cronjob_editor '<interval>' '<command>' <add|remove>

if [[ -z "$1" ]] ;then printf " no interval specified\n" ;fi
if [[ -z "$2" ]] ;then printf " no command specified\n" ;fi
if [[ -z "$3" ]] ;then printf " no action specified\n" ;fi

if [[ "$3" == add ]] ;then
    # add cronjob, no duplication:
    ( crontab -l | grep -v -F -w "$2" ; echo "$1 $2" ) | crontab -
elif [[ "$3" == remove ]] ;then
    # remove cronjob:
    ( crontab -l | grep -v -F -w "$2" ) | crontab -
fi 
} 
cronjob_editor "$1" "$2" "$3"

testado:

$ ./cronjob_editor.sh '*/10 * * * *' 'echo "this is a test" > export_file' add
$ crontab  -l
$ */10 * * * * echo "this is a test" > export_file
speefak
fonte
Se você tiver o mesmo comando no crontab duas vezes (executando em horários diferentes), a remoção excluirá as duas linhas.
Michaelkay
1

Minha solução preferida para isso seria esta:

(crontab -l | grep . ; echo -e "0 4 * * * myscript\n") | crontab -

Isso garantirá que você esteja manipulando a nova linha em branco na parte inferior corretamente. Para evitar problemas com o crontab, geralmente você deve finalizar o arquivo crontab com uma nova linha em branco. E o script acima garante que primeiro remova todas as linhas em branco com o "grep". parte e, em seguida, adicione uma nova linha em branco no final com o "\ n" no final do script. Isso também impedirá a obtenção de uma linha em branco acima do seu novo comando se o arquivo crontab existente terminar com uma linha em branco.

gsus
fonte
1
echo "0 * * * * docker system prune --force >/dev/null 2>&1" | sudo tee /etc/cron.daily/dockerprune
user11547308
fonte
0

Não, não há opção no crontab para modificar os arquivos cron.

Você precisa: pegar o arquivo cron atual (crontab -l> newfile), alterá-lo e colocar o novo arquivo no lugar (crontab newfile).

Se você está familiarizado com o perl, pode usar este módulo Config :: Crontab .

Andrea LLP

andcoz
fonte
0

função de script para adicionar cronjobs. verifique entradas duplicadas, expressões utilizáveis ​​*> "

cronjob_creator () {         
# usage: cronjob_creator '<interval>' '<command>'

  if [[ -z $1 ]] ;then
    printf " no interval specified\n"
elif [[ -z $2 ]] ;then
    printf " no command specified\n"
else
    CRONIN="/tmp/cti_tmp"
    crontab -l | grep -vw "$1 $2" > "$CRONIN"
    echo "$1 $2" >> $CRONIN
    crontab "$CRONIN"
    rm $CRONIN
fi
}

testado:

$ ./cronjob_creator.sh '*/10 * * * *' 'echo "this is a test" > export_file'
$ crontab  -l
$ */10 * * * * echo "this is a test" > export_file

fonte: meu cérebro;)


fonte
-5

Provavelmente, você pode alterar o editor padrão para ed e usar um heredoc para editar.

EDITOR=ed
export EDITOR

crontab -e << EOF
> a
> * * * * * Myscript
> * * * * * AnotherScript
> * * * * * MoreScript
> .
> w
> q
> EOF

Observe que o início > nesse código significa que a tecla Enter / Retorno é pressionada para criar uma nova linha.

O a significa APPEND, para que não substitua nada.

A . significa que você terminou de editar.

O w significa WRITE as alterações.

Os q meios SAIR ou saída ed.

você pode conferir

crontab -l

Você também pode excluir uma entrada.

EDITOR=ed
export EDITOR

crontab -e << EOF
> /Myscript/
> d
> .
> w
> q
> EOF

Isso excluirá a entrada crontab com Myscript.

O d significa excluir o padrão dentro de / / .

Não verifique novamente

crontab -l

Esta solução funciona dentro de um script muito menos o > é claro :-)

Jetchisel
fonte