Проблема с $ RANDOM в crontab


8

У меня странная проблема с $ RANDOM в cron. Я хочу выполнить команду случайное количество минут после того, как cronjob срабатывает.

Этот пример работает непосредственно в терминале и задерживает команду до 30 секунд (замените команду на то, что вы хотите, на самом деле это эхо для / dev / ttyUSB0):

sleep `expr $RANDOM \% 30` ; command

Если в crontab находится одна и та же строка, команда всегда запускается немедленно без задержки:

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

Если я использую выражение без $ RANDOM, оно работает нормально - задержка составляет 15 секунд:

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

Другими словами, похоже, что $ RANDOM не работает в cron.

Но это не просто потому, что само значение $ RANDOM равно нулю, потому что тогда это должно дать задержку в 10:

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

Я также пробовал с && instread of; но это не помогает На самом деле тогда команда вообще не стреляет!

Конечно, я мог бы поместить задержку в скрипт, который затем вызывается из crontab, но это не объясняет мою проблему и не заставляет меня учиться :-)

Это Debian Lenny, если это что-то меняет.

Ответы:


15

cronиспользует /bin/shоболочку для выполнения задач. В некоторых дистрибутивах это символическая ссылка на dash. Ни один из них не поддерживает $RANDOMпеременную, которая является bash-специфическим расширением.

  • С vixie-cron вы можете поставить строку SHELL=/bin/bashвверху вашего crontab.

  • В противном случае вам придется согласиться с bash -c 'echo $RANDOM'или perl -e 'print int(rand(65535))'.

    (В приведенном выше примере 65535 является максимальным числом для возврата. Вы также можете применить другую математику внутри скрипта.)

  • В правильно настроенной системе вы были бы проинформированы об этом cronсами - она ​​всегда отправляет выходные данные задания, включая сообщения об ошибках, по электронной почте. Установите легкий MTA.


Кроме того, в bash, $(( ))предпочтительнее, чем `expr`.


Последнее, что я проверил, /bin/shэто не настоящая оболочка, а просто символическая ссылка на предпочитаемую оболочку системного администратора (обычно bash или dash) в Debian.
Hello71

1
@ Hello71: Что я и сказал в посте. Тем не менее, системное ПО обычно вызывает /bin/sh(и ожидает, что оно будет совместимо с оболочкой Bourne). Примером является system()функция в glibc. Поэтому /bin/shобычно указывает на самую быструю Bourne-совместимую оболочку; и системный администратор должен установить свое предпочтение в соответствующей строке / etc / passwd, чтобы не применять это предпочтение в масштабе
всей

@ Hello71: ... хорошо, в основном то, что я сказал в посте. (Я знаю, что большинство других дистрибутивов ссылаются shна них bash, но это не имело значения.)
grawity

Вы правы, /bin/shуказывает на тире. До сих пор я никогда не слышал о тире. Я посмотрел, и это легкий вариант Баш. Кроме того, я не знал, что cron работал в «искалеченной» среде, но это объясняет различные другие проблемы, с которыми я сталкивался в прошлом. Кстати, я начал использовать, $(())но так как это не сработало, я попробовал всевозможные варианты и в итоге expr- что, конечно, тоже не сработало. Но на этом я и закончил :-) Можно ли запустить нормальную оболочку bash без ограничений bash -c 'xxxx'? Кстати, это не возможно, чтобы поставить разрывы строк в комментариях?
marlar

@marlar: 1) dashэто оболочка. Это не более или менее нормально, чем bash. Это тоже не вариант. 2) См. Пункты № 1 и № 2 в ответе.
Гравитация

1

cronобычно работает в менее «полной» среде, что означает, что у вас просто нет многих доступных переменных среды. По-видимому, $RANDOMэто один из таких sleepслучаев , и фактически ваша команда просто терпит неудачу с ошибкой из-за неопределенной переменной - именно поэтому ваша команда вообще не выполнялась, когда вы переключились на &&вместо ;. (Ну, на самом деле, $RANDOMэто функция Bash, но cronона не работает в полной среде Bash, которой явно не хватает этой функции.)

Для выполнения этой задачи вам нужно будет использовать отдельный скрипт Bash, как вы сказали. В качестве альтернативы, вы можете найти способ использования cat /dev/urandomнепосредственно в cronкоманде, но, вероятно, будет проще просто перенести то, что у вас есть, в отдельный скрипт Bash.


1
Это не красиво, но я нашел это решение, аналогичное вашему предложению: sleep $ (expr od -An -N1 -i /dev/urandom\% 30); команда
marlar

1
$RANDOMне является частью какой-то "полной" среды. Это не имеет ничего общего с переменными среды, установленными при запуске процесса. Это специальная переменная, созданная на лету в bash. Его новое значение всегда генерируется всякий раз, когда переменная читается. --- cronпо умолчанию используется, /bin/shпоэтому в системах, где /bin/shнет ссылок bash $RANDOM, по умолчанию работать не будет.
Пабук
Используя наш сайт, вы подтверждаете, что прочитали и поняли нашу Политику в отношении файлов cookie и Политику конфиденциальности.
Licensed under cc by-sa 3.0 with attribution required.