Thực hiện lệnh mỗi X giây


10

Tôi muốn thực hiện một lệnh bao giờ 10 giây và để nó được thực thi trong nền (do đó loại bỏ watch?). Tất cả các câu trả lời hiển thị giống như sau, nhưng điều này sẽ thực hiện từ 11 đến 14 giây. Làm thế nào điều này có thể được thực hiện?

while true; do
    # perform command that takes between 1 and 4 seconds
    sleep 10
done

có thể với các tín hiệu thời gian thực. và xử lý đúng các bước nhảy vọt. chúc may mắn.
mikeerv

@mikeerv Vậy, đừng bận tâm thử? Tôi không quan tâm đến độ chính xác của mili giây, chỉ cần nói nửa giây.
dùng1032531

Bạn đang cố gắng để thực hiện? Tôi thấy rằng một nhiệm vụ phải chạy với loại tần số đó thường là một cách giải quyết cho một vấn đề khác.
Sobrique

@Sobrique Chính xác. Tôi đang làm một bằng chứng về khái niệm của một logger dữ liệu bỏ phiếu. Trong thực tế, nó sẽ được lập trình bằng một số ngôn ngữ khác, nhưng hiện tại nó hoạt động.
dùng1032531

Câu trả lời:


16

Làm thế nào về:

( # In a subshell, for isolation, protecting $!
  while true; do
    perform-command & # in the background
    sleep 10 ;
    ### If you want to wait for a perform-command
    ### that happens to run for more than ten seconds,
    ### uncomment the following line:
    # wait $! ;
    ### If you prefer to kill a perform-command
    ### that happens to run for more than ten seconds,
    ### uncomment the following line instead:
    # kill $! ;
    ### (If you prefer to ignore it, uncomment neither.)
  done
)

ETA: Với tất cả những bình luận, lựa chọn thay thế và phần dưới để bảo vệ thêm, điều đó có vẻ phức tạp hơn nhiều so với khi nó bắt đầu. Vì vậy, để so sánh, đây là những gì nó trông giống như trước khi tôi bắt đầu lo lắng về waithoặc kill, với sự $!cần thiết của chúng và sự cô lập:

while true; do perform-command & sleep 10 ; done

Phần còn lại thực sự chỉ dành cho khi bạn cần nó.


Bạn có thể giải thích lý do đằng sau kết xuất mã của bạn?
Ismael Miguel

2
Ngoài ra, để trích dẫn shell nào mà mã của bạn hoạt động (như câu trả lời của mikeerv) để mọi người không bị nhầm lẫn khi một shell khác hoạt động khác nhau :)
tro

@IsmaelMiguel Tôi đoán các ý kiến ​​sẽ giải thích lý do. Tôi không chắc những gì không rõ ràng.
Sidhekin

1
Hướng dẫn bash nói về $!: "Mở rộng ID tiến trình của công việc được đặt gần đây nhất vào nền" và sleepkhông được đặt vào nền, vì vậy không, nó sẽ không. :)
Sidhekin

1
ồ sai cả hai tính. điều đó xảy ra khi nào
mikeerv

9

Bạn có thể làm một cái gì đó như sau trong bash, zshhoặc ksh:

SECONDS=0
while   command
do      sleep "$((10-(SECONDS%10)))"
done

Đây là những gì bashhướng dẫn nói về $SECONDS:

$SECONDS

  • Mỗi lần tham số này được tham chiếu, số giây kể từ khi gọi shell được trả về. Nếu một giá trị được gán cho $SECONDS, giá trị được trả về cho các tham chiếu tiếp theo là số giây kể từ khi gán cộng với giá trị được gán. Nếu $SECONDSunset, nó sẽ mất các thuộc tính đặc biệt, ngay cả khi sau đó được đặt lại.

Đây là một ví dụ hoạt động:

(   SECONDS=0
    while   sleep   "$((RANDOM%10))"
    do      sleep   "$((10-(SECONDS%10)))"
            echo    "$SECONDS"
    done
)

10
20
30
40
50
60
70
80
90
100

2
Để tránh thiết lập lại SECONDSlàm sleep "$((10-(($SECONDS-$start_time)%10)))". Bạn sẽ phải làm start_time=$SECONDStrước khi lặp.
ctrl-alt-delor

@richard - Tại sao phải tránh nó?
mikeserv

bởi vì một ngày nào đó bạn sẽ có nó trong một kịch bản mà bạn gọi từ trong vòng lặp như vậy. Và bạn sẽ dành cả ngày để tự hỏi tại sao nó không hoạt động đúng. Nói tóm lại, nó không làm tổ, nếu bạn đặt lại SECONDS. Sinh ra một vỏ phụ như trong chỉnh sửa mới nhất của bạn, cũng nên tránh vấn đề này.
ctrl-alt-delor

1
@richard - vì câu hỏi liên quan đến một while truevòng lặp, tôi không nghĩ rằng bất kỳ trạng thái vỏ nào được dự kiến ​​sẽ tồn tại. Dù sao, việc kết thúc một vòng lặp như vậy trong bối cảnh của chính nó thường là cách thực hành tốt nhất. Tuy nhiên, trong một tình huống như vậy, tôi sẽ quan tâm đến việc làm như vậy trapvì lợi ích hơn là $SECONDSvì lợi ích.
mikeerv

Cảm ơn Mike, tôi đã suy nghĩ để làm một cái gì đó tương tự (nhưng chưa biết chi tiết cụ thể như thế nào). Nhưng giải pháp của Sidhekin dường như làm điều tương tự, phải không? Tôi không đủ điều kiện để đưa ra đánh giá về câu trả lời tốt hơn, nhưng cảm thấy bắt buộc phải chọn một cái gì đó.
dùng1032531

3

Chỉ BASH - Bạn cũng có thể tính thời gian dành cho lệnh của mình và trừ đi 10:

TIMEFORMAT=$'%0R'
while true; do
    T=$({ time command; } 2>&1)
    sleep $(( 10-T ))

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

TIMEFORMAT Giá trị của tham số này được sử dụng dưới dạng chuỗi định dạng chỉ định cách hiển thị thông tin thời gian cho các đường ống có tiền tố với từ dành riêng thời gian. Ký tự% giới thiệu một chuỗi thoát được mở rộng thành giá trị thời gian hoặc thông tin khác. Trình tự thoát và ý nghĩa của chúng là như sau; niềng răng biểu thị các phần tùy chọn.
%% Một nghĩa đen%.
% [p] [l] R Thời gian trôi qua tính bằng giây.
% [p] [l] U Số giây CPU dành cho chế độ người dùng.
% [p] [l] S Số giây CPU dành cho chế độ hệ thống.
% P Phần trăm CPU, được tính là (% U +% S) /% R.

P tùy chọn là một chữ số chỉ định độ chính xác, số chữ số phân số sau dấu thập phân. Giá trị 0 khiến đầu ra không có dấu thập phân hoặc phân số.

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.