Jak utworzyć tabelę crontab za pomocą skryptu

153

Muszę dodać zadanie cron za pośrednictwem skryptu, który uruchamiam, aby skonfigurować serwer. Obecnie używam Ubuntu. Mogę użyć, crontab -eale to otworzy edytor do edycji bieżącej tabeli crontab. Chcę to zrobić programowo.

Czy można to zrobić?

gaurav
źródło
Jeśli chcesz zmodyfikować lub usunąć wpis crontab, zobacz moje rozwiązanie poniżej.
Brian Smith

Odpowiedzi:

11

Zadania Cron są zwykle przechowywane w pliku dla użytkownika w lokalizacji /var/spool/cron

Najprostszą rzeczą do zrobienia jest prawdopodobnie utworzenie pliku tekstowego ze skonfigurowanym zadaniem, a następnie skopiowanie go do folderu buforowania cron i upewnienie się, że ma odpowiednie uprawnienia (600).

Jason Stelzer
źródło
20
Modyfikowanie plików bezpośrednio w / var / spool / cron nie jest mile widziane. W rzeczywistości, jeśli spojrzysz na tamte pliki, zazwyczaj zawierają one ostrzeżenia, takie jak „NIE EDYTUJ TEGO PLIKU” w pierwszym wierszu.
Jared
12
@Jared Chociaż całkiem zgadzam się z tym pomysłem, stwierdzenie, że jest on „źle widziany”, niewiele pomaga. Zamiast tego powiedz, który inny plik powinien być edytowany, jeśli w ogóle, lub wyjaśnij ryzyko ręcznej edycji plików. Planuję stworzyć kilka zadań crona za pomocą zautomatyzowanego wiersza poleceń, a jeśli edycja tego pliku jest jedyną opcją i bez znaczących skutków ubocznych, nie rozumiem, dlaczego nie powinienem go używać.
Balmipour
47
Przewiń w dół, aby uzyskać prawdziwą odpowiedź.
John Red
1
Moim zdaniem ta odpowiedź jest o wiele lepsza: stackoverflow.com/a/610860/2681752
galaux
2
Przyjąłem takie podejście i żałowałem. Na RHEL katalog / var / spool / cron nie jest wykonywalny dla wszystkich, więc użytkownicy nie mogą przechodzić przez katalog i ręcznie edytować swoich plików. Jeśli sprawisz, że / var / spool / cron world będzie wykonywalny, twój przyjazny lokalny administrator będzie na ciebie zły, a zmiana uprawnień może zostać nadpisana, jeśli pakiet cronie zostanie kiedykolwiek ponownie zainstalowany lub zaktualizowany.
functionvoid
384

Oto jedna linijka, która nie używa / nie wymaga, aby nowe zadanie znajdowało się w pliku:

(crontab -l 2>/dev/null; echo "*/5 * * * * /path/to/job -with args") | crontab -

Jest 2>/dev/nullto ważne, aby nie otrzymać no crontab for usernamekomunikatu, który generują niektóre * nixy, jeśli obecnie nie ma żadnych wpisów w tabeli crontab.

Joe Casadonte
źródło
14
To powinna być akceptowana odpowiedź. Potrzebuję teraz sposobu, aby sprawdzić, czy jeden liniowiec, który zamierzam dodać, już tam jest, czy nie ...
ChrisPrime,
7
... och, czekaj, oto jak sprawdzić, czy coś jest w crontab mojego użytkownika, zanim dodam to za pomocą skryptu: stackoverflow.com/a/14451184/3686125
ChrisPrime,
1
jeśli ten skrypt ma być poleceniem do powtórzenia i zmodyfikowania istniejącego zadania crona, fajnie byłoby zastąpić istniejącą linię w crontab. kilka markerów może być używanych do sterowania różnymi zadaniami cron (control-marker-1, control-marker-2, itd ...): (crontab -l 2> / dev / null | grep -v control-marker-1; echo '* / 5 * * * * / path / to / job-with args # control-marker-1') | crontab -
szef kuchni,
7
Okazało się, że powodowało to usunięcie istniejących wpisów crontab, a także musiałem użyć innego użytkownika (root), więc użyłem następujących elementów, aby zachować istniejące wpisy: echo -e "$(sudo crontab -u root -l)\n* * * * * echo hello > /home/danny/temp.log 2>&1" | sudo crontab -u root -Mam nadzieję, że to komuś pomoże
Danny
60

W przypadku plików crontab użytkownika (w tym roota) możesz zrobić coś takiego:

crontab -l -u user | cat - filename | crontab -u user -

gdzie plik o nazwie „filename” zawiera elementy do dołączenia. Możesz także manipulować tekstem za pomocą sedlub innego narzędzia zamiast cat. Powinieneś użyć crontabpolecenia zamiast bezpośrednio modyfikować plik.

Podobna operacja wyglądałaby tak:

{ crontab -l -u user; echo 'crontab spec'; } | crontab -u user -

Jeśli modyfikujesz lub tworzysz systemowe tabele crontab, można nimi manipulować jak zwykłymi plikami tekstowymi. Są one przechowywane w /etc/cron.d, /etc/cron.hourly, /etc/cron.daily, /etc/cron.weekly, /etc/cron.monthlykatalogów i plików w /etc/crontabi /etc/anacrontab.

Wstrzymano do odwołania.
źródło
Wyglądało to obiecująco, ale próbując drugiego podejścia (z echo), otrzymałem „crontab: błąd użycia: należy określić nazwę pliku do zastąpienia”. Strona podręcznika Cron przedstawia składnię jako crontab [ -u user ] file, to znaczy z obowiązkową nazwą pliku. Czy jest jakaś sztuczka, aby zamiast tego zaakceptować dane z potoku?
Mark Berry,
1
@MarkBerry: Przepraszam za to. W potoku należy użyć łącznika, aby wskazać, że dane wejściowe pochodzą z stdin. Poprawię swoją odpowiedź.
Wstrzymano do odwołania.
29

W Ubuntu i wielu innych dystrybucjach możesz po prostu umieścić plik w /etc/cron.dkatalogu zawierającym pojedynczą linię z prawidłowym wpisem w tabeli crontab . Nie ma potrzeby dodawania linii do istniejącego pliku.

Jeśli potrzebujesz czegoś do codziennego uruchamiania, po prostu umieść plik w /etc/cron.daily. Podobnie, można również upuszczać pliki /etc/cron.hourly, /etc/cron.monthlyoraz /etc/cron.weekly.

IvanGoneKrazy
źródło
5
Ale aby to zrobić, musisz być rootem.
Keith
17

Jeszcze prostsza odpowiedź na twoje pytanie brzmiałaby:

echo "0 1 * * * /root/test.sh" | tee -a /var/spool/cron/root

Możesz skonfigurować cronjobs na zdalnych serwerach, jak poniżej:

#!/bin/bash
servers="srv1 srv2 srv3 srv4 srv5"
for i in $servers
  do
  echo "0 1 * * * /root/test.sh" | ssh $i " tee -a /var/spool/cron/root"
done

W systemie Linux domyślną lokalizacją crontabpliku jest /var/spool/cron/. Tutaj możesz znaleźć crontabpliki wszystkich użytkowników. Wystarczy, że dołączysz swój wpis cronjob do pliku odpowiedniego użytkownika. W powyższym przykładzie plik crontab użytkownika root jest dodawany do pliku cronjob, aby był uruchamiany /root/test.shcodziennie o 1 w nocy .

ganesh pathak
źródło
To byłoby /var/spool/cron/crontabs/rootna Ubuntu.
Íhor Mé
17

Pliki Crontab są po prostu plikami tekstowymi i jako takie mogą być traktowane jak każdy inny plik tekstowy. Celemcrontab polecenia jest zwiększenie bezpieczeństwa edycji plików crontab. Podczas edycji za pomocą tego polecenia plik jest sprawdzany pod kątem błędów i zapisywany tylko wtedy, gdy ich nie ma.

crontab [path to file]można użyć do określenia tabeli crontab przechowywanej w pliku. Lubićcrontab -e spowoduje to zainstalowanie pliku tylko wtedy, gdy jest wolny od błędów.

Dlatego skrypt może bezpośrednio zapisywać pliki kart cron lub zapisywać je do pliku tymczasowego i ładować je za pomocą crontab [path to temp file]polecenia. Bezpośrednie pisanie oszczędza konieczności zapisywania pliku tymczasowego, ale także pozwala uniknąć kontroli bezpieczeństwa.

cledoux
źródło
2
Dla noobów takich jak ja, zwróć uwagę, że tak jest crontab [path to file]… To była zdecydowanie najlepsza opcja dla mnie, ponieważ pozwala na bardziej czytelny kod. Używam crontab do śledzenia paczek i zmiany tapety pulpitu ze statusem. Kiedy nie spodziewam się paczek, nie muszę sprawdzać co godzinę. Dlatego chciałem, aby skrypt automatycznie edytować częstotliwość cron.
Rasmus
1
@Rasmus To brzmi jak niesamowity scenariusz, który chciałbym móc ukraść. Czy jest jakaś szansa na udostępnienie w formie streszczenia lub czegoś podobnego?
cledoux
8

(Nie mam wystarczającej reputacji, aby komentować, więc dodaję jako odpowiedź: możesz dodać to jako komentarz obok jego odpowiedzi)

Jednowierszowa wersja Joe Casadonte jest doskonała, z wyjątkiem sytuacji, gdy uruchamiasz z set -e, tj. Jeśli twój skrypt jest ustawiony na niepowodzenie przy błędzie i jeśli nie ma jeszcze cronjobów. W takim przypadku jednowierszowy NIE utworzy cronjob, ale NIE zatrzyma skryptu. Cicha porażka może być bardzo myląca.

Powodem jest to, że crontab -lpowraca z 1kodem powrotu, powodując, że kolejne polecenie (the echo) nie jest wykonywane ... w ten sposób cronjob nie jest tworzony. Ale ponieważ są wykonywane jako podproces (z powodu nawiasów), nie zatrzymują skryptu.

(Co ciekawe, jeśli ponownie uruchomisz to samo polecenie, zadziała: po wykonaniu crontab -raz crontab -lnadal nic nie wyświetla, ale nie zwraca już błędu (nie otrzymujesz no crontab for <user>już komunikatu). Więc następne echojest wykonywane i tworzony jest plik crontab)

W każdym razie, jeśli biegniesz z set -e, linia musi być:

(crontab -l 2>/dev/null || true; echo "*/5 * * * * /path/to/job -with args") | crontab -
Faria
źródło
Tak, ten jest jeszcze doskonalszy.
Yngve Sneen Lindal
7

Jako korekta tych sugestii crontab -l | crontab -: To nie działa na każdym systemie. Na przykład musiałem dodać zadanie do katalogu głównego crontab na dziesiątkach serwerów ze starą wersją SUSE (nie pytaj dlaczego). Stare SUSE dodają wiersze komentarzy na wyjściu programu crontab -l, czyniąc je crontab -l | crontab -nie-idempotentnymi (Debian rozpoznaje ten problem na stronie podręcznika crontab i załatał swoją wersję Vixie Cron, aby zmienić domyślne zachowaniecrontab -l ).

Aby programowo edytować pliki crontab w systemach, w których są crontab -ldodawane komentarze, możesz spróbować wykonać następujące czynności:

EDITOR=cat crontab -e > old_crontab; cat old_crontab new_job | crontab -

EDITOR=cat nakazuje crontabowi użycie cat jako edytora (nie zwykłego domyślnego vi), co nie zmienia pliku, ale zamiast tego kopiuje go na standardowe wyjście. Może to nadal zakończyć się niepowodzeniem, jeśli crontab -oczekuje danych wejściowych w formacie innym niż dane crontab -ewyjściowe. Nie próbuj zastąpić finał crontab -z crontab -e- to nie będzie działać.

user2845840
źródło
4

Cóż, /etc/crontabtylko plik ascii, więc najprościej jest po prostu

 echo "*/15 * * * *   root     date" >> /etc/crontab

który doda ofertę pracy, która będzie wysyłana e-mailem co 15 minut. Dostosuj do smaku i przetestuj przezgrep lub w inny sposób, czy linia została już dodana, aby Twój skrypt był idempotentny.

W Ubuntu i in. Możesz także upuszczać pliki, /etc/cron.*co jest łatwiejsze do zrobienia i przetestowania pod kątem --- plus nie zadzieraj z (systemowymi) plikami konfiguracyjnymi, takimi jak /etc/crontab.

Dirk Eddelbuettel
źródło
1
Myślę, że technicznie crond nie jest wymagany do monitorowania zmian w crontab, nawet jeśli w rzeczywistości robi to większość implementacji, więc poleciłbym później wywołanie crontab -e w celu jego wyprodowania. crontab -e honoruje zmienną EDITOR, jeśli pamięć służy, więc ustawienie jej na / bin / true powinno tylko wymusić ponowne odczytanie pliku crontab.
Ulrich Schwarz
1
Prawda jeszcze na dowolnym systemie Linux niedawnym crond robi monitora, a to na pewno nie na podanej platformie OP.
Dirk Eddelbuettel
Tylko jeśli jesteś rootem i chcesz, aby skrypt działał jako root. Może to nie być pożądane w przypadku PO.
Keith
Nie tak, mam wiele wpisów innych niż root w / etc / crontab. Potrzebujesz „tylko” sudo, aby dołączyć do pliku. W każdym razie, jak już wspomniałem, istnieje również /etc/cron.*/, ale musisz być też rootem, aby tam pisać.
Dirk Eddelbuettel
2

Oto jak zmodyfikować cron wpis bez bezpośredniej edycji pliku cron (co jest niezadowolone).

crontab -l -u <user> | sed 's/find/replace/g' | crontab -u <user> -

Jeśli chcesz usunąć wpis crona, użyj tego:

crontab -l -u <user> | sed '/find/d' | crontab -u <user> -

Zdaję sobie sprawę, że nie o to prosił gaurav, ale dlaczego nie mieć wszystkich rozwiązań w jednym miejscu?

Brian Smith
źródło
1

Napisałem narzędzie do wdrażania crontab w Pythonie: https://github.com/monklof/deploycron

pip install deploycron

Instalacja twojego pliku crontab jest bardzo łatwa, spowoduje to scalenie go z istniejącym plikiem crontab systemu.

from deploycron import deploycron
deploycron(content="* * * * * echo hello > /tmp/hello")
monklof
źródło
1

Jest to podejście polegające na stopniowym dodawaniu zadania cron:

  ssh USER_NAME@$PRODUCT_IP nohup "echo '*/2 * * * * ping -c2 PRODUCT_NAME.com >> /var/www/html/test.html' | crontab -u USER_NAME -"
Oleksii Kyslytsyn
źródło