Jak utworzyć zadanie CRON automatycznie za pomocą Bash bez interaktywnego edytora?

395

Czy crontab ma argument za tworzeniem zadań cron bez użycia edytora (crontab -e). Jeśli tak, to jaki kod stworzyłby cronjob ze skryptu Bash?

Raúl Roa
źródło
5
Niestety, większość najlepszych odpowiedzi tutaj pokazuje tylko, jak modyfikować crontab - choć w dość bezpieczny sposób - ale myślę, że ogólnie jest to złe podejście. Lepszym, bezpieczniejszym i prostszym jest upuszczenie pliku do {{cron.d}}, a istnieją (obecnie) niskie głosy wyjaśniające, jak to zrobić, jeśli spojrzysz w dół.
gregmac,

Odpowiedzi:

539

Możesz dodać do crontab w następujący sposób:

#write out current crontab
crontab -l > mycron
#echo new cron into cron file
echo "00 09 * * 1-5 echo hello" >> mycron
#install new cron file
crontab mycron
rm mycron

Objaśnienie linii Crona

* * * * * "command to be executed"
- - - - -
| | | | |
| | | | ----- Day of week (0 - 7) (Sunday=0 or 7)
| | | ------- Month (1 - 12)
| | --------- Day of month (1 - 31)
| ----------- Hour (0 - 23)
------------- Minute (0 - 59)

Źródło nixCraft .

dogbane
źródło
14
Powinieneś użyć tempfile lub mktemp
Paweł Polewicz
166
(crontab -l; echo "00 09 * * 1-5 echo hello") | crontab -
Edo,
32
(crontab -l ; echo "00 09 * * 1-5 echo hello") | crontab -- łatwiej skopiować kopiowane
ubrania
8
Sugeruję, aby zmienić ;z &&jako bezpieczne-baczności przed przypadku, gdy crontab -lnie powiedzie się. tak jak:(crontab -l && echo "0 0 0 0 0 some entry") | crontab -
MacUsers
12
@MacUsers, crontab -lkończy się niepowodzeniem, jeśli nie ma crontab, więc użycie &&uniemożliwia skryptowi dodanie pierwszego wpisu do crontab.
JPhi1618,
312

Możesz to zrobić w locie

crontab -l | { cat; echo "0 0 0 0 0 some entry"; } | crontab -

crontab -lwyświetla bieżące zadania crontab, catdrukuje je, echodrukuje nowe polecenie i crontab -dodaje wszystkie wydrukowane rzeczy do pliku crontab. Możesz zobaczyć efekt, robiąc nowy crontab -l.

TheBonsai
źródło
3
dzięki, możesz wyjaśnić składnię lub wskazać adres URL, który to wyjaśnia?
witryny
9
crontab -lwyświetla bieżące zadania crontab, catdrukuje je, echodrukuje nowe polecenie i crontab -dodaje wszystkie wydrukowane rzeczy do pliku crontab. Możesz zobaczyć efekt, robiąc nowycrontab -l
nha
3
To dla mnie przyjemność. Jeśli użytkownik nie ma istniejącego pliku crontab, zobaczysz no crontab for <username>, ale i tak działa.
etap
21
nie działa na mojej instancji Amazon EC2. Zamiast tego (crontab -l ; echo "00 09 * * 1-5 echo hello") | crontab -działa.
Stéphane Bruckert
11
To wygląda na kandydata na UUcatA .
ceving
86

Ten krótszy nie wymaga pliku tymczasowego, jest odporny na wiele wstawień i pozwala zmienić harmonogram istniejącego wpisu.

Powiedz, że masz te:

croncmd="/home/me/myfunction myargs > /home/me/myfunction.log 2>&1"
cronjob="0 */15 * * * $croncmd"

Aby dodać go do crontab, bez powielania:

( crontab -l | grep -v -F "$croncmd" ; echo "$cronjob" ) | crontab -

Aby usunąć go z crontab bez względu na aktualny harmonogram:

( crontab -l | grep -v -F "$croncmd" ) | crontab -

Uwagi:

  • grep -F dosłownie dopasowuje ciąg, ponieważ nie chcemy interpretować go jako wyrażenia regularnego
  • Ignorujemy również planowanie czasu i szukamy tylko polecenia. Tą drogą; harmonogram można zmienić bez ryzyka dodania nowej linii do crontab
MoonCactus
źródło
@moeseth: czy możesz opracować?
MoonCactus,
powinieneś spróbować na swoim komputerze
moeseth
2
@moeseth: Oczywiście próbowałem na moim komputerze (Linux). Nie sugerowałbym przypadkowych niedziałających rzeczy: /
MoonCactus
2
Nawiasem mówiąc, 27 osób nie może się mylić (na dzień dzisiejszy). Opisz więc, dlaczego to nie działa w twojej konfiguracji, abyśmy mogli pomóc.
MoonCactus
2
Może to być problem z OSX.
moeseth
40

Dziękuję wszystkim za pomoc. Zestawiając to, co znalazłem tutaj i gdzie indziej, wymyśliłem to:

Kod

command="php $INSTALL/indefero/scripts/gitcron.php"
job="0 0 * * 0 $command"
cat <(fgrep -i -v "$command" <(crontab -l)) <(echo "$job") | crontab -

Nie mogłem wymyślić, jak wyeliminować potrzebę dwóch zmiennych bez powtarzania się.

commandto oczywiście polecenie, które chcę zaplanować. jobtrwa$command i dodaje dane planowania. Potrzebowałem obu zmiennych osobno w wierszu kodu, który działa.

Detale

  1. Podziękowania dla duckyflip, używam tego małego przekierowania thingy ( <(*command*)), aby przekształcić dane wyjściowe crontab -lw dane wejściowe dla plikufgrep polecenia.
  2. fgrepnastępnie odfiltrowuje wszystkie dopasowania $command( -vopcja), bez rozróżniania wielkości liter (-i opcja).
  3. Ponownie, mała rzecz przekierowująca ( <(*command*)) służy do zamiany wyniku z powrotem na dane wejściowe dlacat polecenia.
  4. catPolecenie otrzymuje również echo "$job"(oczywista), również przez zastosowanie tego rodzaju lasera (przekierowania<(*command*) ).
  5. Więc odfiltrowane dane wyjściowe crontab -li proste echo "$job", połączone są przesyłane strumieniowo („|”), aby crontab -w końcu zostać zapisane.
  6. I żyli długo i szczęśliwie!

W skrócie:

Ten wiersz kodu odfiltrowuje wszystkie zadania cron pasujące do polecenia, a następnie wypisuje pozostałe zadania cron z nowym, skutecznie działając jak funkcja „dodaj” lub „zaktualizuj”. Aby tego użyć, wystarczy zamienić wartości zmiennych commandi job.

Stoutie
źródło
5
Zaletą tego podejścia jest to, że można go uruchomić wiele razy, nie martwiąc się o zduplikowane wpisy w pliku crontab (w przeciwieństwie do wszystkich innych rozwiązań). Wynika to zfgrep -v
aleemb
5
Jeśli wolisz tradycyjny sposób crontab -l | fgrep -i -v "$command" | { cat; echo "$job"; } | crontab -l
układania
1
@ AntoineLizée, na końcu odpowiedź zawiera dodatkowe „l”, którego nie powinno być.
Henry
26

EDYCJA (naprawiono nadpisywanie):

cat <(crontab -l) <(echo "1 2 3 4 5 scripty.sh") | crontab -
duckyflip
źródło
Zastąpi to zawartość crontab
TheBonsai
1
@ TheBonsai och, rozumiem, naprawiłem to teraz, więc powinien ZAŁĄCZYĆ nowe polecenie do istniejącej zawartości crontab
duckyflip
3
Pamiętaj, że zastępowanie procesów przez Basha połyka błędy. Jeśli crontab -lzawiedzie, ale się crontab -powiedzie, twój crontab będzie liniowy.
ceving
13

Było wiele dobrych odpowiedzi na temat używania crontab, ale nie wspomniano o prostszej metodzie, takiej jak używanie cron .

Korzystanie cronby skorzystać z systemu plików i katalogów znajdujących się /etc/crontab, /etc/cron.daily,weekly,hourlyczy /etc/cron.d/:

cat > /etc/cron.d/<job> << EOF
SHELL=/bin/bash 
PATH=/sbin:/bin:/usr/sbin:/usr/bin 
MAILTO=root HOME=/  
01 * * * * <user> <command>
EOF

W powyższym przykładzie utworzyliśmy plik w /etc/cron.d/, pod warunkiem, że zmienne środowiskowe dla komendy do pomyślnego wykonania, oraz podaliśmy userkomendę i commandsamą. Ten plik nie powinien być wykonywalny, a nazwa powinna zawierać tylko znaki alfanumeryczne i łączniki (więcej szczegółów poniżej).

Aby udzielić dokładnej odpowiedzi, spójrzmy na różnice między crontabvs cron/crond:

crontab -- maintain tables for driving cron for individual users

Dla tych, którzy chcą uruchomić zadanie w kontekście swojego użytkownika w systemie, użycie crontabmoże mieć sens.

cron -- daemon to execute scheduled commands

Dla tych, którzy używają zarządzania konfiguracją lub chcą zarządzać zadaniami dla innych użytkowników, w takim przypadku powinniśmy skorzystać cron .

Szybki fragment stron podręcznika zawiera kilka przykładów tego, co należy robić, a czego nie robić:

/ etc / crontab i pliki w /etc/cron.d muszą być własnością użytkownika root i nie mogą być zapisywane w grupach ani w inny sposób. W przeciwieństwie do obszaru buforowania pliki w /etc/cron.d lub pliki w /etc/cron.hourly, /etc/cron.daily, /etc/cron.weekly i /etc/cron.monthly dowiązania symboliczne, pod warunkiem, że zarówno dowiązanie symboliczne, jak i plik, na który wskazuje, są własnością użytkownika root. Pliki w /etc/cron.d nie muszą być wykonywalne, podczas gdy pliki w /etc/cron.hourly, /etc/cron.daily, /etc/cron.weekly i /etc/cron.monthly tak, jak są one uruchamiane według części roboczych (więcej informacji można znaleźć w części roboczej (8)).

Źródło: http://manpages.ubuntu.com/manpages/trusty/man8/cron.8.html

Zarządzanie cronami w ten sposób jest łatwiejsze i bardziej skalowalne z perspektywy systemu, ale nie zawsze będzie najlepszym rozwiązaniem.

Mike Mackintosh
źródło
1
Warto wspomnieć, że <job>nie powinno zawierać rozszerzenia pliku.
jww
7

Możliwe, że automatyzujesz to i nie chcesz, aby jedno zadanie zostało dodane dwukrotnie. W takim przypadku użyj:

__cron="1 2 3 4 5 /root/bin/backup.sh"
cat <(crontab -l) |grep -v "${__cron}" <(echo "${__cron}")

Działa to tylko wtedy, gdy używasz BASH. Nie znam prawidłowego DASH (sh składni ).

Aktualizacja: To nie działa, jeśli użytkownik nie ma jeszcze pliku crontab. Bardziej niezawodnym sposobem byłoby:

(crontab -l ; echo "1 2 3 4 5 /root/bin/backup.sh") | sort - | uniq - | crontab - 

Alternatywnie, jeśli Twoja dystrybucja to obsługuje, możesz również użyć osobnego pliku:

echo "1 2 3 4 5 /root/bin/backup.sh" |sudo tee /etc/crond.d/backup

Znaleziono je w innym pytaniu SO .

kvz
źródło
Może używasz sh zamiast bash?
kvz
Nadal sh: 1: Syntax error: "(" unexpectedużywam sh .
Batandwa
Działa to tylko wtedy, gdy używasz BASH. Nie znam poprawnej składni DASH (sh). Zaktualizowałem również odpowiedź
kvz
1
fwiw, ten błąd pojawia się przy użyciu bash, jeśli między <i jest spacja (. To znaczy , że się nie < (udaje, ale <(działa, chyba że w twoim harmonogramie są gwiazdki ...
dou Rozwarp
Uważam, że jest to właściwy sposób:cat <(crontab -l |grep -v "${CRON}") <(echo "${CRON}") | crontab -
Stanislav,
5

Do szybkiego i brudnego tworzenia / zastępowania pliku crontab ze skryptu BASH użyłem tej notacji:

crontab <<EOF
00 09 * * 1-5 echo hello
EOF
Gibbsoft
źródło
5

Wariant, który edytuje crontab, tylko jeśli nie ma tam pożądanego ciągu:

CMD="/sbin/modprobe fcpci"
JOB="@reboot $CMD"
TMPC="mycron"
grep "$CMD" -q <(crontab -l) || (crontab -l>"$TMPC"; echo "$JOB">>"$TMPC"; crontab "$TMPC")
Gerald Schade
źródło
3

Jeśli używasz Vixie Cron, np. W większości dystrybucji Linuksa, możesz po prostu umieścić plik w /etc/cron.d z indywidualnym cronjob.

Działa to tylko dla roota. Jeśli twój system to obsługuje, powinieneś zobaczyć kilka przykładów. (Zwróć uwagę na nazwę użytkownika zawartą w wierszu, w tej samej składni, co stary plik / etc / crontab)

Smutne jest, że w cronie jest to mylne, że nie ma sposobu, aby poradzić sobie z tym jako zwykły użytkownik i że tak wiele implementacji crona nie ma żadnego sposobu, aby sobie z tym poradzić.

głaskanie pod brodę
źródło
2

Tak więc w Debianie, Ubuntu i wielu podobnych dystrybucjach opartych na Debianie ...

Istnieje mechanizm konkatenacji zadania cron, który pobiera plik konfiguracyjny, łączy je i dodaje do uruchomionej usługi cron.

Możesz umieścić plik pod /etc/cron.d/somefilename, gdzie somefilename jest tym, czego chcesz.

sudo echo "0,15,30,45 * * * * ntpdate -u time.nist.gov" >> /etc/cron.d/vmclocksync

Rozłóżmy to:

sudo - ponieważ potrzebujesz podwyższonych uprawnień do zmiany konfiguracji crona w katalogu / etc

echo - pojazd do tworzenia wyjścia na standardowym wyjściu. printf, cat ... też by działały

„- użyj podwójnego cudzysłowu na początku łańcucha, jesteś profesjonalistą

0,15,30,45 * * * * - standardowy harmonogram uruchamiania cron, ten uruchamia się co 15 minut

ntpdate -u time.nist.gov - właściwe polecenie, które chcę uruchomić

„- ponieważ moje pierwsze podwójne cudzysłowy potrzebuje znajomego, aby zamknąć wyjściowy wiersz

>> - podwójne nadpisanie dołącza zamiast zastępuje *

/etc/cron.d/vmclocksync - vmclocksync to nazwa pliku, którą wybrałem, idzie w /etc/cron.d/


* jeśli użyjemy przekierowania>, możemy zagwarantować, że mamy tylko jeden wpis zadania. Ale groziłoby nam usunięcie wszelkich innych reguł w istniejącym pliku. Możesz sam zdecydować, czy możliwe jest zniszczenie za pomocą>, czy możliwe duplikaty za pomocą >> są dla Ciebie. Ewentualnie możesz zrobić coś skomplikowanego lub zaangażowanego, aby sprawdzić, czy nazwa pliku istnieje, czy coś w nim jest i czy dodajesz jakiekolwiek duplikaty - ale mam coś do zrobienia i nie mogę tego zrobić dla Ty w tej chwli.

BradChesney79
źródło
2

Skrypt Bash do dodawania zadania cron bez interaktywnego edytora. Poniższy kod pomaga dodać cronjob przy użyciu plików linux.

#!/bin/bash

cron_path=/var/spool/cron/crontabs/root

#cron job to run every 10 min.
echo "*/10 * * * * command to be executed" >> $cron_path

#cron job to run every 1 hour.
echo "0 */1 * * * command to be executed" >> $cron_path
akash
źródło
1
Wiem, że minęło sporo czasu, ale to wciąż jedyna dobra odpowiedź, ponieważ wszystkie najbardziej głosujące usuwają stare crony zamiast tylko dodawać nowe.
AFE
1
Ten nie instaluje crona. Po prostu dołącza go do pliku. Będziesz musiał jakoś powiadomić proces cron o zainstalowaniu nowego wpisu.
Apoorv Parijat
1

Oto funkcja bash do dodawania polecenia crontabbez powielania

function addtocrontab () {
  local frequency=$1
  local command=$2
  local job="$frequency $command"
  cat <(fgrep -i -v "$command" <(crontab -l)) <(echo "$job") | crontab -
}
addtocrontab "0 0 1 * *" "echo hello"
Klas Mellbourn
źródło
1
CRON="1 2 3 4 5 /root/bin/backup.sh" 
cat < (crontab -l) |grep -v "${CRON}" < (echo "${CRON}")

dodaj parametr -w, aby dokładnie komenda grep, bez parametru -w dodanie polecenia cronjob „testowanie” powoduje usunięcie zadania cron „test123”

funkcja skryptu do dodawania / usuwania cronjobs. brak wpisów powielania:

cronjob_editor () {         
# usage: cronjob_editor '<interval>' '<command>' <add|remove>

if [[ -z "$1" ]] ;then printf " no interval specified\n" ;fi
if [[ -z "$2" ]] ;then printf " no command specified\n" ;fi
if [[ -z "$3" ]] ;then printf " no action specified\n" ;fi

if [[ "$3" == add ]] ;then
    # add cronjob, no duplication:
    ( crontab -l | grep -v -F -w "$2" ; echo "$1 $2" ) | crontab -
elif [[ "$3" == remove ]] ;then
    # remove cronjob:
    ( crontab -l | grep -v -F -w "$2" ) | crontab -
fi 
} 
cronjob_editor "$1" "$2" "$3"

testowane:

$ ./cronjob_editor.sh '*/10 * * * *' 'echo "this is a test" > export_file' add
$ crontab  -l
$ */10 * * * * echo "this is a test" > export_file
speefak
źródło
Jeśli masz to samo polecenie w crontabie dwa razy (uruchamiane w różnych momentach), usunięcie usunie obie linie.
Michaelkay,
1

Moim preferowanym rozwiązaniem byłoby:

(crontab -l | grep . ; echo -e "0 4 * * * myscript\n") | crontab -

Zapewni to prawidłowe posługiwanie się pustą nową linią u dołu. Aby uniknąć problemów z crontabem, zwykle należy zakończyć plik crontab pustą nową linią. Powyższy skrypt upewnia się, że najpierw usuwa wszelkie puste wiersze za pomocą „grep”. część, a następnie dodaj nowy pusty wiersz na końcu z „\ n” na końcu skryptu. Zapobiegnie to również umieszczeniu pustej linii nad nowym poleceniem, jeśli istniejący plik crontab kończy się pustą linią.

gsus
źródło
1
echo "0 * * * * docker system prune --force >/dev/null 2>&1" | sudo tee /etc/cron.daily/dockerprune
użytkownik11547308
źródło
0

Nie, w crontab nie ma opcji modyfikacji plików cron.

Musisz: wziąć bieżący plik cron (crontab -l> newfile), zmienić go i umieścić nowy plik na swoim miejscu (crontab newfile).

Jeśli znasz perl, możesz użyć tego modułu Config :: Crontab .

LLP, Andrea

andcoz
źródło
0

funkcja skryptu, aby dodać cronjobs. sprawdź zduplikowane wpisy, użyteczne wyrażenia *> „

cronjob_creator () {         
# usage: cronjob_creator '<interval>' '<command>'

  if [[ -z $1 ]] ;then
    printf " no interval specified\n"
elif [[ -z $2 ]] ;then
    printf " no command specified\n"
else
    CRONIN="/tmp/cti_tmp"
    crontab -l | grep -vw "$1 $2" > "$CRONIN"
    echo "$1 $2" >> $CRONIN
    crontab "$CRONIN"
    rm $CRONIN
fi
}

testowane:

$ ./cronjob_creator.sh '*/10 * * * *' 'echo "this is a test" > export_file'
$ crontab  -l
$ */10 * * * * echo "this is a test" > export_file

źródło: mój mózg;)


źródło
-5

Prawdopodobnie możesz zmienić domyślny edytor na ed i użyć heredoc do edycji.

EDITOR=ed
export EDITOR

crontab -e << EOF
> a
> * * * * * Myscript
> * * * * * AnotherScript
> * * * * * MoreScript
> .
> w
> q
> EOF

Uwaga wiodący > w tym kodzie oznacza, że ​​naciśnięto klawisz Return / Enter, aby utworzyć nowy wiersz.

Te a środki APPEND więc nie zastąpi nic.

The . oznacza, że ​​skończyłeś edycję.

w środki zapisać zmiany.

Gdy Q oznacza ZAKOŃCZ lub wyjścia wyd.

możesz to sprawdzić

crontab -l

Możesz także usunąć wpis.

EDITOR=ed
export EDITOR

crontab -e << EOF
> /Myscript/
> d
> .
> w
> q
> EOF

Spowoduje to usunięcie wpisu crontab z Myscript.

Do d środki usunąć wzór wewnątrz / / .

Nie, sprawdź to jeszcze raz

crontab -l

To rozwiązanie działa w skrypcie zbyt mało > oczywiście :-)

Jetchisel
źródło