Dlaczego skrypty crontab nie działają?

525

Często crontabskrypty nie są wykonywane zgodnie z harmonogramem lub zgodnie z oczekiwaniami. Istnieje wiele przyczyn:

  1. zła notacja crontab
  2. problem z uprawnieniami
  3. Zmienne środowiska

Ta wiki społeczności ma na celu zebranie najważniejszych powodów, dla których crontabskrypty nie są wykonywane zgodnie z oczekiwaniami. Napisz każdy powód w osobnej odpowiedzi.

Podaj jeden powód na odpowiedź - szczegółowe informacje o tym, dlaczego nie został wykonany - i popraw (y) z tego jednego powodu.

Napisz tylko problemy specyficzne dla crona, np. Polecenia, które wykonują się zgodnie z oczekiwaniami ze strony powłoki, ale są wykonywane błędnie przez crona.

Adam Matan
źródło
12
Musisz zamknąć się, crontab -eaby cron zaczął działać. Na przykład za pomocą vima edytuję plik i używam go :wdo napisania, ale zadanie nie jest dodawane do crona, dopóki też nie wyjdę. Więc nie zobaczę pracy, dopóki ja :qteż nie.
DutGRIFF
Myślę, że najlepszym sposobem na debugowanie crona jest sprawdzenie syslog i znalezienie problemów.
Suneel Kumar
W moim przypadku - wiadomość e-mail
trafiała
Przerwy w dostawie prądu
Josef Klimuk

Odpowiedzi:

501

Inne środowisko

Cron przekazuje minimalny zestaw zmiennych środowiskowych do twoich zadań. Aby zobaczyć różnicę, dodaj pracę zastępczą w ten sposób:

* * * * * env> /tmp/env.output

Poczekaj na /tmp/env.outpututworzenie, a następnie ponownie usuń zadanie. Teraz porównaj zawartość /tmp/env.outputz danymi wyjściowymi polecenia envrun w swoim zwykłym terminalu.

Częstym tutaj „gotcha” jest PATHinna zmienna środowiskowa. Może skrypt cron używa polecenia somecommandznalezione w /opt/someApp/bin, który dodanych do PATHw /etc/environment? cron ignoruje PATHten plik, więc somecommanduruchamianie ze skryptu nie powiedzie się, gdy zostanie uruchomione z cronem, ale zadziała po uruchomieniu w terminalu. Warto zauważyć, że zmienne z /etc/environmentbędą przekazywane do zadań cron, tylko nie zmienne, które cron konkretnie ustawia, takie jak PATH.

Aby obejść ten problem, po prostu ustaw własną PATHzmienną u góry skryptu. Na przykład

#!/bin/bash
PATH=/opt/someApp/bin:/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin

# rest of script follows

Niektórzy wolą zamiast tego używać ścieżek bezwzględnych do wszystkich poleceń. Odradzam to. Zastanów się, co się stanie, jeśli chcesz uruchomić skrypt w innym systemie, aw tym systemie jest /opt/someAppv2.2/binzamiast tego polecenie. Musiałbyś przejść przez cały skrypt zastępując /opt/someApp/bingo /opt/someAppv2.2/binzamiast po prostu niewielkiej edycji w pierwszym wierszu skryptu.

Możesz także ustawić zmienną PATH w pliku crontab, który będzie obowiązywał dla wszystkich zadań cron. Na przykład

PATH=/opt/someApp/bin:/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin

15 1 * * * backupscript --incremental /home /root
geirha
źródło
5
Myślę, że po prostu do tego zakochałam się, a nowa linia na koniec ... podwójna whammy.
WernerCD
6
+1 za env, zupełnie zapomniałem o tym poleceniu i myślałem, że ŚCIEŻKA działa. W moim przypadku było to zupełnie inne.
Izkata
8
@pbr Jeśli takie katalogi są zapisywalne dla innych, system jest już zagrożony.
geirha,
6
@pbr Administrator systemu może nieświadomie usunąć główny system plików. Nie możesz uchronić się przed sysadminami popełniającymi głupie błędy. Jeśli zainstalujesz nowszą wersję interpretera, który nie jest kompatybilny wstecz, oczekiwałbym złamania niezależnie od tego. Dobrym sposobem na poradzenie sobie z tym jest zainstalowanie go jako innego polecenia. Np. Masz Python w wersji 2.x i instalujesz Python 3, instalujesz go jako python3, a nie python. A jeśli chodzi o / opt / someApp / bin, dlaczego, u licha, nie miałby rozsądnych uprawnień / praw własności? każdy rozsądny administrator zapewniłby rozsądne uprawnienia / prawa własności do plików systemowych.
geirha,
2
@pbr Wydaje się, że moglibyśmy trwać wiecznie, tak. Nadal nie rozumiem, dlaczego używanie PATH jest złym pomysłem. Jeśli masz ochotę omówić to dalej w medium, które lepiej nadaje się do dyskusji, znajdziesz mnie między innymi na #ubuntu i #bash na irc.freenode.net
geirha
336

Moja górna sprawa: jeśli zapomnisz dodać nowy wiersz na końcu crontabpliku. Innymi słowy, plik crontab powinien kończyć się pustą linią.

Poniżej znajduje się odpowiednia sekcja na stronach podręcznika dla tego problemu ( man crontabnastępnie przejdź do końca):

   Although cron requires that each entry in a crontab end  in  a  newline
   character,  neither the crontab command nor the cron daemon will detect
   this error. Instead, the crontab will appear to load normally. However,
   the  command  will  never  run.  The best choice is to ensure that your
   crontab has a blank line at the end.

   4th Berkeley Distribution      29 December 1993               CRONTAB(1)
4124
źródło
91
to taki showstopper, dlaczego nie został naprawiony przez tak wiele lat cron?
Capi Etheriel
2
Wydaje się być naprawiony w Vixie cron: man crontabna Ubuntu 10.10 mówi: „cron wymaga, aby każdy wpis w crontab kończył się znakiem nowej linii. Jeśli ostatni wpis w crontab nie zawiera nowej linii, cron uzna crontab (przynajmniej częściowo) za zepsuty i odmawiaj instalacji ”. (A data na koniec to 19 kwietnia 2010 r.)
Marius Gedminas
19
@barraponto W rzeczywistości jest to błąd w nowych edytorach tekstu. Znak „nowej linii” ma być znakiem końca linii , więc ostatnia linia w pliku tekstowym powinna kończyć się znakiem nowej linii, który nie jest pokazywany w edytorze. Vi i vim używają tej postaci poprawnie, a cron został zbudowany, zanim nowi redaktorzy zaczęli swoje dziwne zachowanie ... Dlatego graj w save, włączając pustą linię.
Izkata
6
Jeśli edytujesz crontab przy użyciu crontab -e, sprawdzi on składnię pliku przed zezwoleniem na zapis, w tym sprawdzenie znaku nowej linii.
Tom Harrison Jr
2
@ Chan-HoSuh, według strony podręcznika "cron wymaga, aby każdy wpis w crontab kończył się znakiem nowej linii. Jeśli w ostatnim wpisie w crontabie brakuje nowej linii, cron uzna crontab (przynajmniej częściowo) za uszkodzony i odmówi Zainstaluj to." To zachowanie zostanie wywołane podczas edycji, a następnie zapisania pliku crontab przy użyciu -eopcji i jest niezależne od edytora.
Tom Harrison Jr
139

Demon Cron nie działa. Naprawdę spieprzyłem to kilka miesięcy temu.

Rodzaj:

pgrep cron 

Jeśli nie widzisz numeru, cron nie działa. sudo /etc/init.d/cron startmoże być użyty do uruchomienia crona.

EDYCJA: Zamiast wywoływać skrypty inicjujące przez /etc/init.d, użyj narzędzia serwisowego, np

sudo service cron start

EDYCJA: Możesz także użyć systemctl we współczesnym Linuksie, np

sudo systemctl start cron
6019
źródło
47
Dzięki za pokazanie mi pgrep. Nadal robiłem ps -ef | grep foo
ripper234 17.0311
4
Możesz także użyć, pidof cronktóry pominie wyniki dla innych aplikacji, które również mają słowo „cron”, np. Crontab.
Pithikos,
Dziwne, wszystko to nie daje mi nic do pokazania, że ​​cron działa, ale jeśli ucieknę sudo service cron start, dostanęstart: Job is already running: cron
Colleen
1
service crond startjeśli jego centos / RHEL
Srihari Karanth
91

Skrypt pliki w cron.d/, cron.daily/, cron.hourly/, itd., Nie powinny zawierać kropki ( .), w przeciwnym razie run-parts je pominąć.

Zobacz części robocze (8):

   If neither the --lsbsysinit option nor the --regex option is given then
   the names must consist entirely of upper and lower case  letters,  dig‐
   its, underscores, and hyphens.

   If  the  --lsbsysinit  option  is given, then the names must not end in
   .dpkg-old  or .dpkg-dist or .dpkg-new or .dpkg-tmp, and must belong  to
   one  or more of the following namespaces: the LANANA-assigned namespace
   (^[a-z0-9]+$);   the   LSB   hierarchical   and   reserved   namespaces
   (^_?([a-z0-9_.]+-)+[a-z0-9]+$);  and  the  Debian cron script namespace
   (^[a-zA-Z0-9_-]+$).

Tak więc, jeśli masz skrypt cron backup.sh, analyze-logs.plw cron.daily/katalogu najlepiej usunąć nazwy rozszerzeń.

Xiè Jìléi
źródło
10
Jest to funkcja, a nie błąd - utrzymuje takie rzeczy jak myscript.backup lub myscript.original lub myscript.rpm-new przed uruchomieniem obok myscript.
pbr
@pbr: ma sens. Przydałoby się to przynajmniej do debugowania, jeśli run-parts --test(lub inna wymyślona opcja, jak np --debug.
Wypisywanie
8
Jeśli jest to funkcja, to nie jest fajna :( Wiele osób używa kropki w nazwie pliku (najczęściej jest to backup.sh). Jeśli chcesz, aby skrypt przestał działać, najbardziej logiczną metodą będzie usuń go z katalogu „cron.d”.
MatuDuke
7
Jest to tak zła funkcja, że ​​w rzeczywistości jest to błąd. Powszechną praktyką jest wymaganie określonego zakończenia (takiego jak „.list” lub „.cron” lub coś takiego), jeśli ludzie chcą mieć pewność, że wszystko działa poprawnie, gdy jest zamierzone. Arbitralne wybieranie kropki jako prawdopodobnego separatora dla „.bak” lub „.temp” lub cokolwiek innego jest całkowicie nieprzewidywalne, chyba że w sposób przewidywalny dezorientuje ludzi. Uzasadnione zakończenia, takie jak „.sh” i „.pl” są szeroko stosowane od dziesięcioleci. Jednak wiele osób używa kropki „_bak” lub „_temp” lub „-bak” zamiast kropki. To okropny wybór projektu; w najlepszym razie jest to błąd projektowy.
Teekin,
68

W wielu środowiskach cron wykonuje polecenia za pomocą sh, podczas gdy wiele osób zakłada, że ​​będzie używać bash.

Sugestie, aby przetestować lub naprawić to w przypadku niepowodzenia polecenia:

  • Spróbuj uruchomić polecenie, shaby zobaczyć, czy to działa:

    sh -c "mycommand"
    
  • Zawiń polecenie w podpowłokę bash, aby upewnić się, że zostanie uruchomione w bash:

    bash -c "mybashcommand"
    
  • Powiedz cronowi, aby uruchamiał wszystkie polecenia w bash, ustawiając powłokę u góry twojej crontab:

    SHELL=/bin/bash
    
  • Jeśli polecenie jest skryptem, upewnij się, że skrypt zawiera shebang:

    #!/bin/bash
    
Olorin
źródło
sugestia bash jest bardzo pomocna, naprawiono problem z moim cronem.
Maxim Galushka
To właśnie spowodowało mi 1 godzinę skrzypania / rozwiązywania problemów. Jeszcze bardziej kłopotliwe, jeśli nie zdajesz sobie sprawy z tego, że skrypt działa poprawnie ręcznie, jeśli masz typową powłokę bash, ale nie z nią cron. Dzięki!
Hendy
Dawno temu natknąłem się na coś związanego: polecenie sourcejest w bash, ale nie sh. W cron / sh użyj kropki: . envfilezamiast source envfile.
kungphu
@Clockwork sh "mycommand"mówi, shaby uruchomić mycommand jako plik skryptu. Miałeś na myśli sh -c "mycommand"? W każdym razie wydaje się, że ta odpowiedź polega na tym, aby polecenie było uruchamiane w trybie bash, więc dlaczego dodałeś shtutaj polecenie ?
Olorin
@Olorin Z mojego zrozumienia, celem pierwszego punktu była próba uruchomienia go za pomocą sh, aby sprawdzić, czy problem naprawdę wynika z faktu, że cron uruchamia go za pomocą sh zamiast bash. Z drugiej strony mam niewielką wiedzę na ten temat, więc mogę się mylić.
Mechaniczna
39

Miałem pewne problemy ze strefami czasowymi. Cron działał ze świeżą strefą czasową instalacji. Rozwiązaniem było zrestartowanie crona:

sudo service cron restart
luissquall
źródło
6
Tak, po zmianie strefy czasowej w systemie należy albo ponownie uruchomić każdą usługę, która dba o to, która jest godzina, albo uruchomić ponownie. Wolę restart, aby mieć pewność, że wszystko złapałem.
pbr
Na miłość boską, zabiłem na tym godziny. Próbowałem zrestartować usługę po tym, * * * * * touch /tmp/cronworksjak nic nie zrobiłem, ale jest RELOADna cronlog.
НЛО
36

W skryptach należy zastosować ścieżkę bezwzględną:

Na przykład /bin/grepnależy użyć zamiast grep:

# m h  dom mon dow   command
0 0 *  *  *  /bin/grep ERROR /home/adam/run.log &> /tmp/errors

Zamiast:

# m h  dom mon dow   command
0 0 *  *  *  grep ERROR /home/adam/run.log &> /tmp/errors

Jest to szczególnie trudne, ponieważ to samo polecenie będzie działać po uruchomieniu z powłoki. Powodem jest to, że cronnie ma tej samej PATHzmiennej środowiskowej co użytkownik.

Adam Matan
źródło
3
patrz odpowiedź geirha, możesz (musisz) zdefiniować
ŚCIEŻKĘ
9
Bzzt. NIE musisz definiować ŚCIEŻKI - najlepszym rozwiązaniem jest tutaj używanie ścieżek bezwzględnych. „ponieważ plik wykonywalny może znajdować się gdzie indziej na innym komputerze,„ nie atutuje ”Chcę, aby uruchomił dokładnie ten program, a nie kogoś innego, kto postawiłby ścieżkę przed moim oryginalnym programem”
pbr
1
tak, to było dla mnie, poza cronem mogłem uruchomić polecenie bezpośrednio, wewnątrz crona potrzebowała pełnej /usr/bin/whateverścieżki
Anentropic
32

Jeśli polecenie crontab zawiera %symbol, cron próbuje go zinterpretować. Więc jeśli korzystasz z dowolnego polecenia z nim %zawartego (takiego jak specyfikacja formatu dla polecenia date), musisz go uciec.

To i inne dobre gotcha tutaj:
http://www.pantz.org/software/cron/croninfo.html

JMS
źródło
To właśnie spowodowało, że moja praca w Cron zakończyła się niepowodzeniem przez ostatni tydzień. W końcu zorientowałem się, że moja randka nie ma postaci ucieczki (odwrotny ukos dla innych osób szukających tego, czym jest postać ucieczki). Tak!
Valien
25

Cron wywołuje skrypt, który nie jest wykonywalny.

Po uruchomieniu chmod +x /path/to/scripskrypt staje się wykonywalny i powinien rozwiązać ten problem.

jet
źródło
5
Nie jest to unikalne croni łatwe do zidentyfikowania, po prostu próbując wykonać /path/to/scriptz wiersza poleceń.
Adam Matan
4
Jeśli jesteś przyzwyczajony do wykonywania skryptów przy pomocy . scriptnamelub sh scriptnamelub bash scriptname, wtedy staje się to cronproblemem specyficznym.
Eliah Kagan
24

Możliwe jest również, że hasło użytkownika wygasło. Nawet hasło roota może wygasnąć. Możesz, tail -f /var/log/cron.loga zobaczysz, że cron się nie powiedzie, a hasło wygasło. Możesz ustawić hasło, aby nigdy nie wygasało, wykonując następujące czynności:passwd -x -1 <username>

W niektórych systemach (Debian, Ubuntu) logowanie do crona nie jest domyślnie włączone. W /etc/rsyslog.conf lub /etc/rsyslog.d/50-default.conf wiersz:

# cron.*                          /var/log/cron.log

należy edytować ( sudo nano /etc/rsyslog.conf) bez komentarza w:

cron.*                          /var/log/cron.log

Następnie musisz zrestartować rsyslog przez

/etc/init.d/rsyslog restart

lub

service rsyslog restart 

Źródło: Włącz rejestrowanie crontab w Debianie Linux

W niektórych systemach (Ubuntu) osobny plik rejestrowania dla crona nie jest domyślnie włączony, ale dzienniki związane z cronem pojawiają się w pliku syslog. Można użyć

cat /var/log/syslog | grep cron -i

aby wyświetlić wiadomości związane z cronem.

nieznanych
źródło
Mam Debiana (wheezy), ale nie ma /etc/init.d/rsyslog, tylko inetutils-syslogd i sysklogd. Czy muszę coś zainstalować, czy po prostu zrestartować jeden z dwóch?
hgoebl
18

Jeśli twój kronikarze wywołuje aplikacje GUI, musisz powiedzieć im, jakiego WYŚWIETLACZA powinni użyć.

Przykład: uruchomienie Firefoksa z cronem.

Twój skrypt powinien export DISPLAY=:0gdzieś zawierać .

andrew
źródło
aplay potrzebował tego z jakiegoś powodu. dziękuję
IljaBek
* * * * * export DISPLAY=:0 && <command>
LoMaPh
15

Problemy z uprawnieniami są dość powszechne, obawiam się.

Zauważ, że powszechnym obejściem jest wykonywanie wszystkiego przy użyciu crontab roota, co czasami jest naprawdę złym pomysłem. Ustawienie odpowiednich uprawnień jest zdecydowanie pomijanym problemem.

użytkownik9521
źródło
Zauważ, że jeśli masz linię crontab ustawioną na wyjście potoku do pliku, który jeszcze nie istnieje, a katalogiem pliku jest ten, do którego użytkownik cron nie ma dostępu, to linia nie zostanie wykonana.
Evan Donovan,
14

Niepewne uprawnienia do tabeli cron

Tabela cron jest odrzucana, jeśli jej uprawnienia są niepewne

sudo service cron restart
grep -i cron /var/log/syslog|tail -2
2013-02-05T03:47:49.283841+01:00 ubuntu cron[49906]: (user) INSECURE MODE (mode 0600 expected) (crontabs/user)

Problem został rozwiązany

# correct permission
sudo chmod 600 /var/spool/cron/crontabs/user
# signal crond to reload the file
sudo touch /var/spool/cron/crontabs
John Peterson
źródło
Najpierw sam to wymyśliłem, a potem znalazłem twoją odpowiedź! Nadal wielkie dzięki! W moim przypadku przywróciłem / przywróciłem niektóre tabele crontab w / var / spool / cron / crontabs przez SVN, które zmieniły jego uprawnienia!
alfonx
12

Skrypt jest wrażliwy na lokalizację. Jest to związane z zawsze stosowaniem bezwzględnych ścieżek w skrypcie, ale nie do końca tak samo. Twoje zadanie cron może wymagać cdprzejścia do określonego katalogu przed uruchomieniem, np. Zadanie prowizji w aplikacji Rails może być konieczne w katalogu głównym aplikacji, aby Rake mógł znaleźć właściwe zadanie, nie wspominając o odpowiedniej konfiguracji bazy danych itp.

Więc wpis w crontabie

23 3 * * * /usr/bin/rake db:session_purge RAILS_ENV=production

byłoby lepiej jak

23 3 * * * cd / var / www / production / current && / usr / bin / rake db: session_purge RAILS_ENV = produkcja

Lub, aby zachować prostsze i mniej kruche zapisywanie pliku crontab:

23 3 * * * /home/<user>/scripts/session-purge.sh

z następującym kodem w /home/<user>/scripts/session-purge.sh:

cd / var / www / production / current
/ usr / bin / rake db: session_purge RAILS_ENV = produkcja
pjmorse
źródło
1
Jeśli skrypt wywoływany z crona jest napisany w interpretowanym języku, takim jak PHP, może być konieczne ustawienie katalogu roboczego w samym skrypcie. Na przykład w PHP: chdir(dirname(__FILE__));
Evan Donovan
Właśnie zostałem złapany na tym: skrypt był w katalogu głównym mojego katalogu domowego, ale potem go przeniosłem (i zaktualizowałem crontab) i nie mogłem zrozumieć, dlaczego nie działa. Okazuje się, że skrypt używał ścieżki względnej, zakładając, że był on względny względem lokalizacji skryptu, ale w rzeczywistości był względny względem katalogu głównego mojego katalogu domowego, ponieważ był to katalog roboczy, którego używał cron, i dlatego skrypt działało, gdy znajdowało się w katalogu głównym mojego katalogu domowego (ponieważ oczekiwany katalog roboczy skryptu i jego faktyczne działanie właśnie się zbiegły).
Micheal Johnson
11

Specyfikacje Crontab, które działały w przeszłości, mogą ulec uszkodzeniu podczas przenoszenia z jednego pliku crontab do drugiego. Czasami powodem jest przeniesienie specyfikacji z systemowego pliku crontab do pliku crontab użytkownika lub odwrotnie.

Format specyfikacji zadania cron różni się między plikami crontab użytkowników (/ var / spool / cron / nazwa użytkownika lub / var / spool / cron / crontabs / nazwa użytkownika) i crontabs systemu ( /etc/crontabi pliki w /etc/cron.d).

Crontabs systemowe mają dodatkowe pole „użytkownik” bezpośrednio przed uruchomieniem komendy.

Spowoduje to błędy stwierdzające np. george; command not foundPrzeniesienie polecenia z /etc/crontablub pliku /etc/cron.ddo pliku crontab użytkownika.

I odwrotnie, cron będzie dostarczał błędy podobne /usr/bin/restartxyz is not a valid usernamelub podobne, gdy nastąpi odwrotność.

pbr
źródło
10

skrypt cron wywołuje polecenie z opcją --verbose

Miałem awarię skryptu cron, ponieważ byłem w trybie autopilota podczas pisania skryptu i zawarłem opcję --verbose:

#!/bin/bash
some commands
tar cvfz /my/archive/file.tar.gz /my/shared/directory
come more commands

Skrypt działał poprawnie podczas wykonywania z powłoki, ale nie powiódł się podczas uruchamiania z crontab, ponieważ pełne dane wyjściowe przechodzą do standardowego wyjścia przy uruchamianiu z powłoki, ale nigdzie przy uruchamianiu z crontab. Łatwa naprawa, aby usunąć „v”:

#!/bin/bash
some commands
tar cfz /my/archive/file.tar.gz /my/shared/directory
some more commands
Aaron Peart
źródło
5
Dlaczego powoduje to awarię? Problemy z buforem?
Adam Matan
Wszelkie dane wyjściowe lub błędy uruchamiane przez zadania crona będą wysyłane do Twojej skrzynki pocztowej, więc nigdy nie powinniśmy zapominać o tych błędach / danych wyjściowych. Możemy przekierować je do dowolnego pliku lub / dev / null
Nischay
10

Najczęstszy powód, dla którego widziałem niepowodzenie crona w niepoprawnie określonym harmonogramie. Praktyka wymaga określenia zadania zaplanowanego na 23:15 15 23 * * *zamiast * * 11 15 *lub 11 15 * * *. Dzień tygodnia dla prac po północy też się myli MF jest 2-6po północy, nie 1-5. Określone daty są zwykle problemem, ponieważ rzadko ich używamy, nie * * 3 1 *jest 3 marca. Jeśli nie jesteś pewien, sprawdź harmonogramy cron online pod adresem https://crontab.guru/ .

Jeśli praca z różnymi platformami przy użyciu nieobsługiwanych opcji, takich jak 2/3specyfikacje czasowe, może również powodować awarie. Jest to bardzo przydatna opcja, ale nie jest powszechnie dostępna. Mam również problemy z listami takimi jak 1-5lub 1,3,5.

Korzystanie z niekwalifikowanych ścieżek również spowodowało problemy. Domyślna ścieżka to zwykle, /bin:/usr/binwięc uruchamiane będą tylko standardowe polecenia. Te katalogi zwykle nie mają żądanego polecenia. Wpływa to również na skrypty używające niestandardowych poleceń. Mogą również brakować innych zmiennych środowiskowych.

Całkowite przeszukanie istniejącego crontabu sprawiło mi problemy. Teraz ładuję z kopii pliku. Można to odzyskać z istniejącego pliku crontab za pomocącrontab -l jeśli zostanie zablokowany. Trzymam kopię crontab w ~ / bin. Jest komentowany i kończy się linią # EOF. To jest przeładowywane codziennie z pozycji crontab, takiej jak:

#! / usr / bin / crontab
# Załaduj ponownie ten crontab
#
54 12 * * * $ {HOME} / bin / crontab

Powyższe polecenie przeładowania opiera się na wykonywalnym pliku crontab z ścieżką hukową uruchomioną w pliku crontab. Niektóre systemy wymagają uruchomienia polecenia crontab w poleceniu i podania pliku. Jeśli katalog jest udostępniany w sieci, często używam go crontab.$(hostname)jako nazwy pliku. To ostatecznie usunie przypadki, w których niewłaściwy plik crontab zostanie załadowany na niewłaściwy serwer.

Użycie pliku zapewnia kopię zapasową pliku crontab i pozwala na tymczasowe modyfikacje (tylko raz używam crontab -e automatyczne wycofanie ). Dostępne są nagłówki, które pomagają w prawidłowym ustawieniu parametrów planowania. Dodałem je, gdy niedoświadczeni użytkownicy będą edytować plik crontab.

Rzadko natrafiłem na polecenia wymagające danych wejściowych użytkownika. Te zawodzą pod crontabem, chociaż niektóre będą działać z przekierowaniem danych wejściowych.

BillThor
źródło
3
Obejmuje to trzy osobne problemy. Czy można je podzielić na osobne odpowiedzi?
Eliah Kagan
9
Czy możesz wyjaśnić, jak to 30 23 * * * tłumaczy do 23:15?
JYelton
@JYelton To było oczywiście złe, powinno być 15 23 * * *. Poprawione teraz.
Melebius
7

Jeśli uzyskujesz dostęp do konta za pomocą kluczy SSH, możesz zalogować się na konto, ale nie zauważyć, że hasło do konta jest zablokowane (np. Z powodu wygaśnięcia lub niepoprawnych prób hasła)

Jeśli system używa PAM, a konto jest zablokowane, może to uniemożliwić uruchomienie usługi cronjob. (Przetestowałem to na Solarisie, ale nie na Ubuntu)

Takie wiadomości możesz znaleźć w / var / adm / messages:

24 października 07:51:00 mybox cron [29024]: [ID 731128 autoryzacja] pam_unix_account: cron próbuje zweryfikować zablokowanego konta użytkownika z lokalnego hosta
24 października 07:52:00 mybox cron [29063]: [ID 731128 auth.notice] pam_unix_account: cron próbuje zweryfikować użytkownika zablokowanego konta z lokalnego hosta
24 października 07:53:00 mybox cron [29098]: [ID 731128 auth.notice] pam_unix_account: cron próbuje zweryfikować użytkownika zablokowanego konta z lokalnego hosta
24 października 07:54:00 mybox cron [29527]: [ID 731128 autoryzacja] pam_unix_account: cron próbuje zweryfikować zablokowanego konta użytkownika z lokalnego hosta

Wszystko, co musisz zrobić, to uruchomić:

# passwd -u <NAZWA UŻYTKOWNIKA>

jako root, aby odblokować konto, a crontab powinien znów działać.

JohnGH
źródło
7

Jeśli masz takie polecenie:

* * * * * /path/to/script >> /tmp/output

i nie działa i nie widać żadnych danych wyjściowych, niekoniecznie musi to oznaczać, że cron nie działa. Skrypt może zostać uszkodzony, a wynik przechodzi do stderr, który nie jest przekazywany do / tmp / output. Sprawdź, czy tak nie jest, przechwytując również te dane wyjściowe:

* * * * * /path/to/script >> /tmp/output 2>&1

aby sprawdzić, czy to pomoże Ci rozwiązać problem.

Philluminati
źródło
3

=== Alert Docker ===

Jeśli używasz dokera,

Myślę, że warto dodać, że nie udało mi się sprawić, aby cron działał w tle.

Aby uruchomić zadanie CRON w kontenerze, użyłem nadzorcy i uruchomiłem cron -frazem z innym procesem.

Edycja: Kolejny problem - nie udało mi się również uruchomić go podczas uruchamiania kontenera z siecią HOST. Zobacz ten problem tutaj również: https://github.com/phusion/baseimage-docker/issues/144

AlonL
źródło
3

Pisałem skrypt powłoki instalacyjnej, który tworzy kolejny skrypt usuwający stare dane transakcji z bazy danych. W ramach zadania musiała skonfigurować codzienne cronzadanie do uruchomienia w dowolnym momencie, gdy obciążenie bazy danych było niskie.

Utworzyłem plik mycronjobz harmonogramem cron, nazwą użytkownika i poleceniem i skopiowałem go do /etc/cron.dkatalogu. Moje dwie gotcha:

  1. mycronjob plik musiał być własnością roota, aby uruchomić
  2. Musiałem ustawić uprawnienia do pliku na 644 - 664 nie działało.

Problem z uprawnieniami pojawi się /var/log/syslogjako coś podobnego do:

Apr 24 18:30:01 ip-11-22-33-44 cron[40980]: (*system*) INSECURE MODE (group/other writable) (/etc/crontab)
Apr 24 18:30:01 ip-11-22-33-44 cron[40980]: (*system*) INSECURE MODE (group/other writable) (/etc/cron.d/user)

Pierwszy wiersz odnosi się do /etc/crontabpliku, a później do pliku, pod którym umieściłem /etc/cront.d.

Izik Golan
źródło
2

Linia napisana w sposób, którego crontab nie rozumie. To musi być poprawnie napisane. Oto CrontabHowTo .

Kangarooo
źródło
1
Jak można to debugować?
Adam Matan
Przeglądanie dziennika błędów crona jest najczęstszym sposobem. IIRC „crontab -e” wykonuje również analizę składni po edycji pliku - ale to może nie być uniwersalne.
pbr
2

Demon Cron może być uruchomiony, ale w rzeczywistości nie działa. Spróbuj zrestartować crona:

sudo /etc/init.d/cron restart
Phil Dodd
źródło
3
NIGDY nie widziałem tego przypadku w produkcji. Nie znaczy to, że tak się nie stało - po prostu to, że nie widziałem tego przez 30 lat używania UNIX i Linux. Cron jest niesamowicie solidny.
pbr
1
Nie jestem pewien, ale myślę, że tak się właśnie stało. Spróbowałem pidofcrona i nic nie dostałem. Próbowałem użyć servicenarzędzia i powiedziałem, że cron już działa. Po prostu uruchomiłem to polecenie i uruchomiłem pidofponownie, a otrzymuję wynik.
Colleen,
2

Zapis do crona przez „crontab -e” z argumentem nazwy użytkownika w linii. Widziałem przykłady użytkowników (lub sysadminów) piszących swoje skrypty powłoki i nie rozumiejących, dlaczego nie automatyzują. Argument „użytkownik” istnieje w / etc / crontab, ale nie w plikach zdefiniowanych przez użytkownika. na przykład twój plik osobisty wyglądałby tak:

# m h dom mon dow command

* * */2  *   *  /some/shell/script

podczas gdy / etc / crontab to:

# m h dom mon dow user   command

* * */2  *   *  jdoe   /some/shell/script

Dlaczego więc zrobiłbyś to drugie? W zależności od tego, jak chcesz ustawić swoje uprawnienia, może to być bardzo skomplikowane. Napisałem skrypty do automatyzacji zadań dla użytkowników, którzy nie rozumieją zawiłości lub nie chcą zawracać sobie głowy nudą. Ustawiając uprawnienia na --x------, mogę sprawić, że skrypt będzie wykonywalny bez ich możliwości odczytu (i być może przypadkowej zmiany). Mogę jednak chcieć uruchomić to polecenie z kilkoma innymi z jednego pliku (ułatwiając w ten sposób utrzymanie), ale upewnij się, że dane wyjściowe pliku mają przypisanego właściwego właściciela. Takie postępowanie (przynajmniej w Ubuntu 10.10) zakłóca zarówno niemożność odczytania pliku, jak i jego wykonania, a także wspomniany wcześniej problem z umieszczaniem kropek w / etc / crontab (co, co zabawne, nie powoduje błędów podczas przejścia crontab -e) .

Jako przykład widziałem przypadki sudo crontab -eużycia skryptu z uprawnieniami roota, z odpowiednim chown username file_outputw skrypcie powłoki. Niechlujny, ale działa. IMHO, bardziej wdzięczną opcją jest umieszczenie go /etc/crontabz zadeklarowaną nazwą użytkownika i odpowiednimi uprawnieniami, więc file_outputtrafia we właściwe miejsce i właściciela.

Mange
źródło
„Robiąc to (przynajmniej w Ubuntu 10.10) narusza zarówno niemożność odczytania pliku, jak i wykonania ..... Powinienem wyjaśnić: / etc / crontab (domyślnie) wymaga uprawnień do odczytu ORAZ wykonania, podczas gdy MUSISZ uruchom „sudo crontab -e”, aby utworzyć cronjob, który zastępuje zarówno potrzebę uprawnienia „w”, jak i problem z rozszerzeniami, takimi jak „.sh”. Nie miałem czasu rozbierać kodu crona i sprawdzać, dlaczego to działa, tylko szczegół, który zauważyłem.
Mange
2

Opierając się na tym, o czym wspomniał Aaron Peart na temat trybu pełnego, czasami skrypty nie w trybie pełnym są inicjalizowane, ale nie kończą się, jeśli domyślnym zachowaniem zawartej komendy jest wyświetlanie linii lub więcej na ekranie po uruchomieniu proc. Na przykład napisałem skrypt kopii zapasowej dla naszego intranetu, który używał curl, narzędzia, które pobiera lub przesyła pliki na zdalne serwery, i jest całkiem przydatne, jeśli możesz uzyskać dostęp do tych zdalnych plików tylko przez HTTP. Użycie „curl http://something.com/somefile.xls ” spowodowało, że skrypt, który napisałem, zawiesił się i nigdy nie ukończył, ponieważ wyrzuca nowy wiersz, po którym następuje linia postępu. Musiałem użyć cichej flagi (-s), aby powiedzieć jej, aby nie wyświetlała żadnych informacji, i napisać własny kod, aby obsłużyć, jeśli pobieranie pliku nie powiedzie się.

Świerzb
źródło
1
W przypadku programów, które nie mają trybu cichego, możesz przekierować ich wyjście /dev/null. Na przykład: some-command > /dev/nullprzekieruje tylko standardowe wyjście, a nie wyjście błędu (co zwykle jest tym, czego chcesz, ponieważ chcesz być informowany o błędach). Aby przekierować również wyjście błędu, użyj some-command &> /dev/null.
Eliah Kagan
Tak, to była moja pierwsza myśl podczas pisania wyżej wspomnianego skryptu. Zapominam, dlaczego tego nie użyłem, być może jakieś niestandardowe zachowanie, które omijało to rozwiązanie. Wiem, że tryb pełnych / interaktywnych trybów domyślnych jest domyślny w niektórych poleceniach (patrzę na Ciebie, scp!), Co oznacza, że ​​musisz zepsuć dane wyjściowe, aby zapewnić płynne działanie skryptów powłoki.
Mange,
2

Chociaż możesz definiować zmienne środowiskowe w swoim crontable, nie jesteś w skrypcie powłoki. Zatem konstrukcje takie jak poniższe nie będą działać:

SOME_DIR=/var/log
MY_LOG_FILE=${SOME_LOG}/some_file.log

BIN_DIR=/usr/local/bin
MY_EXE=${BIN_DIR}/some_executable_file

0 10 * * * ${MY_EXE} some_param >> ${MY_LOG_FILE}

Wynika to z faktu, że zmienne nie są interpretowane w tabeli crontable: wszystkie wartości są przyjmowane literalnie. I to samo, jeśli pominiesz nawiasy. Twoje polecenia nie będą działać, a pliki dziennika nie zostaną zapisane ...

Zamiast tego musisz zdefiniować wszystkie zmienne środowiskowe prosto:

SOME_DIR=/var/log
MY_LOG_FILE=/var/log/some_file.log

BIN_DIR=/usr/local/bin
MY_EXE=/usr/local/bin/some_executable_file

0 10 * * * ${MY_EXE} some_param >> ${MY_LOG_FILE}
Alexandre
źródło
2

Kiedy zadanie jest uruchamiane w cronie, standardowe wejście jest zamknięte. Programy, które działają inaczej w zależności od tego, czy standardowe wejście jest dostępne, czy nie, będą zachowywać się inaczej w sesji powłoki i w cronie.

Przykładem jest program goaccessdo analizy plików dziennika serwera WWW. To NIE działa w cronie:

goaccess -a -f /var/log/nginx/access.log > output.html

i goaccesspokazuje stronę pomocy zamiast tworzenia raportu. W skorupce można to odtworzyć za pomocą

goaccess -a -f /var/log/nginx/access.log > output.html < /dev/null

Rozwiązaniem goaccessjest zmusić go do odczytu dziennika ze standardowego wejścia zamiast odczytu z pliku, więc rozwiązaniem jest zmiana wpisu crontab na

cat /var/log/nginx/access.log | goaccess -a > output.html
Martijn de Milliano
źródło
2

W moim przypadku cron i crontab mieli różnych właścicieli.

NIE działa Miałem to:

User@Uva ~ $ ps -ef | grep cron | grep -v grep
User    2940    7284 pty1     19:58:41 /usr/bin/crontab
SYSTEM   11292     636 ?        22:14:15 /usr/sbin/cro 

Zasadniczo musiałem uruchomić cron-config i poprawnie odpowiedzieć na pytania. Jest punkt, w którym musiałem wprowadzić hasło użytkownika Win7 do mojego konta „Użytkownik”. Po przeczytaniu zrobiłem, wygląda na to, że jest to potencjalny problem bezpieczeństwa, ale jestem jedynym administratorem w jednej sieci domowej, więc zdecydowałem, że jest OK.

Oto sekwencja poleceń, która mnie uruchomiła:

User@Uva ~ $ cron-config
The cron daemon can run as a service or as a job. The latter is not recommended.
Cron is already installed as a service under account LocalSystem.
Do you want to remove or reinstall it? (yes/no) yes
OK. The cron service was removed.

Do you want to install the cron daemon as a service? (yes/no) yes
Enter the value of CYGWIN for the daemon: [ ] ntsec

You must decide under what account the cron daemon will run.
If you are the only user on this machine, the daemon can run as yourself.
   This gives access to all network drives but only allows you as user.
To run multiple users, cron must change user context without knowing
  the passwords. There are three methods to do that, as explained in
  http://cygwin.com/cygwin-ug-net/ntsec.html#ntsec-nopasswd1
If all the cron users have executed "passwd -R" (see man passwd),
  which provides access to network drives, or if you are using the
  cyglsa package, then cron should run under the local system account.
Otherwise you need to have or to create a privileged account.
  This script will help you do so.
Do you want the cron daemon to run as yourself? (yes/no) no

Were the passwords of all cron users saved with "passwd -R", or
are you using the cyglsa package ? (yes/no) no

Finding or creating a privileged user.
The following accounts were found: 'cyg_server' .
This script plans to use account cyg_server.
Do you want to use another privileged account name? (yes/no) yes
Enter the other name: User

Reenter: User


Account User already exists. Checking its privileges.
INFO: User is a valid privileged account.
INFO: The cygwin user name for account User is User.

Please enter the password for user 'User':
Reenter:
Running cron_diagnose ...
... no problem found.

Do you want to start the cron daemon as a service now? (yes/no) yes
OK. The cron daemon is now running.

In case of problem, examine the log file for cron,
/var/log/cron.log, and the Windows event log (using /usr/bin/cronevents)
for information about the problem cron is having.

Examine also any cron.log file in the HOME directory
(or the file specified in MAILTO) and cron related files in /tmp.

If you cannot fix the problem, then report it to [email protected].
Please run the script /usr/bin/cronbug and ATTACH its output
(the file cronbug.txt) to your e-mail.

WARNING: PATH may be set differently under cron than in interactive shells.
         Names such as "find" and "date" may refer to Windows programs.


User@Uva ~ $ ps -ef | grep cron | grep -v grep
    User    2944   11780 ?        03:31:10 /usr/sbin/cron
    User    2940    7284 pty1     19:58:41 /usr/bin/crontab

User@Uva ~ $
KiloOne
źródło
1
Chociaż dobrze udokumentowane, wygląda to na punkt specyficzny dla Cygwina; czy to naprawdę należy do askubuntu?
sxc731,
2

Na moich serwerach RHEL7 działałyby zadania root cron, ale zadania użytkownika nie. Odkryłem, że bez katalogu domowego zadania nie będą działać (ale zobaczysz dobre błędy w / var / log / cron). Kiedy utworzyłem katalog domowy, problem został rozwiązany.

Dennis Parslow
źródło
2

Jeśli edytujesz plik crontab przy użyciu edytora systemu Windows (przez sambę lub coś takiego) i zastąpiono go nowymi wierszami \ n \ r lub po prostu \ r, cron nie uruchomi się.

Ponadto, jeśli używasz /etc/cron.d/* i jeden z tych plików zawiera \ r, cron będzie przechodził między plikami i zatrzyma się, gdy trafi na zły plik. Nie jesteś pewien, czy to jest problem?

Posługiwać się:

od -c /etc/cron.d/* | grep \r
Doug
źródło