Подтвердить что ты не робот

Может ли bash script указать, выполняется ли он через cron?

Не получилось много удачи в этом вопросе, и я подумал о публикации на SF, но на самом деле это похоже на вопрос о развитии. Если нет, пожалуйста, не стесняйтесь мигрировать.

Итак, у меня есть script, который проходит через cron каждое утро примерно в 3 часа ночи. Иногда я запускаю одни и те же скрипты вручную. Проблема в том, что каждый раз, когда я запускаю свой script вручную, и он терпит неудачу, он отправляет мне электронное письмо; хотя я могу посмотреть на результат и просмотреть ошибку в консоли.

Есть ли способ для bash script сказать, что он запускается через cron (возможно, используя whoami) и только отправляет электронное письмо, если это так? Я бы хотел прекратить получать электронные письма, когда я делаю свое тестирование...

4b9b3361

Ответ 1

вы можете попробовать "tty", чтобы узнать, работает ли он терминалом или нет. это не скажет вам, что он специально запускается cron, но вы можете определить, является ли его "не пользователем как подсказкой".

вы также можете получить свой родительский pid и следовать за ним по дереву, чтобы искать cron, хотя это немного тяжело.

Ответ 2

Почему бы не иметь аргумент командной строки, который является -t для тестирования или -c для cron.

Или еще лучше:

[email protected]

Если он не указан, не отправляйте электронное письмо.

Ответ 3

Здесь два разных варианта:

  • Возьмите электронную почту из своей программы script/и пусть cron обработает ее. Если вы установите переменную MAILTO в своем crontab, cron отправит что-либо напечатанное на этот адрес электронной почты. например:

    [email protected]
    # run five minutes after midnight, every day
    5 0 * * *       $HOME/bin/daily.job
    
  • Установите переменную среды в вашем crontab, которая используется для определения, работает ли она под cron. например:

    THIS_IS_CRON=1
    # run five minutes after midnight, every day
    5 0 * * *       $HOME/bin/daily.job
    

    и в вашем script что-то вроде

    if [ -n "$THIS_IS_CRON" ]; then echo "I'm running in cron"; else echo "I'm not running in cron"; fi
    

Ответ 4

У меня была аналогичная проблема. Я решил это с проверкой, является ли stdout TTY. Это проверка, если вы выполняете script в интерактивном режиме:

if [ -t 1 ] ; then 
    echo "interacive mode";
else
    #send mail
fi

Я получил это от: Как определить, работает ли моя оболочка script через канал?

Тест -t возвращает true, если дескриптор файла открыт и ссылается на терминал. '1' является стандартным.

Ответ 5

Я знаю, что вопрос старый, но я столкнулся с той же проблемой. Это было мое решение:

CRON=$(pstree -s $$ | grep -q cron && echo true || echo false)

затем проверьте

if $CRON
then
    echo "Being run by cron"
else
    echo "Not being run by cron"
fi

та же идея, что и упомянутая выше, - следует за PID до дерева процессов, проверяющего cron.

Примечание. Это решение работает специально для cron, в отличие от некоторых других решений, которые работают в любое время, когда script запускается не интерактивно.

Ответ 6

Что для меня работает, это проверить $TERM. Под cron это "тупой", но под оболочкой это что-то другое. Используйте команду set в вашем терминале, затем в cron- script и проверьте его

if [ "dumb" == "$TERM" ]
then
    echo "cron"
else
    echo "term"
fi

Ответ 7

Я хотел бы предложить новый ответ на этот вопрос с высокой степенью голосования. Это работает только в системах systemd с loginctl (например, Ubuntu 14.10+, RHEL/CentOS 7+), но может дать гораздо больше авторитетный ответ, чем ранее представленные решения.

service=$(loginctl --property=Service show-session $(</proc/self/sessionid))
if [[ ${service#*=} == 'crond' ]]; then
   echo "running in cron"
fi

Подводя итог: при использовании с systemd, crond (например, sshd и другие) создает новый сеанс, когда он запускает работа для пользователя. Этот сеанс имеет идентификатор, который является уникальным для всего времени работы машины. Каждый сеанс имеет некоторые свойства, одним из которых является имя службы, которая его запускала. loginctl может указать нам значение этого свойства, которое будет "crond" тогда и только тогда, когда сеанс действительно был запущен с помощью crond.


Преимущества использования переменных среды:

  • Не нужно изменять записи cron для добавления специальных вызовов или переменных среды.
  • Отсутствие возможности промежуточного процесса, изменяющего переменные среды для создания ложных или ложных отрицательных

Преимущества перед тестированием для tty:

  • Отсутствие ложных срабатываний в конвейерах, сценарии запуска и т.д.

Преимущества проверки дерева процессов:

  • Нет ложных срабатываний от процессов, у которых также есть crond в их имени
  • Нет ложных негативов, если script отменен

Ответ 8

Мне также понравилась идея от Tal, но также вижу риск возврата undefined. Я закончил с слегка измененной версией, которая, по-моему, работает очень гладко:

CRON="$( pstree -s $$ | grep -c cron )"

Таким образом, вы можете проверить, что $CRON равен 1 или 0 в любое время.

Ответ 9

Многие из команд, использованных в предыдущих публикациях, доступны не во всех системах (pstree, loginctl, tty). Это было единственное, что работало для меня на десятилетнем маршрутизаторе BusyBox/OpenWrt, который я сейчас использую в качестве черного списка DNS-сервера. Он запускает скрипт с функцией автообновления. Запустив crontab, он отправляет электронное письмо.

[ -z "$TERM" ] || [ "$TERM" = "dumb" ] && echo 'Crontab' || echo 'Interactive'

В интерактивной оболочке $TERM -variable возвращает значение vt102 для меня. Я включил проверку на "тупой", так как @edoceo упомянул, что это работает для него. Я не использовал '==', поскольку он не полностью переносим.