Masalah dengan $ ACAK di crontab

9

Saya punya masalah aneh dengan $ ACAK di cron. Saya ingin menjalankan perintah beberapa menit secara acak setelah cronjob menyala.

Contoh ini bekerja langsung di terminal dan menunda perintah hingga 30 detik (ganti perintah dengan apa pun yang Anda inginkan, itu sebenarnya sebuah gema ke / dev / ttyUSB0):

sleep `expr $RANDOM \% 30` ; command

Jika baris yang sama ditempatkan di crontab, perintah selalu langsung aktif tanpa penundaan:

* * * * * sleep `expr $RANDOM \% 30` ; command

Jika saya menggunakan ekspresi tanpa $ RANDOM, itu berfungsi dengan baik - ini membuat penundaan 15 detik:

* * * * * sleep `expr 10 + 5` ; command

Dengan kata lain, sepertinya $ RANDOM tidak berfungsi dalam cron.

Tetapi ini bukan hanya karena $ RANDOM sendiri dievaluasi menjadi nol, karena dengan demikian ini akan memberikan penundaan 10:

* * * * * sleep `expr $RANDOM \% 30 + 10` ; command

Saya juga telah mencoba dengan && instread of; tapi itu tidak membantu. Bahkan, maka perintahnya tidak menembak sama sekali!

Tentu saja saya dapat menempatkan penundaan dalam sebuah skrip yang kemudian dipanggil dari crontab, tetapi itu tidak menjelaskan masalah saya dan tidak membuat saya belajar :-)

Itu Debian Lenny jika itu membuat perbedaan.

pelaut
sumber

Jawaban:

17

cronmenggunakan /bin/shshell untuk menjalankan tugas. Di beberapa distro, ini adalah symlink ke dash. Tak satu pun dari mereka mendukung $RANDOMvariabel, yang merupakan bashekstensi-spesifik.

  • Dengan vixie-cron, Anda dapat meletakkan garis SHELL=/bin/bashdi bagian atas crontab Anda.

  • Jika tidak, Anda harus puas dengan bash -c 'echo $RANDOM'atau perl -e 'print int(rand(65535))'.

    (Pada contoh di atas, 65535 adalah angka maksimum yang akan dikembalikan. Anda dapat menerapkan matematika lain di dalam skrip juga.)

  • Dalam sistem yang dikonfigurasikan dengan benar, Anda akan diberi tahu tentang hal ini dengan cronsendirinya - selalu mengirimkan hasil pekerjaan, termasuk pesan kesalahan, melalui email. Instal MTA ringan.


Juga, dalam bash, $(( ))lebih disukai daripada `expr`.

pengguna1686
sumber
Terakhir saya periksa, /bin/shbukan shell yang sebenarnya, hanya symlink ke shell yang disukai dari sysadmin (biasanya bash atau dash) di Debian.
Hello71
1
@ Hello71: Itulah yang saya katakan di posting. Namun demikian, itu adalah kebiasaan untuk perangkat lunak sistem untuk memohon /bin/sh(dan berharap itu kompatibel dengan Bourne shell). Contohnya adalah system()fungsi dalam glibc. Oleh karena itu /bin/shbiasanya menunjuk ke shell yang kompatibel dengan Bourne tercepat ; dan sysadmin seharusnya mengatur preferensi di baris / etc / passwd yang sesuai, bukan untuk menegakkan preferensi sistem itu secara keseluruhan
user1686
@ Hello71: ... oke, sebagian besar apa yang saya katakan di posting. (Saya tahu sebagian besar distro lain link shke bash, tetapi tampaknya tidak relevan.)
user1686
Anda benar, /bin/shpoin to dash. Sampai sekarang, saya tidak pernah mendengar tentang tanda hubung. Saya mencarinya dan itu adalah varian ringan dari bash. Juga, saya tidak tahu bahwa cron berlari di lingkungan "lumpuh", tetapi itu menjelaskan berbagai masalah lain yang saya miliki di masa lalu. Btw, saya mulai menggunakan $(())tetapi karena tidak berhasil saya mencoba segala macam variasi dan berakhir dengan expr- yang tentu saja tidak berhasil juga. Tapi di situlah saya berakhir :-) Apakah mungkin untuk menjalankan bash shell normal tanpa menggunakan batasan bash -c 'xxxx'? Btw, apakah tidak mungkin untuk memberikan jeda baris dalam komentar?
marlar
@marlar: 1) dashadalah sebuah shell. Ini tidak lebih atau kurang normal daripada bash. Itu juga bukan varian. 2) Lihat poin # 1 dan # 2 dalam jawabannya.
user1686
2

cronbiasanya berjalan dengan lingkungan yang kurang "penuh", artinya Anda tidak memiliki banyak variabel lingkungan yang sama yang tersedia untuk Anda. Rupanya $RANDOMsalah satunya, dan sebenarnya sleepperintah Anda gagal dengan kesalahan karena variabel yang tidak ditentukan - itulah sebabnya perintah Anda gagal dijalankan sama sekali ketika Anda beralih ke &&bukan ;. (Ya, sebenarnya, $RANDOMadalah fungsi Bash, tetapi crontidak berjalan di lingkungan Bash penuh, yang jelas tidak memiliki fungsi ini.)

Untuk menyelesaikan tugas ini, Anda harus menggunakan skrip Bash terpisah, seperti yang Anda katakan. Sebagai alternatif, Anda mungkin dapat menemukan cara untuk menggunakan cat /dev/urandomlangsung dalam cronperintah, tetapi mungkin akan lebih mudah hanya untuk memindahkan apa yang saat ini Anda miliki ke skrip Bash terpisah.

Kromey
sumber
1
Itu tidak cantik, tetapi saya menemukan solusi ini yang analog dengan saran Anda: sleep $ (expr od -An -N1 -i /dev/urandom\% 30); command
marlar
1
$RANDOMbukan bagian dari lingkungan "penuh". Ini tidak ada hubungannya dengan variabel lingkungan yang ditetapkan pada awal proses. Ini adalah variabel khusus yang dibuat "on the fly" di bash. Nilai baru selalu dihasilkan setiap kali variabel dibaca. --- cronsecara default menggunakannya /bin/shpada sistem /bin/shyang tidak ditautkan bash $RANDOMtidak akan berfungsi secara default.
pabouk