Problema com $ RANDOM no crontab

9

Eu tenho um problema estranho com $ RANDOM no cron. Desejo executar um comando um número aleatório de minutos após o cronjob disparar.

Este exemplo funciona diretamente no terminal e atrasa o comando em até 30 segundos (substitua o comando pelo que você quiser, na verdade é um eco para / dev / ttyUSB0):

sleep `expr $RANDOM \% 30` ; command

Se a mesma linha for colocada no crontab, o comando sempre dispara imediatamente sem o atraso:

* * * * * sleep `expr $RANDOM \% 30` ; command

Se eu usar uma expressão sem $ RANDOM, ela funcionará bem - isso atrasa 15 segundos:

* * * * * sleep `expr 10 + 5` ; command

Em outras palavras, parece que $ RANDOM não funciona em um cron.

Mas não é simplesmente porque o próprio $ RANDOM é avaliado como zero, porque isso deve gerar um atraso de 10:

* * * * * sleep `expr $RANDOM \% 30 + 10` ; command

Eu também tentei com o && instread de; mas isso não ajuda. De fato, o comando não dispara!

É claro que eu poderia colocar o atraso em um script que é chamado de crontab, mas isso não explica o meu problema e não me faz aprender :-)

É o Debian Lenny se isso faz alguma diferença.

marlar
fonte

Respostas:

17

cronusa o /bin/shshell para executar tarefas. Em algumas distros, este é um link simbólico para dash. Nenhum deles suporta a $RANDOMvariável, que é uma bashextensão específica.

  • Com o vixie-cron, você pode colocar uma linha SHELL=/bin/bashna parte superior do seu crontab.

  • Caso contrário, você terá que se contentar com bash -c 'echo $RANDOM'ou perl -e 'print int(rand(65535))'.

    (No exemplo acima, 65535 é o número máximo a ser retornado. Você também pode aplicar outras contas dentro do script.)

  • Em um sistema configurado corretamente, você seria informado sobre isso por cronsi só - ele sempre envia a saída do trabalho, incluindo mensagens de erro, por email. Instale um MTA leve.


Além disso, no bash, $(( ))é preferível a `expr`.

user1686
fonte
A última vez que verifiquei, /bin/shnão era um shell real, apenas um link simbólico para o shell preferido do sysadmin (normalmente bash ou dash) no Debian.
Hello71
1
@ Hello71: Foi o que eu disse no post. No entanto, é habitual que o software do sistema seja chamado /bin/sh(e espera que seja compatível com o shell Bourne). Um exemplo é a system()função na glibc. Portanto, /bin/shgeralmente aponta para o shell mais rápido compatível com Bourne; e o administrador do sistema é suposto para definir a sua preferência na linha apropriada de / etc / passwd, não para executar a preferência do sistema de largura
user1686
@ Hello71: ... ok, principalmente o que eu disse no post. (Eu sei que a maioria das outras distros ligar shpara bash, mas não parecem relevantes.)
user1686
Você está certo, /bin/shaponta para correr. Até agora, eu nunca ouvi falar de traço. Eu procurei e é uma variante leve do bash. Além disso, eu não sabia que o cron era executado em um ambiente "aleijado", mas explica vários outros problemas que tive no passado. Btw, eu comecei a usar, $(())mas como não funcionava, tentei todo tipo de variação e acabei com expr- o que obviamente também não funcionou. Mas foi aí que eu terminei :-) É possível executar um shell bash normal sem as limitações usando bash -c 'xxxx'? Aliás, não é possível colocar quebras de linha nos comentários?
marlar 31/03
@ marlar: 1) dashé uma concha. Não é mais ou menos normal que bash. Também não é uma variante. 2) Veja os pontos 1 e 2 da resposta.
user1686
2

cronnormalmente é executado com um ambiente menos "cheio", o que significa que você simplesmente não possui muitas das mesmas variáveis ​​de ambiente disponíveis. Aparentemente, $RANDOMé um deles e, de fato, seu sleepcomando está simplesmente falhando com um erro devido à variável indefinida - e é por isso que seu comando falhou em executar quando você alternou para em &&vez de ;. (Bem, na verdade, $RANDOMé uma função Bash, mas cronnão é executada em um ambiente Bash completo, o que evidentemente carece dessa função.)

Para realizar essa tarefa, você precisará usar um script Bash separado, como você disse. Como alternativa, você pode descobrir uma maneira de usar cat /dev/urandomdiretamente no croncomando, mas provavelmente seria mais fácil mudar o que você tem atualmente para um script Bash separado.

Kromey
fonte
1
Não é bonito, mas encontrei esta solução que é análoga à sua sugestão: sleep $ (expr od -An -N1 -i /dev/urandom\% 30); comando
marlar 31/03
1
$RANDOMnão faz parte de algum ambiente "completo". Não tem nada a ver com variáveis ​​de ambiente definidas no início do processo. É uma variável especial criada "on the fly" no bash. Seu novo valor é sempre gerado sempre que a variável é lida. --- cronpor padrão, usa /bin/shsistemas nos quais /bin/shnão está vinculado bash $RANDOMnão funcionará por padrão.
pabouk