Przetestuj cotygodniowe zadanie CRON [zamknięte]


237

Mam #!/bin/bashplik w katalogu cron.week.

Czy istnieje sposób na sprawdzenie, czy to działa? Nie mogę się doczekać 1 tygodnia

Jestem na Debianie 6 z rootem


4
Nie możesz po prostu przetestować skryptu, uruchamiając go w wierszu poleceń?
Frédéric Hamidi

5
po prostu dodaj osobny wpis w swoim, crontabktóry uruchamia twój plik co kilka minut, sprawdź, czy są tam oczekiwane wyniki, a następnie usuń wpis testowy z twojego crontab. trycrontab -e
davin,

61
Nie, uruchomienie go z wiersza poleceń nie jest dobrym sposobem. Samo uruchomienie skryptu z wiersza poleceń nie gwarantuje, że uruchomi się tak samo, jak ten sam użytkownik, który był uruchamiany z crona. Nawet jeśli zostanie uruchomiony jako ten sam użytkownik, nigdy nie możesz być pewien, czy wszystko inne będzie takie samo. Skrypty, że praca z linii poleceń może nie dla wszystkich z różnych powodów, gdy uruchamiany z crona.
andynormancx

8
„wszystkie rodzaje” mogą być nieco hiperboliczne ... uprawnienia i zmienne środowiskowe to dwa, które
przychodzą

3
Właśnie przeszedłem testy nowej pracy crona, dodam kolejny element do „wszystkich rodzajów”. Jeśli masz coś w bash_profile, nie uruchamiają się raz w zadaniu cron, podczas gdy testowanie zadania z wiersza poleceń działa idealnie. Testowanie zadań crona w standardowym wierszu poleceń wcale nie jest dobrym testem.
andynormancx

Odpowiedzi:


233

Po prostu zrób to, co robi cron, uruchom następujące polecenie root:

run-parts -v /etc/cron.weekly

... lub następny, jeśli pojawi się błąd „Not a directory: -v”:

run-parts /etc/cron.weekly -v

Opcja -vdrukuje nazwy skryptów przed ich uruchomieniem.


4
Jeśli użyję opcji -v z informacją o błędzie „Brak katalogu: -v”, w moim systemie nie ma strony podręcznika dla tego polecenia, -v oznacza pełne, prawda? Używam centos 6,4
maks.

3
Aby uniknąć błędu „Not a directory”, musiałem to zrobić zamiast tego: run-parts /etc/cron.weekly -v
Craig Hyatt

22
Ale to nie bierze pod uwagę zmiennych środowiskowych, które można ustawić w crontab
fcurella

34
run-partspo prostu uruchamia skrypty danego katalogu. Nie ma nic wspólnego z cronem.
Nicolas

23
To naprawdę nie powinno było zostać ocenione i zaakceptowane, poza uruchomieniem skryptu nic nie mówi, czy skrypt rzeczywiście będzie działał po uruchomieniu z crona. Użyj doskonałego skryptu crontest w jednej z pozostałych odpowiedzi na to pytanie.
andynormancx 24.04.16

87

Nieco dalej niż twoje pytanie ... ale oto co robię.

„Jak przetestować zadanie CRON?” pytanie jest ściśle związane z „jak testować skrypty działające w nieinteraktywnych kontekstach uruchamianych przez inne programy?” W cronie wyzwalaczem jest pewien warunek czasowy, ale wiele innych * Nix obiektów uruchamia skrypty lub fragmenty skryptów w sposób nieinteraktywny, a często warunki, w których te skrypty działają, zawierają coś nieoczekiwanego i powodują uszkodzenie, dopóki błędy nie zostaną usunięte. (Zobacz także: https://stackoverflow.com/a/17805088/237059 )

Pomocne jest ogólne podejście do tego problemu.

Jedną z moich ulubionych technik jest użycie skryptu, który napisałem, zwanego „ crontest ”. Uruchamia komendę docelową w sesji ekranowej GNU z poziomu crona, dzięki czemu można podłączyć osobny terminal, aby zobaczyć, co się dzieje, wejść w interakcję ze skryptem, a nawet użyć debuggera.

Aby to ustawić, użyjesz „wszystkich gwiazdek” we wpisie crontab i określisz crontest jako pierwsze polecenie w wierszu poleceń, np .:

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

Więc teraz cron będzie wykonywał twoje polecenie co minutę, ale crontest zapewni, że będzie działać tylko jedna instancja na raz. Jeśli wykonanie polecenia wymaga czasu, możesz wykonać „screen -x”, aby dołączyć i oglądać, jak się uruchamia. Jeśli polecenie jest skryptem, możesz umieścić polecenie „czytaj” u góry, aby zatrzymać i czekać na zakończenie załączania ekranu (naciśnij klawisz Enter po dołączeniu)

Jeśli twoje polecenie jest skryptem bash, możesz to zrobić zamiast tego:

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

Teraz, jeśli załączysz za pomocą „screen -x”, staniesz przed interaktywną sesją bashdb i będziesz mógł przejść przez kod, zbadać zmienne itp.

#!/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

2
Niesamowite, idealne rozwiązanie. Wszystkie inne techniki, które wypróbowałem, naprawdę nie działały, crontest łatwo rozwiązał problem.
andynormancx

1
To było o wiele więcej niż potrzebowałem, ale i tak daje +1 za świetne rozwiązanie; ustawienie crona na częstsze uruchamianie i zrzut danych wyjściowych do / tmp było wystarczająco dobre, aby wykryć mój problem.
jcollum

2
Chłodny. Tak, nie ma powodu, aby odpalać buldożer, jeśli potrzebujesz tylko łopaty ręcznej :)
Stabledog

2
Świetne rzeczy. Uwaga na komputerze Mac musiałem brew tap discoteq/discoteq; brew install flockzmodyfikować skrypt, aby go użyć/usr/local/bin/flock
Claudiu,

1
niezła użyteczność! Bardzo przydatne do diagnozowania problemów z uwierzytelnianiem w nieinteraktywnych kontekstach.
Eric Blum,

44

Po tym, jak zadzwoniłem z niektórymi rzeczami w cronie, które nie były od razu kompatybilne, stwierdziłem, że następujące podejście było dobre do debugowania:

crontab -e

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

Spowoduje to uruchomienie zadania raz na minutę i po prostu zajrzyj do /tmp/cron_debug_log.logpliku, aby dowiedzieć się, co się dzieje.

Nie jest to dokładnie „praca ogniowa”, której możesz szukać, ale bardzo mi to pomogło podczas debugowania skryptu, który początkowo nie działał w cronie.


9
Poleciłbym to podejście. Problem w większości przypadków polega na tym, że nie widać błędu.
Yauhen Yakimovich

8
Niepoprawna linia, żadna dystrybucja nie używa bash dla powłoki cron, więc & >> nie działa. Sugeruję użyć >>/tmp/cron_debug_log.log 2>&1Zamiast tego
drizzt

1
Co rozumiesz przez /path/to/prog- który program?
Nathan

3
Program, który zamierzasz uruchomić z cronem. Może to być usr/home/myFancyScript.shlub może być proste lslub cokolwiek, co chcesz regularnie uruchamiać.
Automatico

To zadziałało dla mnie. To był najłatwiejszy sposób na szybki test, aby sprawdzić, czy wszystko jest w porządku
abhijit

25

Używałbym pliku blokady, a następnie ustawiałem zadanie crona na uruchamianie co minutę. (użyj crontab -e i * * * * * / path / to / job) W ten sposób możesz po prostu edytować pliki i co minutę będą one testowane. Dodatkowo możesz zatrzymać cronjob, dotykając pliku blokady.

    #!/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
Możesz także użyć flock(1)z powłoki; zob man 1 flock. Całkiem przydatny do takich zastosowań, ponieważ zapewnia automatyczne blokowanie.
Craig Ringer

5

Co powiesz na włożenie go cron.hourly, odczekanie do następnego uruchomienia cronowych zadań cron, a następnie usunięcie go? Urodziłoby się to raz w ciągu godziny w środowisku cron. Możesz także uruchomić ./your_script, ale nie będzie to miało takiego samego środowiska jak w cronie.


jest to prawie to samo, co odpowiedź @ Cort3z, z mniejszą
ilością

5

Żadna z tych odpowiedzi nie pasuje do mojej konkretnej sytuacji, a mianowicie, że chciałem uruchomić jedno konkretne zadanie crona, tylko raz i uruchomić je natychmiast.

Jestem na serwerze Ubuntu i używam cPanel do konfigurowania moich zadań cron.

Po prostu zapisałem moje obecne ustawienia, a następnie edytowałem je za minutę. Kiedy naprawiłem kolejny błąd, po prostu edytowałem go ponownie za minutę. A kiedy wszystko się skończyło, przywróciłem ustawienia do poprzedniego stanu.

Przykład: Teraz jest 16:34, więc wstawiłem 35 16 * * *, aby działało o 16:35.

Działa jak urok, a najwięcej, na co musiałem czekać, to trochę mniej niż minuta.

Myślałem, że to lepsza opcja niż niektóre inne odpowiedzi, ponieważ nie chciałem uruchamiać wszystkich moich cron cotygodniowych i nie chciałem, aby zadanie działało co minutę. Zajmuje mi kilka minut, aby rozwiązać wszelkie problemy, zanim znów będę gotowy do przetestowania. Mam nadzieję, że to komuś pomaga.


Dlaczego miałbyś używać crona, aby uruchomić „tylko raz i uruchomić go natychmiast”? Wygląda na to, że lepiej byłoby po prostu uruchomić skrypt bezpośrednio.
Ian Hunter

4

Oprócz tego możesz także użyć:

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

aby zawinąć crona i wysłać Ci wiadomość e-mail w przypadku powodzenia lub niepowodzenia.


10
Czy Cron już nie wysyła wiadomości e-mail i nie wysyła skryptu po uruchomieniu?
Erik,

Cron wysyła wiadomość e-mail do użytkownika, a zwykle użytkownik większości zadań cron jest użytkownikiem root lub użytkownikiem nieinteraktywnym, więc nigdy nie widzisz wiadomości e-mail. W ten sposób serwery zapełniają się, gdy błąd powoduje ogromną liczbę e-maili i odbijają się do rootowania.
dragon788,

3

Rozwiązanie, którego używam, jest następujące:

  1. Edytuj crontab (użyj polecenia: crontab -e), aby uruchamiać zadanie tak często, jak to konieczne (co 1 minutę lub 5 minut)
  2. Zmodyfikuj skrypt powłoki, który powinien zostać wykonany przy użyciu crona, aby wydrukować dane wyjściowe w jakimś pliku (np .: echo „
    Działaj dobrze” >> output.txt)
  3. Sprawdź plik output.txt za pomocą polecenia: tail -f output.txt, który wydrukuje najnowsze dodatki do tego pliku, dzięki czemu można śledzić wykonanie skryptu

2

Zwykle testuję, uruchamiając utworzone w ten sposób zadanie:

W tym celu łatwiej jest użyć dwóch terminali.

uruchomić pracę:

#./jobname.sh

iść do:

#/var/log and run 

uruchom następujące:

#tailf /var/log/cron

To pozwala mi zobaczyć aktualizacje dzienników cron w czasie rzeczywistym. Możesz także przejrzeć dziennik po uruchomieniu, wolę oglądać w czasie rzeczywistym.

Oto przykład prostej pracy crona. Uruchamianie mniam aktualizacji ...

#!/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

Oto podział:

Pierwsze polecenie zaktualizuje samo yum, a następnie zastosuje aktualizacje systemu.

-R 120: Ustawia maksymalny czas, przez jaki yum będzie czekać przed wykonaniem polecenia

-e 0: Ustawia poziom błędu na 0 (zakres 0–10). 0 oznacza drukowanie tylko błędów krytycznych, o których należy poinformować.

-d 0: Ustawia poziom debugowania na 0 - zwiększa lub zmniejsza liczbę drukowanych rzeczy. (zakres: 0–10).

-y: Załóżmy, że tak; zakładamy, że odpowiedź na każde zadane pytanie brzmi „tak”

Po zbudowaniu zadania cron uruchomiłem poniższe polecenie, aby moje zadanie było wykonalne.

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

Mam nadzieję, że to pomaga, Dorlack


2
sudo run-parts --test /var/spool/cron/crontabs/

pliki w tym crontabs/katalogu muszą być wykonywane przez właściciela - octal700

źródło: man crona NNRooth„s


5
Dwa dzwonki. Po pierwsze: Do uruchamiania rzeczy, ponieważ sudo używa innego środowiska (zdefiniowane zmienne). Tak więc błędy w twoim crontabie mogą działać po wykonaniu jako „sudo”, ale nie będą działać, gdy zostaną wykonane jako „root” (i odwrotnie). Po drugie: „man cron” nie pokazuje mi tych informacji (ok, mój człowiek wydaje się być specyficzny dla Debiana) ... „man run-parts” mówi, że - test nie uruchamia skryptów, a jedynie drukuje nazwy im. Skrypty nie są nawet testowane. Drobna rzecz: „wykonywalny przez właściciela”: O ile mi wiadomo, cronjobs są wykonywane tylko jako root.
Alex

-1

Używam Webmina, ponieważ jest to klejnot produktywności dla kogoś, kto uważa administrację z wiersza poleceń za nieco zniechęcającą i nieprzeniknioną.

W interfejsie internetowym „System> Zaplanowane zadania Cron> Edytuj zadanie Cron” znajduje się przycisk „Zapisz i uruchom teraz”.

Wyświetla wynik polecenia i jest dokładnie tym, czego potrzebowałem.

Korzystając z naszej strony potwierdzasz, że przeczytałeś(-aś) i rozumiesz nasze zasady używania plików cookie i zasady ochrony prywatności.
Licensed under cc by-sa 3.0 with attribution required.