Проверьте еженедельную работу cron [закрыто]

237

У меня есть #!/bin/bashфайл в каталоге cron.week.

Есть ли способ проверить, работает ли он? Не могу ждать 1 неделю

Я нахожусь на Debian 6 с рутом

динамический
источник
4
Разве вы не можете просто протестировать скрипт, запустив его в командной строке?
Фредерик Хамиди
5
просто добавьте отдельную запись в ваш crontabфайл, который запускает ваш файл каждые несколько минут, посмотрите, есть ли ожидаемые результаты, и затем удалите тестовую запись из вашего crontab. попробуйтеcrontab -e
Дэвин
61
Нет, запускать его из командной строки не очень хорошо. Простой запуск скрипта из командной строки не гарантирует, что он будет запущен так же, как тот же пользователь, который запускался из cron. Даже если он запускается от имени того же пользователя, вы никогда не сможете быть уверены, что все остальное будет таким же. Сценарии, работа из командной строки , может не для всех видов причин при запуске из хрон.
andynormancx
8
"все виды" могут быть слегка гиперболическими ... разрешения и переменные среды - это те две, которые приходят на ум, вы можете легко иметь другие начальные условия, такие как псевдонимы
andynormancx
3
Я только что прошел тестирование новой работы cron, я добавлю еще один пункт в "allorts". Если у вас есть вещи в bash_profile, они не запускаются один раз в задании cron, тогда как тестирование задания из командной строки работает отлично. Тестирование заданий cron в стандартной командной строке вообще не является хорошим тестом.
andynormancx

Ответы:

233

Просто сделайте то, что делает cron, запустите следующее root:

run-parts -v /etc/cron.weekly

... или следующий, если вы получаете сообщение об ошибке «Не каталог: -v»:

run-parts /etc/cron.weekly -v

Опция -vпечатает имена скриптов до их запуска.

NNRooth
источник
4
Если я использую опцию -v, показывающую ошибку «Не каталог: -v», в моей системе нет справочной страницы для этой команды, -v означает подробное право? Я использую Centos 6,4
макс
3
Чтобы избежать ошибки «Не каталог», я должен был сделать это вместо этого: run-parts /etc/cron.weekly -v
Крейг Хаятт
22
Но это не учитывает переменные окружения, которые могут быть установлены в crontab
fcurella
34
run-partsпросто запускает скрипты данного каталога. Ничего общего с cron.
Николас
23
Это действительно не должно быть одобрено и принято, кроме запуска скрипта, он ничего не говорит о том, будет ли скрипт действительно работать при запуске из cron. Используйте отличный crontest скрипт в одном из других ответов на этот вопрос.
andynormancx
87

Немного за рамками вашего вопроса ... но вот что я делаю.

Как мне проверить работу cron? Этот вопрос тесно связан с тем, «как я тестирую скрипты, которые запускаются в неинтерактивных контекстах, запускаемых другими программами?» В cron триггер является некоторым условием времени, но множество других * nix-средств запускают сценарии или фрагменты сценария неинтерактивными способами, и часто условия, в которых запускаются эти сценарии, содержат что-то неожиданное и вызывают сбой до устранения ошибок. (См. Также: https://stackoverflow.com/a/17805088/237059 ).

Общий подход к этой проблеме полезно иметь.

Один из моих любимых приемов - использовать сценарий, который я написал под названием « crontest ». Он запускает команду target в сеансе экрана GNU из cron, так что вы можете подключиться к отдельному терминалу, чтобы увидеть, что происходит, взаимодействовать со сценарием, даже использовать отладчик.

Чтобы настроить это, вы должны использовать «все звезды» в записи crontab и указать crontest в качестве первой команды в командной строке, например:

* * * * * crontest /command/to/be/tested --param1 --param2

Так что теперь cron будет запускать вашу команду каждую минуту, но crontest гарантирует, что одновременно запускается только один экземпляр. Если для выполнения команды требуется время, вы можете выполнить команду «screen -x» и посмотреть, как она выполняется. Если команда является сценарием, вы можете поместить команду «read» вверху, чтобы она остановилась и подождала завершения прикрепления экрана (нажмите enter после присоединения)

Если ваша команда представляет собой скрипт bash, вы можете сделать это вместо этого:

* * * * * crontest --bashdb /command/to/be/tested --param1 --param2

Теперь, если вы подключитесь с помощью «screen -x», вы столкнетесь с интерактивным сеансом bashdb, и вы сможете пройтись по коду, изучить переменные и т. Д.

#!/bin/bash

# crontest
# See https://github.com/Stabledog/crontest for canonical source.

# Test wrapper for cron tasks.  The suggested use is:
#
#  1. When adding your cron job, use all 5 stars to make it run every minute
#  2. Wrap the command in crontest
#        
#
#  Example:
#
#  $ crontab -e
#     * * * * * /usr/local/bin/crontest $HOME/bin/my-new-script --myparams
#
#  Now, cron will run your job every minute, but crontest will only allow one
#  instance to run at a time.  
#
#  crontest always wraps the command in "screen -d -m" if possible, so you can
#  use "screen -x" to attach and interact with the job.   
#
#  If --bashdb is used, the command line will be passed to bashdb.  Thus you
#  can attach with "screen -x" and debug the remaining command in context.
#
#  NOTES:
#   - crontest can be used in other contexts, it doesn't have to be a cron job.
#       Any place where commands are invoked without an interactive terminal and
#       may need to be debugged.
#
#   - crontest writes its own stuff to /tmp/crontest.log
#
#   - If GNU screen isn't available, neither is --bashdb
#

crontestLog=/tmp/crontest.log
lockfile=$(if [[ -d /var/lock ]]; then echo /var/lock/crontest.lock; else echo /tmp/crontest.lock; fi )
useBashdb=false
useScreen=$( if which screen &>/dev/null; then echo true; else echo false; fi )
innerArgs="$@"
screenBin=$(which screen 2>/dev/null)

function errExit {
    echo "[-err-] $@" | tee -a $crontestLog >&2
}

function log {
    echo "[-stat-] $@" >> $crontestLog
}

function parseArgs {
    while [[ ! -z $1 ]]; do
        case $1 in
            --bashdb)
                if ! $useScreen; then
                    errExit "--bashdb invalid in crontest because GNU screen not installed"
                fi
                if ! which bashdb &>/dev/null; then
                    errExit "--bashdb invalid in crontest: no bashdb on the PATH"
                fi

                useBashdb=true
                ;;
            --)
                shift
                innerArgs="$@"
                return 0
                ;;
            *)
                innerArgs="$@"
                return 0
                ;;
        esac
        shift
    done
}

if [[ -z  $sourceMe ]]; then
    # Lock the lockfile (no, we do not wish to follow the standard
    # advice of wrapping this in a subshell!)
    exec 9>$lockfile
    flock -n 9 || exit 1

    # Zap any old log data:
    [[ -f $crontestLog ]] && rm -f $crontestLog

    parseArgs "$@"

    log "crontest starting at $(date)"
    log "Raw command line: $@"
    log "Inner args: $@"
    log "screenBin: $screenBin"
    log "useBashdb: $( if $useBashdb; then echo YES; else echo no; fi )"
    log "useScreen: $( if $useScreen; then echo YES; else echo no; fi )"

    # Were building a command line.
    cmdline=""

    # If screen is available, put the task inside a pseudo-terminal
    # owned by screen.  That allows the developer to do a "screen -x" to
    # interact with the running command:
    if $useScreen; then
        cmdline="$screenBin -D -m "
    fi

    # If bashdb is installed and --bashdb is specified on the command line,
    # pass the command to bashdb.  This allows the developer to do a "screen -x" to
    # interactively debug a bash shell script:
    if $useBashdb; then
        cmdline="$cmdline $(which bashdb) "
    fi

    # Finally, append the target command and params:
    cmdline="$cmdline $innerArgs"

    log "cmdline: $cmdline"


    # And run the whole schlock:
    $cmdline 

    res=$?

    log "Command result: $res"


    echo "[-result-] $(if [[ $res -eq 0 ]]; then echo ok; else echo fail; fi)" >> $crontestLog

    # Release the lock:
    9<&-
fi
Stabledog
источник
2
Потрясающе, идеальное решение. Все остальные методы, которые я пробовал, на самом деле не работали, crontest легко решила проблему.
andynormancx
1
Это было намного больше, чем мне нужно, но +1 для отличного решения в любом случае; установка cron для более частой работы и вывода вывода в / tmp была достаточно хороша, чтобы определить мою проблему.
jcollum
2
Прохладно. Да, нет причин
зажигать
2
Отличный материал. Обратите внимание на Mac, я должен был, brew tap discoteq/discoteq; brew install flockа затем изменить сценарий для использования/usr/local/bin/flock
Claudiu
1
хорошая утилита! Очень полезно для диагностики проблем аутентификации в неинтерактивных контекстах.
Эрик Блум,
44

После работы с некоторыми вещами в cron, которые не были мгновенно совместимы, я обнаружил, что следующий подход хорош для отладки:

crontab -e

* * * * * /path/to/prog var1 var2 &>>/tmp/cron_debug_log.log

Это будет запускать задачу раз в минуту, и вы можете просто посмотреть в /tmp/cron_debug_log.logфайле, чтобы выяснить, что происходит.

Это не совсем «работа с огнем», которую вы, возможно, искали, но это мне очень помогло при отладке скрипта, который сначала не работал в cron.

Automatico
источник
9
Я бы порекомендовал этот подход. Проблема в большинстве случаев заключается в том, что вы не видите ошибку.
Евгений Якимович
8
Неверная строка, ни один дистрибутив не использует bash для оболочки cron, поэтому & >> не работает. Я предлагаю использовать >>/tmp/cron_debug_log.log 2>&1вместо
drizzt
1
Что вы подразумеваете под /path/to/prog- какой прогой?
Натан
3
Программа, которую вы собираетесь запустить с помощью cron. Это может быть, usr/home/myFancyScript.shили это может быть просто ls, или все, что вы хотите регулярно запускать.
Автоматически
Это сработало для меня. Это был самый простой способ сделать быстрый тест, чтобы проверить, все ли в порядке
abhijit
25

Я бы использовал файл блокировки, а затем настраивал задание cron на запуск каждую минуту. (используйте crontab -e и * * * * * / path / to / job) Таким образом, вы можете просто продолжать редактировать файлы, и каждую минуту они будут проверяться. Кроме того, вы можете остановить cronjob, просто коснувшись файла блокировки.

    #!/bin/sh
    if [ -e /tmp/cronlock ]
    then
        echo "cronjob locked"
        exit 1
    fi

    touch /tmp/cronlock
    <...do your regular cron here ....>
    rm -f /tmp/cronlock
Дэйв Фернхольц
источник
4
Вы также можете использовать flock(1)из оболочки; см man 1 flock. Довольно удобно для такого использования, поскольку обеспечивает автоматическую блокировку.
Крейг Рингер
5

Как насчет того, чтобы положить его в очередь cron.hourly, дождаться следующего запуска почасовых заданий cron и затем удалить? Это запустится один раз в течение часа и в среде cron. Вы также можете запустить ./your_script, но это не будет иметь ту же среду, что и под Cron.

Иеремия Уиллкок
источник
это почти то же самое, что и ответ @ Cort3z, с меньшей детализацией
jcollum
5

Ни один из этих ответов не соответствовал моей конкретной ситуации: я хотел запустить одно конкретное задание cron, только один раз, и запустить его немедленно.

Я нахожусь на сервере Ubuntu, и я использую cPanel для настройки своих заданий cron.

Я просто записал свои текущие настройки, а затем отредактировал их через одну минуту. Когда я исправил еще одну ошибку, я просто отредактировал ее снова через одну минуту. И когда я все закончил, я просто сбросил настройки обратно на прежние.

Пример: сейчас 4:34 вечера, поэтому я поставил 35 16 * * *, чтобы он работал в 16:35.

Это сработало как очарование, и самое большее, что я когда-либо должен был ждать, было чуть меньше одной минуты.

Я думал, что это лучший вариант, чем некоторые другие ответы, потому что я не хотел запускать все свои еженедельные выпуски, и я не хотел, чтобы работа выполнялась каждую минуту. У меня уходит несколько минут, чтобы исправить все проблемы, прежде чем я снова буду готов их протестировать. Надеюсь, это кому-нибудь поможет.

Бен С
источник
Почему вы используете cron для запуска «только один раз и запускаете его немедленно»? Похоже, вам лучше просто запустить скрипт напрямую.
Ян Хантер
4

Помимо этого вы также можете использовать:

http://pypi.python.org/pypi/cronwrap

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

Низкий Киан Сон
источник
10
Разве Cron уже не отправляет по электронной почте и не выводит из скрипта после выполнения?
Эрик
Cron отправляет электронное письмо пользователю, и, как правило, пользователь для большинства заданий cron является пользователем root или неинтерактивной службой, поэтому вы никогда не увидите электронные письма. Вот как серверы заполняются, когда ошибка вызывает огромный поток писем, и они возвращаются к корню.
dragon788
3

Я использую следующее решение:

  1. Отредактируйте crontab (используйте команду: crontab -e), чтобы запускать задание так часто, как это необходимо (каждые 1 минуту или 5 минут)
  2. Измените сценарий оболочки, который должен быть выполнен с использованием cron, чтобы напечатать вывод в некоторый файл (например: echo "Working отлично" >>
    output.txt)
  3. Проверьте файл output.txt с помощью команды: tail -f output.txt, которая напечатает последние добавления в этот файл, и, таким образом, вы сможете отслеживать выполнение скрипта.
Abhilash
источник
2

Я обычно проверяю, запустив задание, которое я создал следующим образом:

Для этого проще использовать два терминала.

запустить работу:

#./jobname.sh

перейти к:

#/var/log and run 

запустите следующее:

#tailf /var/log/cron

Это позволяет мне видеть обновления журналов cron в режиме реального времени. Вы также можете просмотреть журнал после его запуска, я предпочитаю смотреть в режиме реального времени.

Вот пример простой работы cron. Запуск ням-обновления ...

#!/bin/bash
YUM=/usr/bin/yum
$YUM -y -R 120 -d 0 -e 0 update yum
$YUM -y -R 10 -e 0 -d 0 update

Вот разбивка:

Первая команда обновит сам yum, а следующая - системные обновления.

-R 120: устанавливает максимальное количество времени ожидания yum перед выполнением команды.

-e 0: устанавливает уровень ошибки 0 (диапазон 0 - 10). 0 означает печатать только критические ошибки, о которых вам необходимо сообщить.

-d 0: устанавливает уровень отладки равным 0 - увеличивает или уменьшает количество печатаемых документов. (диапазон: 0 - 10).

-у: предположим да; предположим, что ответ на любой вопрос, который будет задан, - да

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

#chmod +x /etc/cron.daily/jobname.sh 

Надеюсь, это поможет, Дорлак

Dorlack
источник
2
sudo run-parts --test /var/spool/cron/crontabs/

файлы в этом crontabs/каталоге должны быть исполняемыми владельцем - восьмеричный700

Источник: man cronи NNRooth«s

n611x007
источник
5
Две вещи Первое: для запуска вещей, как sudo, используется другая среда (определенные переменные). Таким образом, ошибки в вашем crontab могут работать, когда они выполняются как 'sudo', но не будут работать, когда они выполняются как 'root' (и наоборот). Второе: 'man cron' не показывает мне эту информацию (хорошо, мой мужчина, похоже, относится к debian) ... 'man run-parts' говорит, что --test не запускает сценарии, а только печатает имена их. Так что сценарии даже не проверены. Незначительная вещь: «исполняемый владельцем»: насколько я знаю, только cronjobs выполняются от имени пользователя root.
Алекс
-1

Я использую Webmin, потому что это жемчужина производительности для тех, кто считает администрирование командной строки немного пугающим и непроницаемым.

В веб-интерфейсе «Система> Запланированные задания Cron> Редактировать задание Cron» есть кнопка «Сохранить и запустить сейчас».

Он отображает вывод команды и именно то, что мне нужно.

Кикаха
источник