Làm thế nào để tôi ngủ trong một phần nghìn giây trong bash hoặc ksh


128

Giấc ngủ là một lệnh rất phổ biến và chúng ta có thể bắt đầu ngủ từ 1 giây:

# wait one second please 
sleep 1

Nhưng điều gì thay thế nếu tôi chỉ cần đợi 0,1 giây hoặc trong khoảng 0,1 đến 1 giây?

  • nhận xét: trên linux hoặc OS X sleep 0.XXXhoạt động tốt, nhưng trên solaris sleep 0.1hoặc sleep 0.01- cú pháp bất hợp pháp

2
Tôi có thể hỏi tại sao bạn muốn ngủ trong 1ms?
Tom O'Connor

1
Tất nhiên, trong tập lệnh bash của tôi, tôi thêm "ngủ 1", trong một số dòng, nhưng tập lệnh chạy rất chậm, vì vậy sau một số kết luận tôi tính toán rằng giấc ngủ 0,1 cũng mang lại kết quả tốt và nhanh hơn về độ trễ, tôi cần trì hoãn theo thứ tự Để giải quyết vấn đề ssh trong tập lệnh bash của tôi, tôi thực hiện đăng nhập parshel ssh vào một số máy bằng cách mong đợi và không chậm trễ, nó sẽ không hoạt động, Như bạn biết từ câu hỏi của tôi, độ trễ phải phù hợp với cả Linux và Solaris
yael 15/1/13

3
Dù bạn chọn giải pháp nào, hãy nhớ rằng tập lệnh shell sẽ không chính xác về mặt thời gian.
scai

Làm thế nào về việc làm một cái gì đó mất một thời gian rất ngắn để thực hiện, nhưng không làm gì cả .. nhưecho "" >/dev/null
Tom O'Connor

Ý tưởng tốt nhưng làm thế nào msec lệnh này mất? , Tôi cần 0,1 ms, không ít hơn thế - :)
yael

Câu trả lời:


68

Bash có một giấc ngủ "có thể tải", hỗ trợ các giây phân đoạn và loại bỏ các chi phí của lệnh bên ngoài:

$ cd bash-3.2.48/examples/loadables
$ make sleep && mv sleep sleep.so
$ enable -f sleep.so sleep

Sau đó:

$ which sleep
/usr/bin/sleep
$ builtin sleep
sleep: usage: sleep seconds[.fraction]
$ time (for f in `seq 1 10`; do builtin sleep 0.1; done)
real    0m1.000s
user    0m0.004s
sys     0m0.004s

Nhược điểm là các khả năng tải có thể không được cung cấp với bashnhị phân của bạn , vì vậy bạn sẽ cần phải tự biên dịch chúng như hiển thị (mặc dù trên Solaris, nó không nhất thiết phải đơn giản như trên).

Kể từbash-4.4 (tháng 9 năm 2016), tất cả các khả năng tải hiện được xây dựng và cài đặt theo mặc định trên các nền tảng hỗ trợ nó, mặc dù chúng được xây dựng dưới dạng các tệp đối tượng chia sẻ riêng biệt và không có .sohậu tố. Trừ khi distro / OS của bạn đã thực hiện một cái gì đó sáng tạo, thay vào đó bạn sẽ có thể làm:

[ -z "$BASH_LOADABLES_PATH" ] &&
  BASH_LOADABLES_PATH=$(pkg-config bash --variable=loadablesdir 2>/dev/null)  
enable -f sleep sleep

(Trang man ngụ ý BASH_LOADABLES_PATHđược đặt tự động, tôi thấy đây không phải là trường hợp trong bản phân phối chính thức kể từ ngày 4.4.12. Nếu và khi nó được đặt chính xác, bạn chỉ cần enable -f filename commandnametheo yêu cầu.)

Nếu điều đó không phù hợp, điều dễ nhất tiếp theo cần làm là xây dựng hoặc lấy sleeptừ lõi GNU, điều này hỗ trợ tính năng cần thiết. Lệnh POSIX sleeplà tối thiểu, các phiên bản Solaris cũ hơn chỉ thực hiện điều đó. Solaris 11 sleep không hỗ trợ giây.

Như một phương sách cuối cùng, bạn có thể sử dụng perl(hoặc bất kỳ tập lệnh nào khác mà bạn phải xử lý) với lời cảnh báo khởi tạo trình thông dịch có thể tương đương với thời gian ngủ dự định:

$ perl -e "select(undef,undef,undef,0.1);"
$ echo "after 100" | tclsh

2
À, vì bạn đang sử dụng expectnên có thể bạn chỉ cần sử dụng " after N", trong đó N là mili giây, trực tiếp trong tập lệnh của bạn.
mr.spuratic

sử dụng usleepnhư @Luis Vazquez và @sebix viết
Ilan.K

Apple MacOS có chế độ ngủ BSD, cũng hỗ trợ giây phân đoạn
roblogic

125

Các tài liệu cho sleeplệnh từ coreutils nói:

Các triển khai lịch sử của giấc ngủ đã yêu cầu số đó là một số nguyên và chỉ chấp nhận một đối số duy nhất không có hậu tố. Tuy nhiên, GNU ngủ chấp nhận số dấu phẩy động tùy ý. Xem điểm nổi .

Do đó bạn có thể sử dụng sleep 0.1, sleep 1.0e-1và các đối số tương tự.


1
xem nhận xét của tôi về hệ điều hành SOLARIS
yael

Bạn đã trộn lên không được ?
scai

xem cập nhật của tôi trong quastion của tôi
yael

1
Yael, tôi nghĩ vẫn còn quá nhiều tiêu cực trong câu hỏi của bạn; bạn có chắc là bạn "không phải là cú pháp bất hợp pháp"?
MadHatter

ví dụ: Tôi chạy trên solaris 10 này: # ngủ 0,1 ngủ: nhân vật xấu trong tranh luận, về linux ngủ 0,1 hoạt động tốt
yael

58

Giấc ngủ chấp nhận số thập phân để bạn có thể chia nhỏ nó như sau:

1/2 giây

 sleep 0.5

1/100 giây

sleep 0.01

Vì vậy, trong một phần nghìn giây bạn sẽ muốn

sleep 0.001

4
Bạn cũng có thể thả số 0 đứng đầu trước dấu thập phân. ví dụ. sleep .5
Mike gây ra


Nói về những người khác overcomplicating nó ...
Martin

1
@MikeCauser dẫn số không dễ đọc hơn nhiều và tín hiệu có ý định cho người đọc mã sau này. cũng tốt hơn khi bạn thực sự làm toán.
Alexander Mills


8

Bạn có thể chỉ cần sử dụng usleep. Phải mất tham số micro giây (= 1e-6 giây), vì vậy để ngủ 1 mili giây bạn sẽ nhập:

usleep 1000

1
$ usleep No command 'usleep' found, did you mean: Command 'sleep' from package 'coreutils' (main) usleep: command not found
Bulletmagnet

Không, ý tôi là usleepmột phần của initscriptsgói ít nhất là tiêu chuẩn trong tất cả các bản phân phối có nguồn gốc của Red Hat; bao gồm ít nhất là RHEL, CentOS, Fedora, Mageia / Mandriva và SuSE. Dưới đây là một ví dụ: `` ``
Luis Vazquez

1
Dưới đây là một mô hình ilustration chạy trong CentOS 7: : - sleep(từ coreutils ) hoạt động với giây - usleep(từ initscripts ) hoạt động với micro-giây
Luis Vazquez

4

Tôi đã có cùng một vấn đề (không có vỏ ngủ trên Solaris) vì vậy tôi đã viết riêng của mình như vậy:

  #include "stdio.h"
  int main(int argc, char **argv) {
     if(argc == 2) { usleep(atoi(argv[1])); }
     return 0;
}

Không kiểm tra các đối số - Tôi khuyên bạn nên viết một đối số đúng nếu bạn muốn giữ nó nhưng điều đó (gcc us ngủ.c -o us ngủ) sẽ giúp bạn thoát khỏi một lỗ hổng.


1
Bạn ít nhất có thể thay đổi usleep()cuộc gọi trần đó if(argc == 1) { usleep(atoi(argv[1])); }để tránh lập chỉ mục bên ngoài giới hạn của mảng, điều này có thể dẫn đến bất kỳ số hành vi bất ngờ nào.
một CVn

@aCVn Thật ra if (argc == 2) { usleep(atoi(argv[1])); }...
Đổ chuông

Cũng lưu ý rằng usleepđơn vị là s, vì vậy, đợi 1 giây, bạn cần cung cấp đối số 1000000.
Nhẫn Ø

@ NhẫnØ Phải. Sai lầm ngu ngốc, bắt tốt.
một CVn

atoi()là một lựa chọn khủng khiếp để chuyển đổi một chuỗi thành một int. Điều gì atoi( "STRING" )trở lại? atoi()không có cách nào để trả lại bất kỳ lỗi nào
Andrew Henle

0

Tôi thích ý tưởng ngủ, nhưng tôi không thể bình luận theo nó. Vì điều này đã giúp tôi ra ngoài, tôi hy vọng đề xuất của tôi có thể cải thiện ý tưởng ngủ.

https://github.com/fedora-sysv/initscripts/blob/3c3fe4a4d1b2a1113ed302df3ac9866ded51b01b/src/us ngủ.c là mã nguồn thực tế cho us ngủ.c trên hệ sinh thái redhat.

Cố gắng biên dịch nó trong Solaris của bạn. Bạn có thể cần https://www.opencsw.org/packages/libpopt0/ .

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.