Jak mogę programowo utworzyć nowe zadanie cron?

133

Chcę mieć możliwość programowego dodawania nowego zadania cron, jaki jest najlepszy sposób, aby to zrobić?

Z moich badań wynika, że ​​mógłbym zrzucić bieżący plik crontab, a następnie dołączyć nowy, przesyłając go z powrotem do pliku crontab:

(crontab -l ; echo "0 * * * * wget -O - -q http://www.example.com/cron.php") | crontab -

Czy jest lepszy sposób?

davidmytton
źródło
2
Twoje rozwiązanie wydaje się dobre.
Craig S
W Solarisie po prostu usuń kreskę z ostatniego pliku crontab. Możesz dodać grep, aby uniknąć dodawania już tam linii.
lacroix1547
Możliwy duplikat Jak utworzyć zadanie cron za pomocą Bash
Ciro Santilli 郝海东 冠状 病 六四 事件 法轮功
nawiasy klamrowe zamiast nawiasów zrobią to bez tworzenia procesu. Pamiętaj, aby zachować odstępy wokół nawiasów klamrowych, {...; }.
Jay Winston

Odpowiedzi:

-24

Zawsze mi się to udawało.

Powinieneś rozważyć nieco bardziej wyrafinowany skrypt, który może zrobić trzy rzeczy.

  1. Dołącz linię crontab; zapewniając, że nie istnieje. Dodawanie, gdy już istnieje, jest złe.

  2. Usuń linię crontab. Może tylko ostrzeżenie, jeśli nie istnieje.

  3. Połączenie powyższych dwóch funkcji, aby zastąpić linię crontab.

S.Lott
źródło
79
Pyta jak, a ty mu powiedz co?
Cerin
1
Co jeśli użytkownik nie ma jeszcze tabeli crontab?
Maxim Egorushkin
135

Najlepszym sposobem, jeśli pracujesz jako root, jest upuszczenie pliku do /etc/cron.d

jeśli używasz menedżera pakietów do pakowania oprogramowania, możesz po prostu umieścić pliki w tym katalogu i są one interpretowane tak, jakby były plikami crontab, ale z dodatkowym polem na nazwę użytkownika, np .:

Nazwa pliku: /etc/cron.d/per_minute

Zadowolony: * * * * * root /bin/sh /home/root/script.sh

MarkR
źródło
5
Po prostu upewnij się, że używana wersja crona obsługuje /etc/cron.d/. Większość współczesnych dystrybucji Linuksa tak.
sleske
8
To najprostsze, najbardziej eleganckie rozwiązanie. Z pewnością pokonuje konieczność analizowania i edytowania istniejącej tabeli crontab z innymi niepowiązanymi wpisami.
Cerin
13
Jedynym potencjalnym zastrzeżeniem jest częstotliwość, z jaką cron pobiera nowe dodatki do tego folderu (raz na godzinę). Jeśli spodziewasz się, że Twoja praca zacznie działać od razu, uważaj.
JonathanK
6
@JonathanK, czy wiesz, czy cron może zostać poproszony o ponowne skanowanie /etc/cron.d/*? Trudno stwierdzić, czy coś działa, jeśli trzeba czekać godzinę na sprawdzenie!
halfer
4
jak ustawić uprawnienia dla tego pliku? chmod + x /etc/cron.d/per_minute?
giò
104

Rozwiązanie OP ma błąd, może pozwolić na dwukrotne dodanie wpisów, użyj poniżej, aby naprawić.

(crontab -l ; echo "0 * * * * your_command") | sort - | uniq - | crontab -
JohnZ
źródło
5
W rzeczywistości jest to lepsze, jeśli nie opisane rozwiązanie. Zapewnia, że ​​polecenie nie jest dodawane dwukrotnie do crontab.
Bufke
2
Nie jest to dobre rozwiązanie problemu zduplikowanych wpisów. Co by było, gdyby w międzyczasie do crontaba została dodana inna linia?
hmn
6
Dla zapewnienia wyjątkowości, tuż sortprzed uniqnp .:(crontab -l ; echo "0 * * * * your_command") | sort - | uniq - | crontab -
mway
6
Nie ma potrzeby uniq. Użyj -uopcji na sort.
papiro
7
jak uniknąć braku crontab dla użytkownika, kiedy po raz pierwszy edytuję crontab.
wyx
24

Dodać coś do crona

(crontab -l ; echo "0 * * * * hupChannel.sh") 2>&1 | grep -v "no crontab" | sort | uniq | crontab -

Aby usunąć to z cron

(crontab -l ; echo "0 * * * * hupChannel.sh") 2>&1 | grep -v "no crontab" | grep -v hupChannel.sh |  sort | uniq | crontab -

nadzieja pomogłaby komuś

user3865482
źródło
To jest dokładnie to, czego szukałem, dodałbym tylko: | grep -v '^ #' | aby odfiltrować komentarze
Tjunkie
3
Właściwie nie powinieneś tego potrzebować, 2>&1 | grep -v "no crontab"ponieważ gdy nie ma tabeli crontab, linia wyjściowa crontab: no crontab for...jest wysyłana do stderr. Nie ma powodu, aby przechwytywać te dane wyjściowe, wysyłać je na standardowe wyjście, a następnie filtrować je za pomocą grep. Jeśli Twoim celem jest uniknięcie patrzenia crontab: no crontab for...na wynik, użyj 2> /dev/null | sort.....
matty
8

Większość rozwiązań tutaj dotyczy dodawania linii do tabeli crontab. Jeśli potrzebujesz większej kontroli, będziesz chciał mieć możliwość kontrolowania całej zawartości tabeli crontab.

Możesz użyć orurowania, aby zrobić to całkiem elegancko.

Aby całkowicie przepisać plik crontab, zrób

echo "2 2 2 2 2 /bin/echo foobar" |crontab -

Powinno to być łatwe do połączenia z innymi opisanymi tutaj odpowiedziami, takimi jak

crontab -l | <something> | tee |crontab -

Lub, jeśli masz zawartość w pliku, jest to jeszcze prostsze

cat <file> |crontab -
Eldamir
źródło
6

Jeśli planujesz robić to dla scenariusza run-raz tylko wget'ing coś, przyjrzeć się „na”

Christian Witts
źródło
6

Po prostu zmień edytor na tee polecenie:

export EDITOR="tee"
echo "0 * * * * /bin/echo 'Hello World'" | crontab -e
Renato Tambellini
źródło
4
Uważaj - to usuwa wszystkie istniejące wpisy.
starfry
5

Zakładając, że w twojej tabeli crontab znajduje się już wpis, poniższe polecenie powinno działać stosunkowo dobrze. Zauważ, że $CMDzmienna jest tam tylko dla czytelności. Sortowanie przed odfiltrowaniem duplikatów jest ważne, ponieważ uniqdziała tylko na sąsiednich wierszach.

CMD='wget -O - -q http://www.example.com/cron.php"'
(crontab -l ; echo "0 * * * * $CMD") | sort | uniq | crontab -

Jeśli obecnie masz pustą tabelę crontab, na stderr pojawi się następujący błąd:

no crontab for user

Jeśli chcesz tego uniknąć, możesz dodać trochę złożoności dodaj zrób coś takiego:

(crontab -l ; echo "0 * * * * $CMD") 2>&1 | sed "s/no crontab for $(whoami)//"  | sort | uniq | crontab -
Tim McNamara
źródło
3

Oto inny jednoliniowy sposób, który pozwala uniknąć duplikatów

(crontab -l 2>/dev/null | fgrep -v "*/1 *  *  *  * your_command"; echo "*/1 *  *  *  * your_command") | crontab -

A oto sposób na odpowiedź JohnZ i uniknięcie no crontab for userkomunikatu lub jeśli musisz działać w set -euśrodowisku typu i nie możesz mieć nic zwracającego błąd (w takim przypadku 2>/dev/nullczęść jest opcjonalna):

( (crontab -l 2>/dev/null || echo "")  ; echo "0 * * * * your_command") | sort -u - | crontab -

Lub jeśli chcesz podzielić rzeczy, aby były bardziej czytelne:

new_job="0 * * * * your_command"
preceding_cron_jobs=$(crontab -l || echo "")
(echo "$preceding_cron_jobs" ; echo "$new_job") | sort - | uniq - | crontab -

Lub opcjonalnie usuń wszelkie odniesienia do komendy twoja_polecenie (np. Jeśli harmonogram się zmienił, chcesz, aby był on kiedykolwiek cron'owany tylko raz). W tym przypadku już nie potrzebujemy uniq(dodatkowy bonus, kolejność reklamowa jest również zachowana):

new_job="0 * * * * your_command"
preceding_cron_jobs=$(crontab -l || echo "")
preceding_cron_jobs=$(echo "$preceding_cron_jobs" | grep -v your_command )
(echo "$preceding_cron_jobs" ; echo "$new_job") | crontab -
rogerdpack
źródło
2

man crontab jest również przydatny:

CRONTAB (1)

NAZWA

   crontab - manipulate per-user crontabs (Dillon's Cron)

STRESZCZENIE

   crontab file [-u user] - replace crontab from file

   crontab - [-u user] - replace crontab from stdin

   crontab -l [user] - list crontab for user
vitaly.v.ch
źródło
3
Część, która mówi "zamień crontab na stdin" to właściwie połowa odpowiedzi :-)
Grodriguez
2

Dodając do odpowiedzi JohnZ, oto składnia planowania jako root, jeśli jesteś sudoerem:

(sudo crontab -l ; echo "0 * * * * your_command") | sort - | uniq - | sudo crontab -
BuvinJ
źródło
1
function cronjob_exists($command){

    $cronjob_exists=false;

    exec('crontab -l', $crontab);


    if(isset($crontab)&&is_array($crontab)){

        $crontab = array_flip($crontab);

        if(isset($crontab[$command])){

            $cronjob_exists=true;

        }

    }
    return $cronjob_exists;
}

function append_cronjob($command){

    if(is_string($command)&&!empty($command)&&cronjob_exists($command)===FALSE){

        //add job to crontab
        exec('echo -e "`crontab -l`\n'.$command.'" | crontab -', $output);


    }

    return $output;
}

    append_cronjob('* * * * * curl -s http://localhost/cron/test.php');
RafaSashi
źródło
1

Spowoduje to sprawdzenie, czy polecenie nie istnieje przed jego dodaniem.

crontab -l 2>/dev/null | grep -q '/path/to/script' || echo "5 * * * * /path/to/script" | crontab -

Twoje zdrowie.

Ezra Obiwale
źródło
0

Piping stdout into crontabnie zainstalował dla mnie nowego crontab na macOS, więc zamiast tego znalazłem to rozwiązanie, używając teeedytora w powłoce podrzędnej:

(EDITOR=tee && (crontab -l ; echo "@daily ~/my-script.sh" ) | uniq - | crontab -e)
Simon Hänisch
źródło
0

Jeśli chcesz, aby zadanie było uruchamiane jako użytkownik:

crontab -l | { cat; echo "@weekly what_you_want_to_execute"; } | crontab -

Jeśli chcesz, aby zadanie było uruchamiane z uprawnieniami:

sudo crontab -l | { cat; echo "@weekly what_you_want_to_execute"; } | sudo crontab -

i sprawdź zadanie (z lub bez 'sudo'):

crontab -l | sed '/^$/d; /#/d'
ajcg
źródło
0

Poniżej przedstawiam to, czego używam w swoim skrypcie

1.

(2>/dev/null crontab -l ; echo "0 3 * * * /usr/local/bin/certbot-auto renew") | crontab -
cat <(crontab -l 2>/dev/null) <(echo "0 3 * * * /usr/local/bin/certbot-auto renew") | crontab -

# wypisz aktualną tabelę crontab

crontab -l > mycron 2>/dev/null

#echo nowy cron do pliku cron

echo "0 3 * * * /usr/local/bin/certbot-auto renew" >> mycron

# zainstaluj nowy plik cron

crontab mycron

rm mycron
Anh Quach
źródło
-1

możesz również dodać swoje zadania do /etc/cron.*/

vitaly.v.ch
źródło
-2

Możesz również edytować plik tekstowy tabeli cron bezpośrednio, ale Twoje rozwiązanie wydaje się całkowicie akceptowalne.

Alex Fort
źródło
1
Byłbym nieufny wobec tego z powodu obaw o możliwość jednoczesnych edycji powodujących uszkodzenie plików. Użycie polecenia crontab wiersza poleceń powinno uniknąć tego problemu.
Craig S
Craig, bez dalszych badań nie byłbym pewien, czy wersja wiersza poleceń jest atomowa i bezpieczna w warunkach wyścigu. Prawdopodobnie w każdym razie „całkiem bezpieczny”.
tuomassalo
"Edycja pliku bezpośrednio" nie jest możliwa bez uprawnień administratora (pod warunkiem, że możesz dowiedzieć się, gdzie znajduje się plik crontab użytkownika i jak upewnić się, że demon cron poprawnie odbiera twoje zmiany), a "edycja" programistyczna wydaje się być tym, o co chodzi przede wszystkim potrzebuje porady.
tripleee