Vấn đề với $ RANDOM trong crontab


9

Tôi đã gặp một vấn đề kỳ lạ với $ RANDOM trong cron. Tôi muốn thực hiện một lệnh một số phút ngẫu nhiên sau khi cronjob kích hoạt.

Ví dụ này hoạt động trực tiếp trong thiết bị đầu cuối và trì hoãn lệnh tối đa 30 giây (thay thế lệnh bằng bất cứ thứ gì bạn muốn, nó thực sự là tiếng vang tới / dev / ttyUSB0):

sleep `expr $RANDOM \% 30` ; command

Nếu cùng một dòng được đặt trong crontab, lệnh sẽ luôn kích hoạt ngay lập tức mà không bị trễ:

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

Nếu tôi sử dụng một biểu thức không có $ RANDOM, nó hoạt động tốt - điều này làm chậm 15 giây:

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

Nói cách khác, có vẻ như $ RANDOM không hoạt động trong một cron.

Nhưng nó không chỉ đơn giản vì bản thân $ RANDOM ước tính bằng không, bởi vì sau đó điều này sẽ cho độ trễ là 10:

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

Tôi cũng đã thử với &&. nhưng điều đó không có ích. Trong thực tế, sau đó lệnh không bắn gì cả!

Tất nhiên tôi có thể đặt độ trễ trong một tập lệnh được gọi từ crontab, nhưng điều đó không giải thích được vấn đề của tôi và không khiến tôi học được :-)

Đó là Debian Lenny nếu điều đó tạo ra sự khác biệt.

Câu trả lời:


17

cronsử dụng /bin/shshell để thực thi các tác vụ. Trong một số distro, đây là một liên kết tượng trưng đến dash. Không ai trong số họ hỗ trợ $RANDOMbiến, đó là một bashphần mở rộng đặc thù.

  • Với vixie-cron, bạn có thể đặt một dòng SHELL=/bin/bashở đầu crontab của bạn.

  • Nếu không, bạn sẽ phải giải quyết với bash -c 'echo $RANDOM'hoặc perl -e 'print int(rand(65535))'.

    (Trong ví dụ trên, 65535 là số tối đa được trả về. Bạn cũng có thể áp dụng toán học khác trong tập lệnh.)

  • Trong một hệ thống được cấu hình đúng, bạn sẽ được thông báo về điều này cron- nó luôn gửi đầu ra công việc, bao gồm cả thông báo lỗi, qua email. Cài đặt một MTA nhẹ.


Ngoài ra, trong bash, $(( ))được ưa thích hơn `expr`.


Tôi đã kiểm tra lần cuối, /bin/shkhông phải là trình bao thực tế, chỉ đơn thuần là một liên kết tượng trưng đến trình bao ưa thích của sysadmin (thường là bash hoặc dash) trên Debian.
Hello71

1
@ Hello71: Đó là những gì tôi đã nói trong bài viết. Tuy nhiên, theo thông lệ, phần mềm hệ thống sẽ gọi /bin/sh(và hy vọng nó tương thích với vỏ Bourne). Một ví dụ là system()hàm trong glibc. Do đó, /bin/shthường chỉ đến lớp vỏ tương thích Bourne nhanh nhất ; và sysadmin có nghĩa vụ phải đặt ưu tiên của mình trong dòng / etc / passwd thích hợp, không thực thi ưu tiên đó trên toàn hệ thống
user1686

@ Hello71: ... được thôi, chủ yếu là những gì tôi đã nói trong bài viết. (Tôi biết hầu hết các bản phân phối khác liên kết shđến bash, nhưng nó dường như không liên quan.)
user1686

Bạn nói đúng, /bin/shchỉ vào dấu gạch ngang. Cho đến bây giờ, tôi chưa bao giờ nghe về dash. Tôi nhìn nó và nó là một biến thể nhẹ của bash. Ngoài ra, tôi không biết rằng cron chạy trong môi trường "què quặt", nhưng nó giải thích nhiều vấn đề khác mà tôi gặp phải trong quá khứ. Btw, tôi đã bắt đầu sử dụng $(())nhưng vì nó không hoạt động nên tôi đã thử tất cả các loại biến thể và kết thúc với expr- tất nhiên điều đó cũng không hiệu quả. Nhưng đó là nơi tôi đã kết thúc :-) Có thể chạy shell bash bình thường mà không bị giới hạn sử dụng bash -c 'xxxx'không? Btw, không thể đặt ngắt dòng trong các bình luận?
tuyên bố

@marlar: 1) dashlà một cái vỏ. Nó không nhiều hơn hoặc ít hơn bình thường hơn bash. Nó cũng không phải là một biến thể của nó. 2) Xem điểm # 1 và # 2 trong câu trả lời.
dùng1686

2

cronthường chạy với môi trường "đầy đủ" hơn, nghĩa là bạn đơn giản không có nhiều biến môi trường giống nhau có sẵn cho bạn. Rõ ràng $RANDOMlà một trong những điều đó, và trên thực tế, sleeplệnh của bạn chỉ đơn giản là không có lỗi do biến không xác định - đó là lý do tại sao lệnh của bạn không chạy được khi bạn chuyển sang &&thay vì ;. (Chà, thực ra, $RANDOMlà một hàm Bash, nhưng cronkhông chạy trong môi trường Bash đầy đủ, rõ ràng là thiếu chức năng này.)

Để hoàn thành nhiệm vụ này, bạn sẽ cần sử dụng một tập lệnh Bash riêng, như bạn đã nói. Ngoài ra, bạn có thể tìm ra cách sử dụng cat /dev/urandomtrực tiếp trong cronlệnh, nhưng có lẽ sẽ dễ dàng hơn khi di chuyển những gì bạn hiện có sang một tập lệnh Bash riêng.


1
Nó không đẹp, nhưng tôi thấy giải pháp này tương tự như gợi ý của bạn: ngủ $ (expr od -An -N1 -i /dev/urandom\% 30); chỉ huy
tuyên bố

1
$RANDOMkhông phải là một phần của môi trường "đầy đủ". Nó không có gì để làm với các biến môi trường được thiết lập khi bắt đầu quá trình. Đó là một biến đặc biệt được tạo ra "trên đường bay" trong bash. Giá trị mới của nó luôn được tạo ra bất cứ khi nào biến được đọc. --- crontheo mặc định sử dụng /bin/shnhư vậy trên các hệ thống /bin/shkhông được liên kết đến bash $RANDOMsẽ không hoạt động theo mặc định.
pabouk
Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.