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


8

У мене є дивна проблема з $ RANDOM в кроні. Я хотів би виконати команду випадковою кількістю хвилин після пожежі, яка спрацьовує.

Цей приклад працює безпосередньо в терміналі і затримує команду на 30 секунд (замініть команду на все, що завгодно, це насправді відлуння до / dev / ttyUSB0):

sleep `expr $RANDOM \% 30` ; command

Якщо той самий рядок розміщений у crontab, команда завжди запускається негайно без затримки:

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

Якщо я використовую вираз без $ RANDOM, він працює добре - це робить затримку на 15 секунд:

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

Іншими словами, здається, що $ RANDOM не працює в кроні.

Але це не просто тому, що $ RANDOM сам оцінює нуль, тому що тоді це повинно дати затримку 10:

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

Я також намагався з && замінити; але це не допомагає. Насправді тоді команда зовсім не стріляє!

Я, звичайно, міг би помістити затримку в сценарій, який потім викликається з crontab, але це не пояснює мою проблему і не змушує мене вчитися :-)

Це Дебіан Ленні, якщо це має значення.

Відповіді:


15

cronвикористовує /bin/shоболонку для виконання завдань. У деяких дистрибутивах це символьне посилання на dash. Жоден з них не підтримує $RANDOMзмінну, яка є bashспецифічним розширенням.

  • За допомогою vixie-cron ви можете поставити лінію SHELL=/bin/bashу верхній частині свого кронтабу.

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

    (У наведеному вище прикладі 65535 - це максимальне число, яке потрібно повернути. Ви також можете застосувати іншу математику всередині сценарію.)

  • У правильно налаштованій системі вас би про це повідомили cronсамі - вона завжди надсилає вихідні завдання, включаючи повідомлення про помилки, електронною поштою. Встановіть легкий MTA.


Крім того, в bash, $(( ))віддається перевага `expr`.


Останнє, що я перевірив, чи /bin/shне була фактичною оболонкою, а лише символьне посилання на бажану оболонку sysadmin (як правило, bash або dash) на Debian.
Привіт71

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

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

Ви праві, /bin/shвказує на тире. Досі я ніколи не чув про тире. Я подивився на це, і це легкий варіант баш. Крім того, я не знав, що cron працював у «каліці», але це пояснює різні інші проблеми, які у мене були в минулому. До речі, я почав використовувати, $(())але оскільки це не спрацювало, я спробував всілякі варіації і закінчив expr- що, звичайно, теж не працювало. Але на цьому я і закінчився :-) Чи можна запустити звичайну баш-оболонку без обмежень за допомогою bash -c 'xxxx'? Btw, чи не можна ставити перерви у коментарях?
1111 року

@marlar: 1) dashоболонка. Це не якийсь - або більш-менш нормально , ніж bash. Це теж не варіант. 2) Див. Пункти №1 та №2 у відповіді.
grawity

1

cronЗазвичай працює з менш "повним" середовищем, тобто просто не має у вас багатьох однакових змінних оточуючих. Мабуть , $RANDOMце один такий, а насправді ваша sleepкоманда просто збій з помилкою через невизначену змінної - тому ваша команда не змогла працювати на всіх , коли ви перейшли на &&замість ;. (Ну, насправді, $RANDOMце функція Bash, але cronвона не працює в повному середовищі Bash, що, очевидно, не вистачає цієї функції.)

Для виконання цього завдання вам потрібно буде використовувати окремий сценарій Bash, як ви вже говорили. Крім того, ви можете з'ясувати спосіб використання cat /dev/urandomбезпосередньо в cronкоманді, але, мабуть, буде простіше просто перенести те, що у вас є, до окремого сценарію Bash.


1
Це не дуже, але я знайшов таке рішення, яке є аналогом вашої пропозиції: sleep $ (expr od -An -N1 -i /dev/urandom\% 30); команда
марла

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