Programlı olarak nasıl yeni bir cron işi oluşturabilirim?


130

Programatik olarak yeni bir cron işi ekleyebilmek istiyorum, bunu yapmanın en iyi yolu nedir?

Gönderen Araştırmam , ben anki crontab'ın dökümü ve sonra crontab içine onu geri boru, yenisini eklemek olabilir görünüyor:

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

Daha iyi bir yol var mı?


2
Çözümünüz iyi bir çözüm gibi görünüyor.
Craig S

Solaris'te sadece son crontab için çizgiyi kaldırın. Zaten orada bir satır eklemekten kaçınmak için bir grep ekleyebilirsiniz.
lacroix1547


parantez yerine küme parantezleri bunu bir işlem oluşturmadan yapar. Diş tellerinin etrafında boşluk bıraktığınızdan emin olun, {...; }.
Jay Winston

Yanıtlar:


-25

Benim için her zaman iyi çalıştı.

Üç şey yapabilen biraz daha karmaşık bir senaryo düşünmelisiniz.

  1. Bir crontab satırı ekleyin; var olmadığından emin olmak. Zaten var olduğunda eklemek kötüdür.

  2. Crontab hattını kaldırın. Belki de yoksa sadece uyarı.

  3. Crontab hattının yerini almak için yukarıdaki iki özelliğin bir kombinasyonu.


78
Nasıl diye soruyor ve sen ona ne diyorsun?
Cerin

1
Ya kullanıcının henüz bir crontab'ı yoksa?
Maxim Egorushkin

132

Kök olarak çalıştırmanın en iyi yolu, /etc/cron.d içine bir dosya bırakmaktır.

Yazılımınızı paketlemek için bir paket yöneticisi kullanıyorsanız, dosyaları o dizine yerleştirebilirsiniz ve bunlar crontab'larmış gibi yorumlanır, ancak kullanıcı adı için fazladan bir alan vardır, örn:

Dosya adı: /etc/cron.d/per_minute

İçerik: * * * * * root /bin/sh /home/root/script.sh


5
Kullanımdaki cron sürümünün /etc/cron.d/ 'yi desteklediğinden emin olun. Çoğu modern Linux dağıtımları bunu yapar.
sleske

8
Bu en basit, en zarif çözümdür. Mevcut bir crontab'ı diğer ilgili olmayan girişlerle ayrıştırmak ve düzenlemek zorunda kalmanın kesinlikle yenidir.
Cerin

13
Bununla ilgili olası bir uyarı, cron'un bu klasöre yeni eklemeler alma sıklığıdır (saatte bir). İşinizin hemen koşmaya başlamasını bekliyorsanız, dikkatli olun.
JonathanK

6
@JonathanK, cron'un yeniden taraması istenebilir /etc/cron.d/*mi biliyor musun ? Kontrol etmek için bir saat beklemek gerekirse, bir şeyin çalışıp çalışmadığını bilmek zor!
2014

4
bu dosya için izinler nasıl ayarlanmalıdır? chmod + x /etc/cron.d/per_minute?
giò

101

OP'nin çözümünde bir hata var, girişlerin iki kez eklenmesine izin verebilir, düzeltmek için aşağıyı kullanın.

(crontab -l ; echo "0 * * * * your_command") | sort - | uniq - | crontab -

5
Bu aslında tarif edilmemişse daha iyi bir çözümdür. Komutun crontab'a iki kez eklenmemesini sağlar.
Bufke

2
Bu, yinelenen giriş sorunu için pek iyi bir düzeltme değildir. Ya bu arada crontab'a başka bir satır eklenirse?
hmn

6
sortuniq(crontab -l ; echo "0 * * * * your_command") | sort - | uniq - | crontab -
Benzersizliği

6
Gerek yok uniq. -uSeçeneği kullanın sort.
papiro

6
crontab'ı ilk düzenlediğimde kullanıcı için crontab olmaması nasıl engellenir .
wyx

23

Cron'a bir şey eklemek için

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

Bunu cron'dan kaldırmak için

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

umarım birine yardım eder


Tam olarak aradığım şey buydu, sadece şunu ekleyecektim: | grep -v '^ #' | yorumları filtrelemek için
Tjunkie

2
Aslında ihtiyacınız olmamalı 2>&1 | grep -v "no crontab"çünkü crontab olmadığında, çıktı satırı crontab: no crontab for...stderr'e gönderilir. Bu çıktıyı yakalamak, standart çıktıya göndermek ve sonra grep kullanarak filtrelemek için hiçbir neden yok. Amacınız crontab: no crontab for...çıktınızda görmekten kaçınmaksa , kullanın 2> /dev/null | sort.....
matty

6

Bunu sadece bir şeyler yapmak için tek seferlik bir senaryo için yapmayı planlıyorsanız, " şuna " bir göz atın


6

Düzenleyiciyi tee komutuna değiştirin:

export EDITOR="tee"
echo "0 * * * * /bin/echo 'Hello World'" | crontab -e

3
Dikkat - bu mevcut tüm girişleri siler.
starfry

5

Crontab'inizde zaten bir girdi olduğunu varsayarsak, aşağıdaki komut nispeten iyi çalışmalıdır. $CMDDeğişkenin sadece okunabilirlik için orada olduğuna dikkat edin . Yinelenenleri filtrelemeden önce sıralama önemlidir çünkü uniqyalnızca bitişik satırlarda çalışır.

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

Şu anda boş bir crontab'ınız varsa, stderr'e aşağıdaki hatayı alacaksınız:

no crontab for user

Bundan kaçınmak istiyorsanız, biraz karmaşıklık ekleyebilir ve şuna benzer bir şey yapabilirsiniz:

(crontab -l ; echo "0 * * * * $CMD") 2>&1 | sed "s/no crontab for $(whoami)//"  | sort | uniq | crontab -

5

Buradaki çözümlerin çoğu, crontab'a satır eklemek içindir. Daha fazla kontrole ihtiyacınız varsa, crontab'ın tüm içeriğini kontrol edebilmek isteyeceksiniz.

Bunu oldukça zarif bir şekilde yapmak için biye kullanabilirsiniz.

Crontab'ı tamamen yeniden yazmak için

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

Bu, burada açıklanan diğer yanıtlarla birleştirmek kolay olmalıdır.

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

Veya içeriğiniz bir dosyadaysa, daha da basittir

cat <file> |crontab -

3

İşte yinelemeleri önleyen tek satırlık başka bir yol

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

Ve burada JohnZ'un cevabını yapmanın ve mesajdan kaçınmanın bir yolu var veya bir yazım ortamında çalışmanız no crontab for usergerekiyorsa set -euve herhangi bir şeyin hata vermesini sağlayamıyorsanız (bu durumda 2>/dev/nullparça isteğe bağlıdır):

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

Veya her şeyi daha okunaklı olacak şekilde bölmek istiyorsanız:

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

Veya isteğe bağlı olarak your_command ile ilgili tüm referansları kaldırın (örn: program değiştiyse, yalnızca bir kez cron'lanmasını istersiniz). Bu durumda artık ihtiyacımız yok uniq(ek bonus, kampanya siparişi de korunur):

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 -

2

man crontab ayrıca kullanışlıdır:

CRONTAB (1)

ADI

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

ÖZET

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

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

   crontab -l [user] - list crontab for user

3

2

JohnZ'un cevabına ek olarak, sudoer iseniz root olarak programlanacak sözdizimi burada:

(sudo crontab -l ; echo "0 * * * * your_command") | sort - | uniq - | sudo crontab -

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');

1

Bu, komutunuzun eklemeden önce mevcut olup olmadığını kontrol eder.

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

Şerefe.


0

Stdout içine borulama macOS'ta crontabbenim için yeni crontab'ı yüklemedi, bu yüzden bunun yerine bu çözümü teebir alt kabukta düzenleyiciyi kullanarak buldum :

(EDITOR=tee && (crontab -l ; echo "@daily ~/my-script.sh" ) | uniq - | crontab -e)

0

Görevin bir kullanıcı olarak çalışmasını istiyorsanız:

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

Görevin ayrıcalıklarla çalışmasını istiyorsanız:

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

ve görevi kontrol edin ('sudo' ile veya olmadan):

crontab -l | sed '/^$/d; /#/d'


-2

Doğrudan cron tablosu metin dosyasını da düzenleyebilirsiniz, ancak çözümünüz tamamen kabul edilebilir görünüyor.


1
Eşzamanlı düzenlemelerin dosya bozulmasına neden olma ihtimaliyle ilgili endişelerim nedeniyle bu konuda endişeli olurdum. Komut satırı crontab komutunu kullanmak bu sorunu önlemelidir.
Craig S

Craig, daha fazla araştırma yapmadan komut satırı sürümünün atomik ve yarış koşullarına uygun olduğundan emin olamazdım. Muhtemelen "oldukça güvenli".
tuomassalo

"Dosyayı doğrudan düzenlemek", kök erişimi olmadan mümkün değildir (kullanıcının crontab dosyasının nerede yaşadığını ve cron arka plan programının değişikliklerinizi doğru bir şekilde aldığından nasıl emin olacağınızı öğrenebilmeniz koşuluyla) ve programatik olarak "düzenleme" sorusu bu gibi görünüyor her şeyden önce tavsiye istiyor.
üçlü
Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.