Bagaimana saya bisa secara terprogram membuat pekerjaan cron baru?

129

Saya ingin dapat secara sistematis menambahkan pekerjaan cron baru, apa cara terbaik untuk melakukan ini?

Dari penelitian saya , sepertinya saya bisa membuang crontab saat ini dan kemudian menambahkan yang baru, menyalurkannya kembali ke crontab:

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

Apakah ada cara yang lebih baik?

davidmytton
sumber
2
Solusi Anda sepertinya bagus.
Craig S
Pada Solaris hanya menghapus tanda hubung untuk crontab terakhir. Anda dapat menambahkan grep untuk menghindari menambahkan garis yang sudah ada di sana.
lacroix1547
Kemungkinan rangkap dari Cara membuat pekerjaan cron menggunakan Bash
Ciro Santilli 郝海东 冠状 病 六四 六四 事件
kurung kurawal bukannya kurung akan melakukannya tanpa memunculkan proses. Pastikan untuk menjaga ruang di sekitar kawat gigi, {...; }.
Jay Winston

Jawaban:

-25

Itu selalu bekerja dengan baik untuk saya.

Anda harus mempertimbangkan skrip yang sedikit lebih canggih yang dapat melakukan tiga hal.

  1. Tambahkan garis crontab; memastikan bahwa itu tidak ada. Menambahkan ketika sudah ada buruk.

  2. Hapus garis crontab. Mungkin hanya peringatan jika tidak ada.

  3. Kombinasi dari dua fitur di atas untuk menggantikan garis crontab.

S.Lott
sumber
78
Dia bertanya bagaimana dan Anda memberi tahu dia apa?
Cerin
1
Bagaimana jika pengguna belum memiliki crontab?
Maxim Egorushkin
132

Cara terbaik jika Anda menjalankan sebagai root, adalah dengan memasukkan file ke /etc/cron.d

jika Anda menggunakan manajer paket untuk mengemas perangkat lunak Anda, Anda dapat meletakkan file di direktori itu dan ditafsirkan seolah-olah itu adalah crontab, tetapi dengan bidang tambahan untuk nama pengguna, misalnya:

Nama file: /etc/cron.d/per_minute

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

MarkR
sumber
5
Pastikan versi cron yang digunakan mendukung /etc/cron.d/. Kebanyakan distribusi Linux modern melakukannya.
sleske
8
Ini adalah solusi paling sederhana dan paling elegan. Tentu ketukan harus mengurai dan mengedit crontab yang ada dengan entri yang tidak terkait lainnya.
Cerin
13
Satu peringatan potensial untuk ini adalah frekuensi di mana cron mengambil tambahan baru ke folder ini (sekali per jam). Jika Anda mengharapkan pekerjaan Anda segera mulai berjalan, waspadalah.
JonathanK
6
@ JonathanK, apakah Anda kebetulan tahu apakah cron dapat diminta untuk memindai ulang /etc/cron.d/*? Sulit untuk mengetahui apakah sesuatu berfungsi jika seseorang harus menunggu satu jam untuk memeriksa!
halfer
4
bagaimana seharusnya perms diatur untuk file ini? chmod + x /etc/cron.d/per_minute?
giò
101

Solusi OP memiliki bug, mungkin memperbolehkan entri ditambahkan dua kali, gunakan di bawah untuk memperbaikinya.

(crontab -l ; echo "0 * * * * your_command") | sort - | uniq - | crontab -
JohnZ
sumber
5
Ini sebenarnya solusi yang lebih baik jika tidak dijelaskan. Ini memastikan perintah tidak ditambahkan dua kali ke crontab.
Bufke
2
Ini bukan perbaikan yang baik untuk masalah entri duplikat. Bagaimana jika baris lain ditambahkan ke crontab sementara itu?
hmn
6
Untuk memastikan keunikan, tepat sortsebelumnya uniq, misalnya:(crontab -l ; echo "0 * * * * your_command") | sort - | uniq - | crontab -
mway
6
Tidak perlu uniq. Gunakan -uopsi pada sort.
papiro
6
cara menghindari tidak ada crontab untuk pengguna saat saya pertama kali mengedit crontab.
wyx
23

Untuk menambahkan sesuatu ke cron

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

Untuk menghapus ini dari cron

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

harapan akan membantu seseorang

pengguna3865482
sumber
Inilah yang saya cari, saya hanya ingin menambahkan ini: | grep -v '^ #' | untuk menyaring komentar
Tjunkie
2
Anda sebenarnya tidak perlu 2>&1 | grep -v "no crontab"karena ketika tidak ada crontab, garis output crontab: no crontab for...dikirim ke stderr. Tidak ada alasan untuk menangkap output itu, mengirimkannya ke stdout, dan kemudian menyaringnya menggunakan grep. Jika tujuan Anda adalah untuk menghindari melihat crontab: no crontab for...output Anda, maka gunakan 2> /dev/null | sort.....
matty
6

Jika Anda berencana melakukannya untuk skenario sekali jalan hanya untuk mendapatkan sesuatu, lihat 'pada'

Christian Witts
sumber
6

Cukup ubah perintah editor menjadi tee:

export EDITOR="tee"
echo "0 * * * * /bin/echo 'Hello World'" | crontab -e
Renato Tambellini
sumber
3
Waspadalah - ini menghapus semua entri yang ada.
Starfry
5

Dengan asumsi bahwa sudah ada entri di crontab Anda, perintah berikut harus bekerja relatif baik. Perhatikan bahwa $CMDvariabel hanya ada untuk dibaca. Menyortir sebelum memfilter duplikat penting, karena uniqhanya berfungsi pada baris yang berdekatan.

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

Jika saat ini Anda memiliki crontab kosong, Anda akan menerima kesalahan berikut untuk stderr:

no crontab for user

Jika Anda ingin menghindari ini, Anda dapat menambahkan sedikit kerumitan dan melakukan sesuatu seperti ini:

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

Sebagian besar solusi di sini adalah dengan menambahkan baris ke crontab. Jika Anda membutuhkan lebih banyak kontrol, Anda ingin dapat mengontrol seluruh konten crontab.

Anda dapat menggunakan perpipaan untuk melakukan ini dengan cukup elegan.

Untuk sepenuhnya menulis ulang crontab, lakukan

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

Ini harus mudah digabungkan dengan jawaban lain yang dijelaskan di sini seperti

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

Atau, jika Anda memiliki konten dalam file, itu bahkan lebih sederhana

cat <file> |crontab -
Eldamir
sumber
3

Berikut cara satu-liner lain, yang menghindari duplikat

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

Dan inilah cara untuk melakukan jawaban dan menghindari no crontab for userpesan dari JohnZ , atau jika Anda perlu beroperasi di set -eulingkungan tipe dan tidak bisa mendapatkan apa pun yang mengembalikan kegagalan (dalam hal ini 2>/dev/nullbagian ini opsional):

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

Atau jika Anda ingin membagi beberapa hal agar lebih mudah dibaca:

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

Atau secara opsional menghapus referensi ke perintah_Anda (mis: jika jadwal telah berubah, Anda hanya ingin itu pernah dicatat sekali). Dalam hal ini kita tidak lagi membutuhkan uniq(bonus tambahan, urutan penyisipan juga dipertahankan):

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
sumber
2

man crontab juga berguna:

CRONTAB (1)

NAMA

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

RINGKASAN

   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
sumber
3
Bagian yang mengatakan "ganti crontab dari stdin" sebenarnya setengah jawaban :-)
Grodriguez
2

Menambah jawaban JohnZ, inilah sintaks untuk menjadwalkan sebagai root jika Anda seorang sudoer:

(sudo crontab -l ; echo "0 * * * * your_command") | sort - | uniq - | sudo crontab -
Terima kasih
sumber
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
sumber
1

Ini akan memeriksa untuk memastikan bahwa perintah Anda belum ada sebelum menambahkannya.

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

Bersulang.

Ezra Obiwale
sumber
0

Mem-pipkan stdout ke crontabtidak menginstal crontab baru untuk saya di macOS, jadi saya menemukan solusi ini sebagai gantinya, menggunakan teeeditor di sub shell:

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

Jika Anda ingin tugas dijalankan sebagai pengguna:

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

Jika Anda ingin tugas dijalankan dengan hak istimewa:

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

dan periksa tugas (dengan atau tanpa 'sudo'):

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

Anda juga dapat menambahkan tugas Anda ke /etc/cron.*/

vitaly.v.ch
sumber
-2

Anda juga dapat mengedit file teks tabel cron secara langsung, tetapi solusi Anda tampaknya dapat diterima.

Alex Fort
sumber
1
Saya akan curiga dengan hal ini karena kekhawatiran akan kemungkinan penyuntingan bersamaan yang menyebabkan file korupsi. Menggunakan perintah crontab command-line harus menghindari masalah itu.
Craig S
Craig, tanpa riset lebih lanjut, saya tidak akan yakin bahwa versi baris perintahnya adalah atom dan ras-kondisi-aman. Mungkin "cukup aman".
tuomassalo
"Mengedit file secara langsung" tidak layak tanpa akses root (asalkan Anda dapat mengetahui di mana file crontab pengguna tinggal, dan bagaimana memastikan daemon cron menerima perubahan Anda dengan benar), dan "mengedit" secara terprogram sepertinya menjadi pertanyaannya ingin saran tentang di tempat pertama.
tripleee