Liên tục thực hiện lại một lệnh khi nó kết thúc ở Bash


62

Tôi đang cố gắng tìm ra một cách đơn giản để tiếp tục thực hiện lại một lệnh bất cứ khi nào nó kết thúc, vì bất kỳ lý do gì (lỗi hoặc cách khác).

Điều gì sẽ là cách tốt nhất để tiếp cận điều này?

EDIT: Tôi đã không đủ rõ ràng trước đây. Tôi cần thực hiện tiếp theo để đợi cho đến khi kết thúc trước đó.

EDIT 2: Hầu như tất cả các câu trả lời hoạt động tuyệt vời. Tôi đã lầm tưởng rằng hầu hết các câu trả lời sẽ rẽ nhánh quá trình hoặc thực hiện lại nó chỉ một lần, không ai trong số đó là mong muốn.

linux  bash 

1
Bạn vẫn chưa rõ. Sẽ hữu ích nếu bạn đề cập đến chương trình bạn đang thực hiện.
Daniel Beck

1
-1 Câu hỏi này không cho thấy bất kỳ nỗ lực nghiên cứu nào, vì người dùng nhận xét rằng câu trả lời không hoạt động thay vì thực sự cố gắng làm những gì họ đề xuất.
Daniel Beck

Câu trả lời:


39

Điều này tạo ra một vòng lặp vô hạn, thực hiện lặp đi lặp commandlại.

while :
    do
        command
done

Xin vui lòng xem chỉnh sửa cho câu hỏi ban đầu. Tôi cần phải tiếp tục thực hiện lại nhiều lần, không chỉ một lần.

8
@calcifer Câu trả lời này hoạt động khá tốt. Có điều gì đó bất thường về chương trình của bạn mà không ai trong số bốn người dùng trả lời cho đến nay dự đoán và bạn đã không đề cập đến nó.
Daniel Beck

@calcifer đây là một vòng lặp vô hạn. nó cứ lặp đi lặp lại cho đến hết thời gian (tốt, cho đến khi kịch bản kết thúc bằng mọi cách)
Nate Koppenhaver

1
Thật tệ, tôi nghĩ điều này (và tất cả các câu trả lời khác) sẽ phân nhánh quá trình hoặc thực hiện lại nó chỉ một lần, không ai trong số đó muốn. Vì vậy, có, câu trả lời này hoạt động. Cảm ơn.

1
phiên bản một dòng while true; do echo 'Hit CTRL+C'; sleep 1; done
:,

107

Các watchlệnh sẽ lặp lại một lệnh mãi mãi với một khoảng thời gian quy định:

watch -n0 <command>

Đặt -nthành 0 có hiệu quả đặt khoảng thời gian không có gì (tôi nghĩ rằng nó thực sự là .1 giây).

watch cũng có các lợi ích bổ sung của việc căn chỉnh đầu ra để có thể dễ dàng nhìn thấy các thay đổi trực quan và có một công tắc để làm nổi bật các thay đổi từ lần chạy trước.

Tham khảo: trang người xem :

xem chạy lệnh liên tục, hiển thị đầu ra của nó (màn hình đầu tiên). Điều này cho phép bạn xem sự thay đổi đầu ra của chương trình theo thời gian. Theo mặc định, chương trình được chạy cứ sau 2 giây; sử dụng -n hoặc --interval để chỉ định một khoảng khác nhau.

đồng hồ sẽ chạy cho đến khi bị gián đoạn.


Xin vui lòng xem chỉnh sửa cho câu hỏi ban đầu.

6
Tất cả các câu trả lời cho đến nay làm điều này, bao gồm cả câu trả lời này. Linux sẽ không rẽ nhánh trừ khi bạn yêu cầu cụ thể.
Paul

Tôi không biết rằng về ngã ba, cảm ơn.

Tôi không thể thấy bất kỳ đầu ra bằng phương pháp này.
Raffi Khatchadourian

@RaffiKhatchadourian Bạn đang nói nếu bạn làm watch lstrong một thư mục chứa các tệp, bạn không nhận được gì?
Paul

17

Một giải pháp đơn giản sẽ là:

yourcommand; !#

;tách các lệnh, cho phép nhiều lệnh trong một dòng ( Bash: Lists )

!#nói với bash để "lặp lại mọi thứ tôi đã viết cho đến nay trong dòng này" ( Bash: Event-Designators )


1
Xin lỗi, tôi không đủ rõ ràng. Tôi cần phải tiếp tục thực hiện lại nhiều lần, không chỉ một lần.

Cảm ơn vì điều này, tôi đã tìm kiếm nó, đặc biệt là vì yourcommand; !!thực tế không hoạt động với các lệnh trên cùng một dòng, tuy nhiên, !#dường như làm được. Chúc mừng!
sdaau

; !#đã không hoạt động trên ZSH, nó chỉ mở rộng tuyên bố về cơ bản nhân bản nó, nó không kích hoạt nó
tiết lộ

7

Bạn có thể lập kế hoạch trước trong khi thực hiện lệnh (miễn là nó không tương tác) và nhập lại !!sẽ thực hiện lại lệnh trước đó. Điều này hoạt động ví dụ trong thời gian ping -c 5.


Bạn cũng có thể định nghĩa một hàm trong bash:

function repeat { "$@"; "$@"; }

Để duy trì nó, lưu trữ nó trong ~/.bashrc.

Sau đó, bạn có thể chạy lệnh của bạn như thế này:

repeat ping -c5 heise.de

Nếu đó là một lệnh cụ thể mà bạn muốn thực hiện nhiều lần (chứ không phải bất kỳ lệnh nào ), bạn có thể thay thế "$@"trong đoạn mã đó bằng lệnh thực tế của mình và đặt tên cho hàm, ví dụ repeat_pingthay vào đó.


Để biến nó thành một vòng lặp vô hạn, bạn có thể làm những gì @Dennis gợi ý. Tôi khuyên bạn nên thêm một khoảng thời gian chờ đợi nếu bạn có ý định sử dụng điều này trong một vỏ tương tác, như thế này:

function repeat { while 1 ; do "$@" ; sleep 1 ; done; }

Nếu không, thật bất tiện khi hủy bỏ vòng lặp vô hạn này bằng cách sử dụng Ctrl-Z.


Xin vui lòng xem chỉnh sửa cho câu hỏi ban đầu.

6
@calcifer Các lệnh thực thi này đợi cho đến khi cuộc gọi chương trình trở lại. Chương trình của bạn có tách ra khỏi vỏ và quay trở lại trước khi thoát không?
Daniel Beck

Thật tệ, tôi nghĩ điều này (và tất cả các câu trả lời khác) sẽ phân nhánh quá trình hoặc thực hiện lại nó chỉ một lần, không ai trong số đó muốn. Vì vậy, có, câu trả lời này hoạt động. Cảm ơn.

4

Đưa ra một whilevòng lặp một điều kiện boolean như sau:

#!/bin/bash

while true; do

    do_something && wait

done

Điều này sẽ thực hiện lặp đi lặp lại cho đến khi bash nhận được tín hiệu chấm dứt quá trình. Thường ở dạng ctrl+c.

Bạn cũng có thể sử dụng watchlệnh để chạy một kịch bản nhiều lần. Ví dụ, một đồng hồ đơn giản trong thiết bị đầu cuối bash của bạn sử dụng watchcó thể trông như sau:

$ watch -t -n1 date +%T

Các -ttùy chọn nói watchkhông hiển thị tiêu đề của quá trình đó đang chạy. Điều này cung cấp cho bạn một đầu ra sạch sẽ chỉ của lệnh đang được lặp lại. Các -n1tùy chọn cho xem để lặp lại mỗi ngiây. Trong trường hợp này, -n1sẽ là khoảng thời gian 1thứ hai. Sau đó date +%Tlệnh hiển thị thời gian tại thời điểm hoàn thành lệnh. Thực hiện lệnh này sẽ cung cấp cho bạn một đồng hồ hoạt động trong thiết bị đầu cuối của bạn.

Và sau đó, một phương thức nữa không có trong bất kỳ câu trả lời nào khác sẽ là một cuộc gọi hàm vô hạn.

do_something() { do_something }; do_something && wait

Điều này về cơ bản giống như whilevòng lặp boolean chỉ sử dụng các lệnh gọi hàm đệ quy.

(chỉnh sửa) Để giữ tài nguyên cho máy của bạn, tôi đã thêm vào && waitđể mỗi lần chạy một quy trình, các vòng lặp sẽ "chờ" cho đến khi quá trình đó kết thúc với trạng thái thoát 0 trước lần lặp tiếp theo. Điều này rất hữu ích trong một kịch bản shell tương tác.


1
Có một whileví dụ về vòng lặp nhưng nó không sử dụng truecú pháp boolean . Có một watchví dụ nhưng nó không đưa ra nhiều cú pháp hữu ích. Tôi đang giải thích về những điều này cho bất cứ ai nó có thể giúp đỡ. Tôi muốn cung cấp một số hữu ích thiết thực cho những điều này. Các whileboolean loop cũng có thể falsevà không thực hiện cho đến khi một điều kiện không đúng sự thật được đáp ứng. Nó khá tiện dụng.

1
@ Spittin'IT Đã thêm một phương thức không được sử dụng trong các câu trả lời khác để thuận tiện cho bạn.

Đủ công bằng và tôi hiểu ... Tôi chỉ bình luận khi tôi đi qua mô-đun đánh giá nhưng chỉnh sửa và theo dõi tốt đẹp !!
Pimp Juice IT

Làm thế nào để iftiếp tục thực hiện lại?
Kamil Maciorowski

Điểm tốt Kamil. Quên để làm cho nó đệ quy lol. Đã sửa lỗi trong việc sử dụng một hàm gọi chính nó trong ifcâu lệnh.

0

Đây là một phương pháp khác mà tôi sử dụng để lặp lại một lệnh trong bash. Điều này nghe có vẻ ngớ ngẩn với một số người vì nó không liên quan đến việc viết kịch bản và có thể được nhiều người biết đến. Nhưng tôi nghĩ rằng nó đáng được đề cập vì nó nhanh chóng và thân thiện với người mới bắt đầu, theo nghĩa là không có nhiều cú pháp để nhớ. Tôi chỉ thử nghiệm điều này trong gnome-terminal của Ubuntu và các thiết bị đầu cuối khác có thể không hỗ trợ điều này.

  1. Nhập lệnh trong terminal một lần.
  2. Chọn lệnh bao gồm ký tự dòng mới bằng chuột.
  3. Sao chép lựa chọn bằng cách sử dụng Ctrl-Chèn hoặc sử dụng menu ngữ cảnh (thường được truy cập bằng nhấp chuột phải).
  4. Sử dụng Shift-Chèn để dán bao nhiêu lần bạn muốn chạy lệnh.

Bạn không phải đợi để dán cho đến khi mỗi lệnh kết thúc. Các lệnh được dán vào một hàng đợi và chúng thực thi lần lượt.


0

Hôm nay tôi cảm thấy vô vị.

Đọc từ một trong những luồng vô hạn và dẫn nó đến xargs

cat /dev/zero | xargs --null echo hello there

Nếu bạn cần nghỉ ngơi một chút ở đó, bạn có thể sẽ cần phải thực thi sh

cat /dev/zero | xargs --null sh -c "echo hello there && sleep 3"
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.