Chạy lệnh unix chính xác trong khoảng thời gian rất ngắn MÀ KHÔNG tích lũy độ trễ thời gian theo thời gian


38

Câu hỏi

Tôi muốn có thể chạy một lệnh UNIX chính xác mỗi giây trong một khoảng thời gian dài .

Tôi cần một giải pháp, không bị tụt lại sau một thời gian nhất định, vì thời gian mà chính lệnh cần để thực thi. ngủ , xem , và một kịch bản trăn nhất định đều làm tôi thất bại về vấn đề này.

Trên vi điều khiển, chẳng hạn như http://Arduino.cc, tôi sẽ thực hiện điều đó thông qua các ngắt đồng hồ phần cứng. Tôi muốn biết liệu có một giải pháp kịch bản shell chính xác theo thời gian tương tự hay không. Tất cả các giải pháp mà tôi tìm thấy trong StackExchange.com, dẫn đến độ trễ thời gian đáng chú ý, nếu chạy trong nhiều giờ. Xem chi tiết bên dưới.

Mục đích / ứng dụng thực tế

Tôi muốn kiểm tra xem kết nối mạng của tôi có liên tục lên hay không bằng cách gửi dấu thời gian qua nc(netcat) cứ sau 1 giây.

Người gửi:

precise-timestamp-generator | tee netcat-sender.txt | nc $receiver $port

Người nhận:

nc -l -p $port > netcat-receiver.txt

Sau khi hoàn thành, so sánh hai bản ghi:

diff netcat-sender.txt netcat-receiver.txt

Khác biệt sẽ là dấu thời gian chưa được truyền. Từ đó tôi sẽ biết lúc nào LAN / WAN / ISP của tôi gây rắc rối.


Giải pháp SLEEP

while [ true ]; do date "+%Y-%m-%d %H:%M:%S" ; sleep 1; done | tee timelog-sleep.txt

Nhận được một độ lệch nhất định theo thời gian, vì lệnh trong vòng lặp cũng mất một ít thời gian.

Độ chính xác

cat timelog-sleep.txt

2012-07-16 00:45:16
[...]
2012-07-16 10:20:36

Giây trôi qua: 34520

wc -l timelog-sleep.txt

Dòng trong tệp: 34243

Tóm tắt chính xác:

  • 34520-34243 = 277 vấn đề thời gian
  • 34520/34243 = 1.008 = giảm 0,8%

Giải pháp REPEAT PYTHON

Tìm thấy tại: Lặp lại lệnh Unix cứ sau x giây

repeat.py 1 "date '+%Y-%m-%d %H:%M:%S'" >> timelog-repeat-py.txt

Giả sử để tránh thời gian bù, nhưng không làm như vậy.

Độ chính xác

wc -l timelog-repeat-py.txt

2012-07-16 13:42:44
[...]
2012-07-16 16:45:24

Giây trôi qua: 10960

wc -l timelog-repeat-py.txt

Dòng trong tệp: 10859

Tóm tắt chính xác:

  • 10960-10859 = 101 vấn đề thời gian
  • 10960/10859 = 1,009 = 0,9%

Giải pháp XEM

watch -n 1 "date '+%Y-%m-%d %H:%M:%S' >> ~/Desktop/timelog-watch.txt"

Độ chính xác

wc -l timelog-watch.txt
2012-07-16 11:04:08
[...]
2012-07-16 13:25:47

Giây trôi qua: 8499

wc -l timelog-watch.txt

Dòng trong tệp: 8366

Tóm tắt chính xác:

  • 8499-8366 = 133 vấn đề thời gian.
  • 8499/8366 = 1.016 = 1.6%.

5
Độ phân giải cần thiết, độ chính xác là gì và tại sao bạn cần nó / bạn đang sử dụng nó để làm gì?
jippie

Điều gì xảy ra nếu bạn nicequá trình ngủ?
Tilo Wiklund

1
Bạn có mặc dù sử dụng lịch trình THỜI GIAN THỰC để hy vọng giảm thiểu độ trễ cho cuộc gọi ngủ ().
mdpc

Tôi nhận ra rằng thời gian của bạn sẽ luôn bị ảnh hưởng bởi trạng thái hoạt động hiện tại của hộp. Nếu một cái gì đó khiến chương trình bạn quan tâm không được tải khỏi bộ đệm, bạn sẽ tăng thời gian, trừ khi bạn có thể đảm bảo rằng thời gian chạy thông thường của chương trình ít hơn đáng kể so với khoảng thời gian bạn muốn. Tôi muốn ở trên một hệ thống thời gian thực, trong một thiết lập được loại bỏ đáng kể mà không có ai khác đăng nhập, hoặc trong chế độ người dùng. Có lẽ một giải pháp tốt hơn là sửa đổi chương trình đang đề cập để tự thực hiện vòng lặp, thay vì gọi nó từ chương trình khác.
Hack Saw

2
Khởi chạy mỗi lệnh trong luồng riêng của nó, theo cách đó, mọi lệnh chặn liên quan đến IO sẽ không làm mất thời gian của bạn.
Joel Cornett

Câu trả lời:


12

Làm thế nào để kịch bản Perl này tôi vừa đánh lên công việc?

#!/usr/bin/perl

use strict;
use warnings;
use Time::HiRes qw/time sleep/;

sub launch {
    return if fork;
    exec @_;
    die "Couldn't exec";
}

$SIG{CHLD} = 'IGNORE';

my $interval = shift;
my $start = time();
while (1) {
    launch(@ARGV);
    $start += $interval;
    sleep $start - time();
}

Sử dụng: perl timer.pl 1 date '+%Y-%m-%d %H:%M:%S'

Nó đã chạy được 45 phút mà không bỏ qua một lần nào và tôi nghi ngờ nó sẽ tiếp tục làm như vậy trừ khi a) tải hệ thống trở nên quá cao đến mức fork () mất hơn một giây hoặc b) một giây nhảy vọt được chèn vào.

Tuy nhiên, không thể đảm bảo rằng lệnh chạy ở các khoảng thời gian chính xác thứ hai, vì có một số chi phí, nhưng tôi nghi ngờ nó tệ hơn nhiều so với giải pháp dựa trên ngắt.

Tôi đã chạy nó trong khoảng một giờ với date +%N(nano giây, phần mở rộng GNU) và chạy một số thống kê về nó. Độ trễ nhiều nhất là 1 155 micro giây. Trung bình (trung bình số học) 216 Tuyển, trung bình 219 Gõ, độ lệch chuẩn 42 bậc. Nó chạy nhanh hơn 270 Nhận 95% thời gian. Tôi không nghĩ bạn có thể đánh bại nó ngoại trừ bằng chương trình C.


1
Tôi đã chạy nó qua đêm mà không có ứng dụng người dùng hoạt động nào khác trong khoảng thời gian 1 giây và nó chạy trong 29241 giây mà không bỏ qua một giây nào! Điều này sẽ phù hợp với mục đích của tôi. Sau đó, tôi chạy nó một lần nữa sáng nay với một khoảng thời gian 0,1 giây, GNU datevới +%Nvà chỉ sau 3 phút nó ném rằng lỗi: Time::HiRes::sleep(-0.00615549): negative time not invented yet at ~/bin/repeat.pl line 23.Dòng 23 trong kịch bản lưu của tôi:sleep $start - time();
porg

Nếu bạn chạy nó với các khoảng 0,01 giây hoặc 0,001 giây, đó chỉ là vấn đề vài giây hoặc ít hơn cho đến khi chương trình hủy bỏ với lỗi "thời gian âm". Nhưng với mục đích của tôi, nó phù hợp!
porg

28

Hàm POSIX ualarm()cho phép bạn lên lịch hạt nhân để báo hiệu định kỳ quá trình của bạn, với độ chính xác đến micro giây.

Đánh lên một chương trình đơn giản:

 #include<unistd.h>
 #include<signal.h>
 void tick(int sig){
     write(1, "\n", 1);
 }
 int main(){
     signal(SIGALRM, tick);
     ualarm(1000000, 1000000); //alarm in a second, and every second after that.
     for(;;)
         pause();
 }

Biên dịch

 gcc -O2 tick.c -o tick

Sau đó gắn nó vào bất cứ điều gì bạn cần thực hiện định kỳ như vậy:

./tick | while read x; do
    date "+%Y-%m-%d %H:%M:%S"
done | tee timelog-sleep.txt

Tôi có cần một vỏ đặc biệt hoặc C-std cho điều đó không? Tôi đã biên dịch nó (đưa ra một cảnh báo nhỏ về việc trả lại bị mất) nhưng không có đầu ra nào được tạo ra.
toán

@math Với -std=c99, bạn sẽ không nhận được cảnh báo về sự trở lại mất tích. Nếu không, bạn không cần bất cứ điều gì đặc biệt. Bạn đã gõ nhầm một số 0? strace ./ticksẽ cho bạn thấy những gì nó đang làm từ một viễn cảnh cao nguyên
Dave

Tôi nhận được: gcc -O2 -std = c99 -o tick tick.c tick.c: Trong chức năng 'main': tick.c: 10: 5: cảnh báo: khai báo ngầm định của hàm 'ualarm' [-Wimplicit-function-khai báo ] tick.c: Trong chức năng 'tick': tick.c: 5: 10: cảnh báo: bỏ qua giá trị trả về của 'write', được khai báo với thuộc tính warn_unuse_result [-Wunuse-result] :: Có vẻ như hệ thống của tôi (Ubuntu 12.04) không ủng hộ nó Tuy nhiên, ít nhất có một trang người đàn ông mà ualarm nên ở unistd.h. (gcc là 4.6.3)
toán

28

Bạn đã thử watchvới tham số --precise?

watch -n 1 --precise "date '+%Y-%m-%d %H:%M:%S.%N' >> ~/Desktop/timelog-watch.txt"

Từ trang người đàn ông:

Thông thường, khoảng thời gian này được hiểu là thời gian giữa thời gian hoàn thành một lần chạy lệnh và bắt đầu lần chạy tiếp theo. Tuy nhiên, với tùy chọn -p hoặc --precise, bạn có thể khiến đồng hồ cố gắng chạy lệnh mỗi giây. Hãy thử với ntptime và chú ý cách các giây phân số giữ nguyên (gần như), trái ngược với chế độ bình thường khi chúng liên tục tăng.

Thông số có thể không có sẵn trên hệ thống của bạn, mặc dù.

Bạn cũng nên xem xét những gì sẽ xảy ra khi việc thực hiện chương trình của bạn cần nhiều hơn một giây. Có nên bỏ qua việc thực hiện theo lịch trình tiếp theo hoặc nên chạy trễ?

Cập nhật : Tôi đã chạy tập lệnh một thời gian và nó không mất một bước nào:

2561 lines
start: 2012-07-17 09:46:34.938805108
end:   2012-07-17 10:29:14.938547796

Cập nhật: Các --preciselá cờ là một bổ sung Debian, các bản vá là tuy nhiên khá đơn giản: http://patch-tracker.debian.org/patch/series/view/procps/1:3.2.8-9squeeze1/watch_precision_time.patch


Chính xác là con đường để đi. Ước gì tôi có thể +10 cái này.
krlmlr

Phiên bản nào watchhỗ trợ tùy chọn đó? Đó là trên không có máy tôi đã kiểm tra.
tylerl

Phiên bản 0.3.0 của nó, là phiên bản hiện tại trên Ubuntu 12.04. Nó đến từ phiên bản 3.2.8-11ubfox6 của gói Procps.
daniel kullmann

Hmm, gói nguồn Procps không hỗ trợ --precise. Đây là một bổ sung Debian (3.2.8-9, watch_precision_time.patch)
daniel kullmann

1
Ok, nhưng giống như mdpc trong các bình luận về câu hỏi đã nêu: Điều này cũng có thể thất bại khi hệ thống của bạn đang tải nặng. Tôi vừa thử nghiệm nó cùng với sự căng thẳng (đặt tải lên đĩa và lõi) và nhận được điều này: 2012-07-24 07:20:21.864818595 2012-07-24 07:20:22.467458430 2012-07-24 07:20:23.068575669 2012-07-24 07:20:23.968415439 Công cụ thời gian thực (kernel, v.v.) không có lý do!
toán

18

crontabcó độ phân giải 1 phút. Nếu bạn ổn với thời gian trễ tích lũy mỗi phút và sau đó đặt lại vào phút tiếp theo, ý tưởng cơ bản này có thể hoạt động:

* * * * * for second in $(seq 0 59); do /path/to/script.sh & sleep 1s;done

Lưu ý rằng script.shcũng được chạy trong nền. Điều này sẽ giúp giảm thiểu độ trễ tích lũy với mỗi lần lặp của vòng lặp.

Tùy thuộc vào mức độ sleeptạo ra độ trễ , tuy nhiên có khả năng 59 giây trùng lặp với 0 giây của phút tiếp theo.

EDIT để ném một số kết quả, trong cùng định dạng như trong câu hỏi:

$ cat timelog-cron
2012-07-16 20:51:01
...
2012-07-16 22:43:00

1 giờ 52 phút = 6720 giây

$ wc -l timelog-cron
6720 timelog-cron

0 vấn đề thời gian, giảm 0%. Bất kỳ thời gian tích lũy đặt lại mỗi phút.


1
Tôi có thể hỏi tại sao điều này đã bị hạ cấp?
Izkata

2
Đó là một hack xấu xí
hhaamu

2
@hhaamu Có gì xấu về nó? Hệ điều hành chung trên PC không được thiết kế cho các hoạt động rất quan trọng về thời gian, vậy bạn có thể mong đợi gì hơn nữa? Nếu bạn muốn thời gian "thanh lịch" và hoàn toàn chính xác, bạn phải sử dụng bộ lập lịch CPU khác hoặc chuyển sang nhân thời gian thực hoặc sử dụng phần cứng chuyên dụng, v.v ... Đây là một giải pháp hoàn toàn hợp pháp và tôi không thấy lý do nào cả downvote. Đó chắc chắn là một cải tiến trên cái chỉ có "chạy trong nền" mà không cần đồng bộ hóa lại định kỳ thông qua cron.
jw013

1
Cộng với việc dừng lại rất dễ dàng. Không cần phải mạo hiểm giết nó vào giữa một chu kỳ - loại bỏ mục từ crontab và nó tự hoàn thành vào cuối phút.
Izkata

Bạn thật may mắn vì trên hệ thống của bạn cronchính xác đến lần thứ hai, nhưng nói chung không phải vậy .
Dmitry Grigoryev

15

Vấn đề của bạn là bạn đang ngủ trong một khoảng thời gian cố định sau khi bạn chạy chương trình của mình mà không tham gia để xem xét lượng thời gian đã trôi qua kể từ lần cuối bạn ngủ.

Bạn có thể làm điều này là bash hoặc bất kỳ ngôn ngữ lập trình nào khác, nhưng điều quan trọng là sử dụng đồng hồ để xác định thời gian để lên lịch cho giấc ngủ tiếp theo. Trước khi ngủ, hãy kiểm tra đồng hồ, xem bạn còn bao nhiêu thời gian và ngủ chênh lệch.

Do thỏa hiệp lập lịch xử lý, bạn không được đảm bảo thức dậy ngay trên đồng hồ, nhưng bạn nên ở gần (trong một vài ms không tải, hoặc trong vòng vài trăm ms khi tải). Và bạn sẽ không tích lũy lỗi theo thời gian vì mỗi lần bạn đồng bộ hóa lại trên mỗi chu kỳ ngủ và loại bỏ bất kỳ lỗi tích lũy nào.

Nếu bạn cần nhấn chính xác đồng hồ, thì thứ bạn đang tìm kiếm là một hệ điều hành thời gian thực , được thiết kế chính xác cho mục đích này.


Tôi nghĩ cũng rất có thể các chương trình porg đã kiểm tra khối trong khi chạy quy trình dự định - điều mà họ nên làm để tránh việc giết chết máy mà họ đang chạy.
symcbean

Cho dù bạn có chặn hay không, cơ chế hoạt động tốt. Nếu bạn chặn, bạn ngủ thời gian còn lại sau khi chặn. Nếu bạn không chặn, thì chuỗi thời gian hoặc quá trình của bạn đang ngủ trong khi luồng kia đang hoạt động. Dù bằng cách nào, kết quả tương tự.
tylerl

@tylerl: Dòng lệnh cụ thể sẽ như thế nào đối với giải pháp của bạn?
porg

Tôi đoán bạn có nghĩa là những thứ tương tự như nhau @lynxlynxlynx
porg

@porg bạn cần sử dụng date +%S.%Nđể có được số giây với độ chính xác dưới giây và usleepngủ với độ chính xác dưới giây, nhưng sau đó chỉ là vấn đề toán học.
tylerl

7

Tôi đã luôn luôn từ bỏ việc có một cái gì đó chạy chính xác trên khoảng thời gian. Tôi nghĩ bạn sẽ phải viết một chương trình C và chú ý rất cẩn thận để không vượt quá phần của khoảng thời gian 1 giây với mã của riêng bạn. Bạn có thể sẽ phải sử dụng luồng hoặc nhiều quá trình giao tiếp với nhau để làm việc này. Cẩn thận để tránh quá trình bắt đầu luồng hoặc quá trình bắt đầu quá trình.

Một tài liệu tham khảo có vẻ có liên quan đến năm 1993: Đồng hồ lấy mẫu ngẫu nhiên cho ước tính sử dụng CPU và hồ sơ mã hóa Bạn sẽ muốn xem phần phụ lục "Mã nguồn bất lợi" để xem cách chúng đo chính xác các khoảng thời gian và "đánh thức" chương trình của họ vào đúng thời điểm. Vì mã này đã 19 tuổi, có thể nó sẽ không chuyển trực tiếp hoặc dễ dàng, nhưng nếu bạn đọc nó và cố gắng hiểu nó, các nguyên tắc liên quan có thể hướng dẫn mã của bạn.

EDIT: Tìm thấy một tài liệu tham khảo khác có thể giúp: Hiệu ứng của Độ phân giải đồng hồ đối với việc lập lịch cho các quy trình thời gian thực tương tác và mềm mại sẽ giúp bạn với bất kỳ nền tảng lý thuyết nào.


4

Hãy xem nanos ngủ () (từ http://linux.about.com/l Library / cmd / blcmdl2_nanos ngủ.htmlm ). Thay vì làm cho chương trình của bạn ngủ 1 giây, hãy làm cho nó ngủ (1 - đạn cần thiết để chạy) giây. Bạn sẽ có được một giải pháp tốt hơn nhiều.


Bạn có thể làm tương tự với thường xuyên sleep, tức là sleep 0.99. Vấn đề là lượng thời gian cần thiết để chạy không đổi, thậm chí giá trị trung bình của nó có thể dao động theo thời gian.
Dmitry Grigoryev

3

Hãy thử chạy lệnh của bạn trong nền để nó không ảnh hưởng nhiều đến thời gian của vòng lặp, nhưng thậm chí điều đó sẽ không đủ nếu bạn không muốn bất kỳ sự tích lũy nào trong thời gian dài vì chắc chắn có một vài mili giây liên quan đến nó.

Vì vậy, điều này có khả năng tốt hơn, nhưng cũng có thể vẫn chưa đủ tốt:

while [ true ]; do date "+%Y-%m-%d %H:%M:%S" & sleep 1; done | 
tee timelog-sleep.txt

Trên máy tính của tôi, điều này đã đưa ra 2 lỗi trong 20 phút hoặc 0,1 mỗi phút, đó là khoảng cải thiện gấp năm lần so với lần chạy của bạn.


Vấn đề với sleep 1là nó được đảm bảo ngủ ít nhất một giây - không bao giờ ít hơn. Do đó lỗi tích lũy.
hhaamu

So sánh kết quả thời gian từ hai máy tính khác nhau là khá vô nghĩa, trừ khi bạn đã chạy mã gốc trên hệ thống của mình và thu được kết quả tương tự như OP.
Dmitry Grigoryev

1

Xấu xí nhưng nó hoạt động. Bạn có lẽ nên suy nghĩ lại về thiết kế chương trình của bạn nếu bạn cần một vòng lặp như thế này. Về cơ bản, nó kiểm tra xem toàn bộ giây hiện tại có bằng với lần kiểm tra trước hay không và in số nano giây kể từ khi thay đổi giây. Độ chính xác bị ảnh hưởng bởi giấc ngủ .001.

while true; do T=$( date +%s ); while [[ $T -eq $( date +%s ) ]]; do sleep .001; done; date "+%N nanoseconds late"; done

Độ chính xác tính bằng mili giây, với điều kiện 'tải trọng' date "+%N nanoseconds late"không mất nhiều thời gian hơn chỉ dưới một giây. Bạn có thể giảm tải CPU bằng cách tăng thời gian ngủ hoặc nếu bạn thực sự không phiền, chỉ cần thay thế lệnh ngủ bằng cách true.

002112890 nanoseconds late
001847692 nanoseconds late
002273652 nanoseconds late
001317015 nanoseconds late
001650504 nanoseconds late
002180949 nanoseconds late
002338716 nanoseconds late
002064578 nanoseconds late
002160883 nanoseconds late

Đây là một thực tế tồi vì về cơ bản bạn thực hiện cuộc thăm dò CPU cho một sự kiện và bạn đang lãng phí chu kỳ CPU. Bạn có thể muốn gắn vào một ngắt hẹn giờ (không thể có từ bash) hoặc sử dụng phần cứng chuyên dụng như vi điều khiển. Một PC và hệ điều hành của nó không được thiết kế cho độ chính xác thời gian cao.


1

Một phương pháp khác là sử dụng tạm ngưng trong một vòng lặp và gửi SIGCONT từ một chương trình bên ngoài chính xác. Gửi một tín hiệu rất nhẹ và sẽ có độ trễ ít hơn nhiều so với thực hiện một cái gì đó. Bạn cũng có thể xếp hàng trước một loạt các lệnh bằng lệnh "at", hầu như không ai sử dụng "at" nữa. Tôi không chắc nó chính xác đến mức nào.

Nếu độ chính xác là rất quan trọng và bạn muốn nghiêm túc về vấn đề này, thì âm thanh này giống như loại ứng dụng mà bạn thường sử dụng RTOS, có thể được thực hiện trong Linux với kernel đã vá RT-Preeem, sẽ cung cấp cho bạn độ chính xác và một số biện pháp kiểm soát ngắt, nhưng nó có thể gây phiền toái hơn giá trị của nó.

https://rt.wiki.kernel.org/index.php/RT_PREEMPT_HOWTO

Xenomai cũng có thể hữu ích, đó là một triển khai RTOS đầy đủ và được chuyển cho x86 và x86_64, nhưng có một số chương trình liên quan.

http://www.xenomai.org/index.php/Main_Page


1

Với ksh93(có điểm nổi $SECONDSvà tích hợp sleep)

typeset -F SECONDS=0
typeset -i i=0
while true; do
   cmd
   sleep "$((++i - SECONDS))"
done

Kịch bản tương tự cũng sẽ hoạt động với zshnhưng sẽ gọi sleeplệnh hệ thống của bạn . zshcó tích hợp zselectsẵn, nhưng chỉ với độ phân giải 1/100.


0

Tôi muốn đi với một chương trình C nhỏ:

#include <sys/time.h>
#include <unistd.h>

int main(int argc, char **argv, char **envp)
{
    struct timeval start;
    int rc = gettimeofday(&start, NULL);
    if(rc != 0)
            return 1;

    for(;;)
    {
        struct timeval now;
        rc = gettimeofday(&now, NULL);
        useconds_t delay;
        if(now.tv_usec < start.tv_usec)
            delay = start.tv_usec - now.tv_usec;
        else
            delay = 1000000 - now.tv_usec + start.tv_usec;
        usleep(delay);
        pid_t pid = fork();
        if(pid == -1)
            return 1;
        if(pid == 0)
            _exit(execve(argv[1], &argv[1], envp));
    }
}

Chương trình này hy vọng chương trình gọi với đường dẫn đầy đủ là đối số đầu tiên của nó và truyền vào bất kỳ đối số còn lại nào. Nó sẽ không đợi lệnh kết thúc, vì vậy nó sẽ vui vẻ bắt đầu nhiều trường hợp.

Ngoài ra, phong cách mã hóa ở đây thực sự cẩu thả, và một số giả định được đưa ra có thể hoặc không được đảm bảo bởi các tiêu chuẩn áp dụng, tức là chất lượng của mã này là "phù hợp với tôi".

Chương trình này sẽ có khoảng thời gian dài hơn hoặc ngắn hơn khi đồng hồ được điều chỉnh bằng NTP hoặc bằng cách cài đặt thủ công. Nếu chương trình nên xử lý việc này, POSIX cung cấp timer_create(CLOCK_MONOTONIC, ...)không bị ảnh hưởng bởi điều này.


0

Bạn nên theo dõi thời gian hiện tại và so sánh nó với thời gian bắt đầu. Vì vậy, bạn ngủ một lượng thời gian tính toán mỗi lần lặp, không phải là một lượng cố định. Theo cách này, bạn sẽ không tích lũy các lỗi thời gian và tránh xa nơi bạn nên đến vì bạn đặt lại thời gian của mình mỗi vòng lặp thành thời gian tuyệt đối từ đầu.

Ngoài ra, một số chức năng ngủ trở lại sớm nếu có sự gián đoạn, vì vậy trong trường hợp này, bạn sẽ phải gọi lại phương thức ngủ cho đến khi hết thời gian.



0

Cái này có thể chạy ít nhất 100 lần một giây với độ phân giải rất chính xác.

Sự tồn tại của thư mục số vòng lặp mỗi phút tạo ra lịch trình. Phiên bản này hỗ trợ độ phân giải microsecond giả sử máy tính của bạn có thể xử lý nó. Số lần thực hiện mỗi phút không phải chia hết cho 60 và cũng không giới hạn ở 60 Tôi đã kiểm tra nó tới 6000 và nó hoạt động.

Phiên bản này có thể được cài đặt trong thư mục /etc/init.d và chạy như một dịch vụ.

#! /bin/sh

# chkconfig: 2345 91 61
# description: This program is used to run all programs in a directory in parallel every X times per minute. \
#              Think of this program as cron with microseconds resolution.

# Microsecond Cron
# Usage: cron-ms start
# Copyright 2014 by Marc Perkel
# docs at http://wiki.junkemailfilter.com/index.php/How_to_run_a_Linux_script_every_few_seconds_under_cron"
# Free to use with attribution

# The scheduling is done by creating directories with the number of"
# executions per minute as part of the directory name."

# Examples:
#   /etc/cron-ms/7      # Executes everything in that directory  7 times a minute
#   /etc/cron-ms/30     # Executes everything in that directory 30 times a minute
#   /etc/cron-ms/600    # Executes everything in that directory 10 times a second
#   /etc/cron-ms/2400   # Executes everything in that directory 40 times a second

basedir=/etc/cron-ms

case "$1" in

   start|restart|reload)
   $0 stop
   mkdir -p /var/run/cron-ms
   for dir in $basedir/* ; do
      $0 ${dir##*/} &
   done
   exit
   ;;

   stop)
   rm -Rf /var/run/cron-ms
   exit
   ;;

esac

# Loops per minute is passed on the command line

loops=$1
interval=$((60000000/$loops))

# Just a heartbeat signal that can be used with monit to verify it's alive

touch /var/run/cron-ms

# After a restart the PIDs will be different allowing old processes to terminate

touch /var/run/cron-ms/$$

# Sleeps until a specific part of a minute with microsecond resolution. 60000000 is full minute

usleep $(( $interval - 10#$(date +%S%N) / 1000 % $interval ))

# Deleting the PID files exit the program

if [ ! -f /var/run/cron-ms/$$ ]
then
   exit
fi

# Run all the programs in the directory in parallel

for program in $basedir/$loops/* ; do
   if [ -x $program ] 
   then
      $program &> /dev/null &
   fi
done

exec $0 $loops
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.