Bagaimana cara membuat pekerjaan cron menggunakan Bash secara otomatis tanpa editor interaktif?

395

Apakah crontab memiliki argumen untuk membuat pekerjaan cron tanpa menggunakan editor (crontab -e). Jika demikian, Apa yang akan menjadi kode membuat cronjob dari skrip Bash?

Raúl Roa
sumber
5
Sayangnya, sebagian besar jawaban teratas di sini hanya menunjukkan cara memodifikasi crontab - meskipun dengan cara yang cukup aman - tapi saya pikir secara keseluruhan pendekatan yang salah. Lebih baik, lebih aman dan lebih sederhana adalah dengan memasukkan file ke {{cron.d}}, dan ada (saat ini) jawaban dengan suara rendah yang menjelaskan bagaimana melakukan itu jika Anda melihat lebih jauh.
gregmac

Jawaban:

539

Anda dapat menambahkan ke crontab sebagai berikut:

#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

Penjelasan garis cron

* * * * * "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)

Sumber nixCraft .

dogbane
sumber
14
Anda harus menggunakan tempfile atau mktemp
Paweł Polewicz
166
(crontab -l; gema "00 09 * * 1-5 gema halo") | crontab -
Edo
32
(crontab -l ; echo "00 09 * * 1-5 echo hello") | crontab -- lebih mudah untuk menyalin
jawaban
8
Saya sarankan untuk mengubahnya ;dengan &&sebagai penjaga keamanan terhadap kasus ini jika crontab -lgagal. jadi, seperti:(crontab -l && echo "0 0 0 0 0 some entry") | crontab -
MacUsers
12
@MacUsers, crontab -lgagal jika tidak ada crontab, jadi menggunakan &&skrip tidak mungkin untuk menambahkan entri pertama ke crontab.
JPhi1618
312

Anda mungkin dapat melakukannya dengan cepat

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

crontab -ldaftar pekerjaan crontab saat ini, catmencetaknya, echomencetak perintah baru dan crontab -menambahkan semua barang yang dicetak ke dalam file crontab. Anda dapat melihat efeknya dengan melakukan yang baru crontab -l.

TheBonsai
sumber
3
terima kasih, bisakah Anda menjelaskan sintaks, atau menunjuk ke url yang menjelaskannya?
situs
9
crontab -ldaftar pekerjaan crontab saat ini, catmencetaknya, echomencetak perintah baru dan crontab -menambahkan semua barang yang dicetak ke dalam file crontab. Anda dapat melihat efeknya dengan melakukan yang barucrontab -l
nha
3
Bekerja untukku. Jika pengguna tidak memiliki crontab yang ada, Anda akan melihat no crontab for <username>, tetapi tetap berfungsi.
fazy
21
tidak berfungsi pada instance Amazon EC2 saya. Sebaliknya, (crontab -l ; echo "00 09 * * 1-5 echo hello") | crontab -bekerja.
Stéphane Bruckert
11
Ini terlihat seperti kandidat untuk UUcatA .
ceving
86

Yang lebih pendek ini tidak memerlukan file sementara, itu kebal terhadap banyak penyisipan, dan memungkinkan Anda mengubah jadwal entri yang ada.

Katakan Anda memiliki ini:

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

Untuk menambahkannya ke crontab, tanpa duplikasi:

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

Untuk menghapusnya dari crontab apa pun jadwal saat ini:

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

Catatan:

  • grep -F cocok dengan string secara harfiah, karena kami tidak ingin menafsirkannya sebagai ekspresi reguler
  • Kami juga mengabaikan penjadwalan waktu dan hanya mencari perintah. Cara ini; jadwal dapat diubah tanpa risiko menambahkan baris baru ke crontab
MoonCactus
sumber
@moeseth: dapatkah Anda menjelaskan?
MoonCactus
Anda harus mencobanya di komputer Anda
moeseth
2
@moeseth: Saya jelas mencobanya di komputer saya (linux). Saya tidak akan menyarankan hal-hal yang tidak bekerja secara acak: /
MoonCactus
2
Omong-omong, 27 orang tidak mungkin salah (sampai hari ini). Jadi tolong jelaskan mengapa itu tidak berfungsi untuk pengaturan Anda, jadi kami dapat membantu.
MoonCactus
2
Mungkin masalah OSX.
moeseth
40

Terima kasih semuanya atas bantuan Anda. Menyatukan apa yang saya temukan di sini dan di tempat lain saya datang dengan ini:

Kode

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

Saya tidak tahu bagaimana cara menghilangkan kebutuhan untuk dua variabel tanpa mengulangi sendiri.

commandjelas merupakan perintah yang ingin saya jadwalkan. jobmengambil $commanddan menambahkan data penjadwalan. Saya membutuhkan kedua variabel secara terpisah di baris kode yang berfungsi.

Detail

  1. Credit to duckyflip, saya menggunakan redirect thingy ( <(*command*)) ini untuk mengubah output crontab -lmenjadi input untuk fgrepperintah.
  2. fgrepkemudian memfilter kecocokan $command( -vopsi), tidak peka huruf besar-kecil ( -iopsi).
  3. Sekali lagi, redirect thingy ( <(*command*)) digunakan untuk mengubah hasilnya kembali menjadi input untuk catperintah.
  4. The catperintah juga menerima echo "$job"(self explanatory), sekali lagi, melalui penggunaan thingy redirect ( <(*command*)).
  5. Jadi keluaran yang difilter dari crontab -ldan yang sederhana echo "$job", digabungkan, disalurkan ('|') ke crontab -untuk akhirnya ditulis.
  6. Dan mereka hidup bahagia selama lamanya!

Pendeknya:

Baris kode ini menyaring semua pekerjaan cron yang cocok dengan perintah, kemudian menulis pekerjaan cron yang tersisa dengan yang baru, secara efektif bertindak seperti fungsi "tambah" atau "perbarui". Untuk menggunakan ini, yang harus Anda lakukan adalah menukar nilai untuk commanddan jobvariabel.

Stoutie
sumber
5
Untuk manfaat membaca orang lain, keuntungan dari pendekatan ini adalah Anda dapat menjalankannya beberapa kali tanpa khawatir tentang entri duplikat di crontab (tidak seperti semua solusi lain). Itu karenafgrep -v
aleemb
5
Jika Anda lebih suka cara piping kiri-ke-kanan yang tradisional, ganti baris terakhir dengan: crontab -l | fgrep -i -v "$command" | { cat; echo "$job"; } | crontab -l
Antoine Lizée
1
@ AntoineLizée, Anda menjawab memiliki "l" tambahan pada akhirnya, yang seharusnya tidak ada di sana.
Henry
26

EDIT (perbaikan penulisan):

cat <(crontab -l) <(echo "1 2 3 4 5 scripty.sh") | crontab -
duckyflip
sumber
Ini akan menggantikan semua konten crontab
TheBonsai
1
@TheBonsai oh saya mengerti, saya memperbaikinya sekarang sehingga harus LAMPIRAN perintah baru ke konten crontab yang ada
duckyflip
3
Perlu diingat, bahwa proses substitusi Bash menelan kesalahan. Jika crontab -lgagal, tetapi crontab -berhasil, crontab Anda akan menjadi one-liner.
ceving
13

Ada banyak jawaban bagus seputar penggunaan crontab, tetapi tidak disebutkan metode yang lebih sederhana, seperti menggunakan cron.

Menggunakan cronakan memanfaatkan file sistem dan direktori yang berlokasi di /etc/crontab, /etc/cron.daily,weekly,hourlyatau /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

Dalam contoh di atas, kami membuat file di /etc/cron.d/, menyediakan variabel lingkungan untuk perintah untuk mengeksekusi berhasil, dan menyediakan useruntuk perintah, dan commanditu sendiri. File ini seharusnya tidak dapat dieksekusi dan namanya hanya boleh mengandung alfanumerik dan tanda hubung (lebih detail di bawah).

Untuk memberikan jawaban yang menyeluruh, mari kita lihat perbedaan antara crontabvs cron/crond:

crontab -- maintain tables for driving cron for individual users

Bagi mereka yang ingin menjalankan pekerjaan dalam konteks pengguna mereka pada sistem, menggunakan crontabmungkin masuk akal.

cron -- daemon to execute scheduled commands

Bagi mereka yang menggunakan manajemen konfigurasi atau ingin mengelola pekerjaan untuk pengguna lain, dalam hal ini kita harus menggunakan cron.

Kutipan cepat dari halaman manual memberi Anda beberapa contoh tentang apa yang harus dan tidak harus dilakukan:

/ etc / crontab dan file-file di /etc/cron.d harus dimiliki oleh root, dan tidak boleh ditulis kelompok atau lainnya. Berbeda dengan area spool, file di bawah /etc/cron.d atau file di bawah /etc/cron.hourly, /etc/cron.daily, /etc/cron.weekly dan /etc/cron.monthly juga mungkin symlink, dengan ketentuan bahwa symlink dan file yang ditunjuknya dimiliki oleh root. File-file di bawah /etc/cron.d tidak perlu dieksekusi, sedangkan file-file di bawah /etc/cron.hourly, /etc/cron.daily, /etc/cron.weekly dan /etc/cron.bulan lakukan, seperti mereka dijalankan oleh run-parts (lihat run-parts (8) untuk informasi lebih lanjut).

Sumber: http://manpages.ubuntu.com/manpages/trusty/man8/cron.8.html

Mengelola crons dengan cara ini lebih mudah dan lebih terukur dari perspektif sistem, tetapi tidak akan selalu menjadi solusi terbaik.

Mike Mackintosh
sumber
1
Mungkin perlu disebutkan bahwa <job>tidak boleh menyertakan ekstensi file.
jww
7

Kemungkinannya adalah Anda mengotomatisasi ini, dan Anda tidak ingin satu pekerjaan ditambahkan dua kali. Dalam hal ini gunakan:

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

Ini hanya berfungsi jika Anda menggunakan BASH. Saya tidak mengetahui shsintaks DASH ( ) yang benar.

Pembaruan: Ini tidak berfungsi jika pengguna belum memiliki crontab. Cara yang lebih andal adalah:

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

Atau, jika distro Anda mendukungnya, Anda juga dapat menggunakan file terpisah:

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

Menemukan mereka dalam pertanyaan SO lainnya .

kvz
sumber
Menggunakan sh bukannya bash mungkin?
kvz
Masih sh: 1: Syntax error: "(" unexpectedmenggunakan sh .
Batandwa
Ini hanya berfungsi jika Anda menggunakan BASH. Saya tidak mengetahui sintaks DASH (sh) yang benar. Memperbarui jawabannya juga
kvz
1
fwiw, saya mendapatkan kesalahan ini menggunakan bash jika ada ruang antara <dan (. Itu berarti < (gagal tetapi <(berfungsi, kecuali ada tanda bintang di jadwal Anda ...
doublesharp
Saya percaya ini adalah cara yang benar:cat <(crontab -l |grep -v "${CRON}") <(echo "${CRON}") | crontab -
Stanislav
5

Untuk pembuatan / penggantian crontab dari dengan skrip BASH yang cepat dan kotor, saya menggunakan notasi ini:

crontab <<EOF
00 09 * * 1-5 echo hello
EOF
Gibbsoft
sumber
5

Varian yang hanya mengedit crontab jika string yang diinginkan tidak ditemukan di sana:

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

Jika Anda menggunakan Vixie Cron, mis. Pada sebagian besar distribusi Linux, Anda cukup meletakkan file di /etc/cron.d dengan masing-masing cronjob.

Ini hanya berfungsi untuk root saja. Jika sistem Anda mendukung ini, Anda akan melihat beberapa contoh di sana. (Catat nama pengguna yang disertakan dalam baris, dalam sintaksis yang sama dengan yang lama / etc / crontab)

Ini adalah kesalahan yang menyedihkan di cron bahwa tidak ada cara untuk menangani hal ini sebagai pengguna biasa, dan begitu banyak implementasi cron tidak memiliki cara sama sekali untuk menangani hal ini.

membuang
sumber
2

Jadi, di Debian, Ubuntu, dan banyak distro berbasis Debian serupa ...

Ada mekanisme penggabungan tugas cron yang mengambil file konfigurasi, bundel mereka dan menambahkannya ke layanan cron Anda berjalan.

Anda dapat meletakkan file di bawah /etc/cron.d/somefilename di mana somefilename adalah apa pun yang Anda inginkan.

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

Mari kita bongkar ini:

sudo - karena Anda memerlukan hak yang lebih tinggi untuk mengubah konfigurasi cron di bawah direktori / etc

gema - kendaraan untuk membuat output pada std out. printf, cat ... akan bekerja juga

"- gunakan doublequote di awal string Anda, Anda seorang profesional

0,15,30,45 * * * * - jadwal lari cron standar, ini berjalan setiap 15 menit

ntpdate -u time.nist.gov - perintah aktual yang ingin saya jalankan

"- karena tanda kutip ganda pertama saya membutuhkan seorang teman untuk menutup garis yang sedang diproduksi

>> - pengalihan dua kali lipat alih-alih menimpa *

/etc/cron.d/vmclocksync - vmclocksync adalah nama file yang saya pilih, ia berada di /etc/cron.d/


* jika kami menggunakan> redirect, kami dapat menjamin bahwa kami hanya memiliki satu entri tugas. Tapi, kita berisiko membuang aturan lain dalam file yang ada. Anda dapat memutuskan sendiri apakah kemungkinan penghancuran dengan> benar atau kemungkinan duplikat dengan >> adalah untuk Anda. Atau, Anda dapat melakukan sesuatu yang berbelit-belit atau terlibat untuk memeriksa apakah nama file ada, jika ada sesuatu di dalamnya, dan apakah Anda menambahkan jenis duplikat - tetapi, saya memiliki beberapa hal untuk dilakukan dan saya tidak dapat melakukannya untuk kamu sekarang

BradChesney79
sumber
2

Skrip Bash untuk menambahkan pekerjaan cron tanpa editor interaktif. Kode di bawah ini membantu menambah cronjob menggunakan file 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
sumber
1
Saya tahu ini waktu yang sangat lama, tetapi ini masih satu-satunya jawaban yang baik, karena semua yang paling banyak memilih menghapus crons lama daripada hanya menambahkan yang baru.
afe
1
Yang ini tidak menginstal cron. Itu hanya menambahkannya ke file. Anda harus memberitahukan proses cron untuk menginstal entri baru.
Apoorv Parijat
1

Berikut adalah fungsi bash untuk menambahkan perintah crontabtanpa duplikasi

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
sumber
1
CRON="1 2 3 4 5 /root/bin/backup.sh" 
cat < (crontab -l) |grep -v "${CRON}" < (echo "${CRON}")

tambahkan parameter -w ke grep perintah yang tepat, tanpa parameter -w menambahkan cronjob "pengujian" menyebabkan penghapusan pekerjaan cron "testing123"

fungsi skrip untuk menambah / menghapus cronjobs. tidak ada entri duplikasi:

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"

diuji:

$ ./cronjob_editor.sh '*/10 * * * *' 'echo "this is a test" > export_file' add
$ crontab  -l
$ */10 * * * * echo "this is a test" > export_file
speefak
sumber
Jika Anda memiliki perintah yang sama di crontab dua kali (berjalan pada waktu yang berbeda), penghapusan akan menghapus kedua baris.
Michaelkay
1

Solusi pilihan saya adalah:

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

Ini akan memastikan Anda menangani baris baru kosong di bagian bawah dengan benar. Untuk menghindari masalah dengan crontab, Anda biasanya harus mengakhiri file crontab dengan baris baru yang kosong. Dan skrip di atas memastikan terlebih dahulu menghapus setiap baris kosong dengan "grep." bagian, dan kemudian tambahkan baris kosong baru di akhir dengan "\ n" di akhir skrip. Ini juga akan mencegah mendapatkan baris kosong di atas perintah baru Anda jika file crontab Anda yang ada berakhir dengan baris kosong.

ya Tuhan
sumber
1
echo "0 * * * * docker system prune --force >/dev/null 2>&1" | sudo tee /etc/cron.daily/dockerprune
pengguna11547308
sumber
0

Tidak, tidak ada opsi di crontab untuk memodifikasi file cron.

Anda harus: mengambil file cron saat ini (crontab -l> newfile), ubah dan letakkan file baru di tempatnya (crontab newfile).

Jika Anda terbiasa dengan perl, Anda dapat menggunakan modul ini Config :: Crontab .

LLP, Andrea

andcoz
sumber
0

fungsi skrip untuk menambahkan cronjobs. periksa entri duplikat, ekspresi yang bisa digunakan *> "

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
}

diuji:

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

sumber: otak saya;)


sumber
-5

Anda mungkin dapat mengubah editor default menjadi ed dan menggunakan heredoc untuk mengedit.

EDITOR=ed
export EDITOR

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

Perhatikan bagian depan > dalam kode itu berarti tombol kembali / masuk ditekan untuk membuat baris baru.

The sebuah alat APPEND sehingga tidak akan menimpa apa-apa.

The . berarti Anda selesai mengedit.

The w berarti MENULIS perubahan.

The q berarti QUIT atau keluar ed.

Anda bisa memeriksanya

crontab -l

Anda juga dapat menghapus entri.

EDITOR=ed
export EDITOR

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

Itu akan menghapus entri crontab dengan Myscript di dalamnya.

The d berarti menghapus pola dalam / / .

Tidak periksa lagi

crontab -l

Solusi ini bekerja di dalam naskah terlalu kurang > tentu saja :-)

Jetchisel
sumber