Shell: có thể trì hoãn một lệnh mà không sử dụng 'ngủ` không?


21

Có bất kỳ sự thay thế, thay thế hoặc thủ thuật bash nào cho việc trì hoãn các lệnh mà không sử dụng sleepkhông? Ví dụ, thực hiện lệnh dưới đây mà không thực sự sử dụng chế độ ngủ:

$ sleep 10 && echo "This is a test"

42
Có chuyện gì với bạn sleepvậy?
muru

5
Không có lý do thực sự nào ngoài sự tò mò. Tôi nghĩ rằng nó sẽ rất thú vị để tìm hiểu một số giải pháp thay thế. Tôi nghĩ atcó thể là một, nhưng tôi không thể tìm thấy bất kỳ ví dụ sử dụng nào.
user321697

1
@ user321697, ngay bây giờ, tại lịch sử là để lên lịch cho các công việc đơn lẻ. chúng được thực thi bởi dịch vụ atd, vì vậy chúng sẽ không tạm dừng tập lệnh shell của bạn. một trường hợp sử dụng tại sẽ là để nó làm một cái gì đó tại một thời điểm xác định (không đồng bộ) và tạo một tệp đánh dấu khi nó kết thúc, trong khi tập lệnh của bạn đang chờ tệp đó xuất hiện trong một vòng lặp while. bạn có thể đạt được hiệu quả tương tự bằng cách lên lịch cho một công việc để gửi tập lệnh của bạn SIGCONT và sau đó đóng băng tập lệnh của bạn bằng cách gửi cho mình một SIGSTOP.
Grega Bremec

1
Tôi đến đây mong mọi người đề nghị một spinlock. Tôi ngạc nhiên với tất cả các câu trả lời.
Daan van Hoek

3
Re: "Curiosity" - trong unix.stackexchange.com/help/dont-ask , lưu ý yêu cầu "Bạn chỉ nên hỏi những câu hỏi thực tế, có thể trả lời dựa trên những vấn đề thực tế mà bạn gặp phải. " - rằng điều này đã được- nhận được mặc dù trái với hướng dẫn đó làm cho nó trở thành một ngoại lệ khá hiếm.
Charles Duffy

Câu trả lời:


17

Bạn có những lựa chọn thay thế cho sleep: Chúng là atcron. Trái với sleepnhững điều này cần bạn cung cấp thời gian mà bạn cần chúng để chạy.

  • Hãy chắc chắn rằng atddịch vụ đang chạy bằng cách thực thi service atd status.
    Bây giờ hãy nói ngày là 11:17 sáng UTC; nếu bạn cần thực thi một lệnh lúc 11:25 UTC, cú pháp là : echo "This is a test" | at 11:25.
    Bây giờ hãy nhớ rằng atdtheo mặc định sẽ không đăng nhập hoàn thành công việc. Để biết thêm tham khảo liên kết này . Tốt hơn là ứng dụng của bạn có đăng nhập riêng.

  • Bạn có thể sắp xếp công việc trong cron, để tham khảo thêm: man cronđể xem các tùy chọn của nó hoặc crontab -eđể thêm công việc mới. /var/log/croncó thể được kiểm tra thông tin về việc thực hiện công việc.

FYI sleep system call đình chỉ việc thực hiện hiện tại và lên lịch trình cho nó lập luận đối với nó.

CHỈNH SỬA:

Như @Gaius đã đề cập, bạn cũng có thể thêm thời gian atcho lệnh. Nhưng hãy cho biết thời gian là 12:30:30và bây giờ bạn đã chạy bộ lập lịch với now +1 minutes. Mặc dù 1 phút, có nghĩa là 60 giây đã được chỉ định, atnhưng không thực sự đợi đến khi 12:31:30thực hiện công việc, thay vào đó, nó thực thi công việc tại 12:31:00. Các đơn vị thời gian có thể được minutes, hours, days, or weeks. Để tham khảo thêmman at

ví dụ: echo "ls" | at now +1 minutes


7
Điều này không đúng, bạn có thể lên lịch làm việc ngay bây giờ +1 phút, để chạy trong thời gian ít phút
Gaius

29

Với bashnội dung, bạn có thể làm:

coproc read -t 10 && wait "$!" || true

Để ngủ trong 10 giây mà không sử dụng sleep. Điều coprocnày là để làm cho readstdin đó là một đường ống nơi không có gì sẽ xuất hiện. || truelà bởi vì waittrạng thái thoát sẽ phản ánh phân phối SIGALRM, điều này sẽ khiến shell thoát ra nếu errexittùy chọn được đặt.

Trong các vỏ khác:

mkshksh93đã tích sleephợp sẵn, không có điểm nào trong việc sử dụng bất cứ thứ gì khác ở đó (mặc dù cả hai cũng hỗ trợ read -t).

zshcũng hỗ trợ read -t, nhưng cũng có một trình bao bọc dựng sẵn xung quanh select(), vì vậy bạn cũng có thể sử dụng:

zmodload zsh/zselect
zselect -t 1000 # centiseconds

Nếu những gì bạn muốn là lên lịch mọi thứ sẽ được chạy từ phiên shell tương tác, hãy xem thêm zsh/schedmô-đun trongzsh .


Bạn sẽ xem xét read -t 10 < /dev/zero || true?
Jeff Schaller

5
@JeffSchaller Tôi sẽ tránh nó vì đó là một vòng lặp bận rộn.
Stéphane Chazelas

@ StéphaneChazelas Tôi sẽ không mong đợi mà là một vòng lặp bận rộn - tôi mong đợi bất kỳ của vỏ readđược triển khai sử dụng lựa chọn (2) hoặc một cái gì đó tương tự (ngụ ý rằng thời gian chờ đọc với-sẽ là một câu trả lời tốt cho câu hỏi này). Tôi đang bày tỏ sự ngạc nhiên thay vì mâu thuẫn với bạn, nhưng bạn có thể chỉ ra thảo luận thêm về điều này không?
Norman Gray

5
@NormanGray, /dev/zerolà một tệp chứa một lượng dữ liệu vô hạn (NUL byte). Vì vậy, readsẽ đọc càng nhiều càng tốt trong 10 giây đó. Rất may, trong trường hợp bashkhông hỗ trợ lưu trữ byte NUL trong các biến của nó, điều đó sẽ không sử dụng hết bộ nhớ, nhưng điều đó vẫn sẽ làm hao tổn tài nguyên CPU.
Stéphane Chazelas

1
@NormanGray, nếu chạy từ thiết bị đầu cuối, /dev/stdoutsẽ là thiết bị tty, do đó, nó sẽ có tác dụng phụ (như dừng tập lệnh nếu chạy trong nền) và sẽ quay lại nếu người dùng nhấn enter chẳng hạn. read -t 10 /dev/stdout | :sẽ hoạt động trên Linux, nhưng chỉ trên Linux, trong khi coprocsẽ hoạt động bất kể HĐH.
Stéphane Chazelas

7

Một số ý tưởng khác.

top -d10 -n2 >/dev/null

vmstat 10 2 >/dev/null

sar 10 1 >/dev/null

timeout 10s tail -f /dev/null

1
Bạn đã "đánh cắp" ý tưởng về thời gian / thời gian chờ của tôi .... +1
Rui F Ribeiro

1
Ohhhh của tôi, cảm ơn, tôi đã ở trong một tình huống không ngủ, top là tuyệt vời!
Fire-Dragon-DoL

6

Vì có những câu trả lời gợi ý sử dụng -t delaytùy chọn không chuẩn read, nên đây là một cách để đọc hết thời gian trong một vỏ tiêu chuẩn:

{ ss=`stty -g`; stty -icanon min 0 time 20; read foo; stty "$ss"; }

Đối số stty timelà trong phần mười của giây.


5

Sử dụng biến tích hợp bash $SECONDSvà vòng lặp bận:

for((target=$((SECONDS + 10)); SECONDS < target; true)); do :; done

2
Điều đó sẽ có hiệu lực tạm dừng trong một khoảng thời gian trong khoảng từ 9 đến 10 giây (do lỗi trongbash ; zshmkshcó vấn đề tương tự nhưng đã được khắc phục kể từ đó)
Stéphane Chazelas 19/11/18

7
Một cách tốt để làm cho nhiệt.
ctrl-alt-delor

6
sẽ không phải là lần đầu tiên tôi bị buộc tội là đầy không khí nóng! :)
Jeff Schaller

4

thủ thuật lâu đời nhất trong cuốn sách:

read && echo "This is a test"

Chỉ cần nhấn Entervà nó sẽ tiếp tục!


Điều này sẽ không nếu quá trình cần phải được chạy tương tác miễn phí hoặc trong nền phải không?
ss_iwe

Đúng: Nhưng đó không phải là một trong những yêu cầu của OP theo câu hỏi ban đầu, vì vậy vẫn là một câu trả lời hợp lệ ...
Fabby 20/11/18

1
OP đặc biệt đưa ra một ví dụ (với sleep) và yêu cầu một sự thay thế tương đương mà không có. Vì vậy, readkhông phân tích, xin lỗi. ;)
AnoE

@AnoE Câu trả lời của Stéphane dĩ nhiên là tốt nhất, câu trả lời của tôi chỉ là cũ nhất --- press «enter» to continue --- ;-)
Fabby

4

Quay trở lại thời của máy vi tính chạy BASIC, sự chậm trễ thường được thực hiện với một vòng lặp trống:

FOR I = 1 TO 10000:NEXT

Nguyên tắc tương tự có thể được sử dụng để chèn độ trễ trong tập lệnh shell:

COUNTER=0; while [ $COUNTER -lt 10000 ]; do :; let COUNTER=COUNTER+1; done

Tất nhiên, vấn đề với cách tiếp cận này là độ dài của độ trễ sẽ thay đổi tùy theo máy theo tốc độ bộ xử lý của nó (hoặc thậm chí trên cùng một máy dưới các tải khác nhau). Không giống như vậy sleep, nó có thể cũng sẽ tối đa hóa CPU của bạn (hoặc một trong các lõi của nó).


2
Một cách tốt để làm cho nhiệt.
ctrl-alt-delor

2
Các vòng lặp trễ là một ý tưởng khủng khiếp cho bất cứ điều gì ngoại trừ thời gian ngủ ngắn nhất (vài nano giây hoặc chu kỳ xung nhịp trong trình điều khiển thiết bị) trên bất kỳ CPU hiện đại nào có thể chạy HĐH giống Unix. tức là một giấc ngủ quá ngắn, bạn không thể có CPU làm bất cứ điều gì khác trong khi chờ đợi, như lên lịch cho một quá trình khác hoặc vào trạng thái ngủ công suất thấp trước khi thức giấc ngắt quãng. Tần số CPU động làm cho thậm chí không thể hiệu chỉnh vòng lặp trễ cho số đếm mỗi giây, ngoại trừ độ trễ tối thiểu có khả năng ngủ lâu hơn rất nhiều ở tốc độ xung nhịp thấp trước khi tăng tốc.
Peter Cordes

Máy tính cổ có mức tiêu thụ năng lượng ít phụ thuộc vào khối lượng công việc. Các CPU hiện đại cần phải tự động giảm sức mạnh cho các bộ phận khác nhau của chip càng nhiều càng tốt để không bị tan chảy (ví dụ: tắt nguồn các bộ phận của đơn vị thực thi FPU hoặc SIMD trong khi chỉ có mã số nguyên đang chạy hoặc ít nhất là chuyển tín hiệu đồng hồ đến các bộ phận của chip không cần phải chuyển đổi). Và việc chuyển sang trạng thái ngủ công suất thấp khi không hoạt động (thay vì quay trong vòng lặp vô hạn chờ ngắt thời gian) cũng gần đây hơn so với các máy tính cổ mà bạn đề cập.
Peter Cordes

Để biết thêm về lịch sử CPU, xem Hướng dẫn vi xử lý hiện đại Hướng dẫn 90 phút! - lightra.com/ con / modernmicro Processors .
Peter Cordes

3

Không có tích hợp, hoạt động tương tự sleep(trừ khi sleepđược tích hợp sẵn). Tuy nhiên, có một số lệnh khác sẽ chờ.

Một số bao gồm.

  • atcron: được sử dụng để lên lịch các nhiệm vụ tại một thời điểm cụ thể.

  • inotifywait: được sử dụng để chờ một tệp hoặc các tệp được sửa đổi / xóa / thêm / etc


Cảm ơn vì điều đó. Bạn có thể cung cấp một ví dụ để thực hiện một tác vụ theo lịch trình (10 giây kể từ bây giờ) với at?
dùng321697

1
một chỉnh sửa và upvote! ;-)
Fabby

cronnhiệm vụ lưu trữ trong crontab, phải không? Nơi atlưu trữ dữ liệu theo lịch trình?
user321697

@ user321697 Đã trả lời ở đây
Fabby 19/11/18

Xin lỗi vì đã hoàn nguyên bản chỉnh sửa của bạn về Q: bạn đã thay đổi mục đích chính của câu hỏi OP sẽ vô hiệu hóa câu trả lời đơn giản nhất trong tất cả ... \ _ () _ /
Fabby

3

Một tác phẩm kinh điển từ Xứ sở Windows và Batches:

ping -c 11 localhost >/dev/null && echo "This is a test"

Cấu hình sai tường lửa hoặc hệ thống tên có thể giới thiệu một độ trễ bổ sung đáng kể.
quang phổ

1
127.0.0.1 ... @spectras
AnoE

1
Rất may không còn cần thiết nữa, vì Windows hiện hỗ trợ ngủ ngon.
Baldrickk

1
@AnoE> giải quyết phần hệ thống tên, không phải phần tường lửa. Mặc dù không phổ biến, nó có thể được cấu hình để âm thầm thả ping trên giao diện cục bộ. Điều đó sẽ khiến ping phải chờ lâu hơn nữa.
quang phổ

+1 cho những ký ức "thích"
AC

0

Nếu bạn muốn tương tác chờ đợi một dòng mới trong một tệp, thì

tail -f
.

Chờ đợi một sự thay đổi trên một hệ thống tập tin? Sau đó sử dụng ví dụ

inotify / inoticoming
.

Và có những lựa chọn khác, tùy thuộc vào ý của bạn với "chờ đợi".

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.