Linux / Bash, làm thế nào để lên lịch các lệnh trong hàng đợi FIFO?


7

Tôi muốn khả năng lên lịch các lệnh để được chạy trong hàng đợi FIFO. Tôi không muốn chúng được chạy vào một thời điểm xác định trong tương lai như trường hợp với lệnh "at". Tôi muốn họ bắt đầu chạy ngay bây giờ, nhưng không đồng thời. Lệnh được lên lịch tiếp theo trong hàng đợi chỉ được chạy sau khi lệnh đầu tiên kết thúc thực thi. Ngoài ra, thật tuyệt nếu tôi có thể chỉ định số lượng lệnh tối đa từ hàng đợi có thể chạy đồng thời; ví dụ: nếu số lượng lệnh đồng thời tối đa là 2, thì chỉ có tối đa 2 lệnh được lên lịch trong hàng đợi sẽ được lấy từ hàng đợi theo cách thức FIFO để thực hiện, lệnh tiếp theo trong hàng đợi còn lại chỉ được bắt đầu khi một trong các lệnh Hiện tại 2 lệnh đang chạy kết thúc.

Tôi đã nghe thấy bộ đệm nhiệm vụ có thể làm một cái gì đó như thế này, nhưng gói này dường như không được hỗ trợ / thử nghiệm tốt và không có trong kho lưu trữ tiêu chuẩn của Ubuntu (Ubuntu là thứ tôi đang sử dụng). Nếu đó là cách thay thế tốt nhất thì hãy cho tôi biết và tôi sẽ sử dụng bộ đệm nhiệm vụ, nếu không, tôi rất muốn tìm hiểu cách tốt nhất, dễ nhất, được kiểm tra nhất, không có lỗi, để làm điều đó với bash.

CẬP NHẬT:

Giải pháp đơn giản như; hoặc && từ bash không hoạt động. Tôi cần lên lịch các lệnh này từ một chương trình bên ngoài, khi một sự kiện xảy ra. Tôi chỉ không muốn có hàng trăm phiên bản lệnh của mình chạy đồng thời, do đó cần một hàng đợi. Có một chương trình bên ngoài sẽ kích hoạt các sự kiện nơi tôi có thể chạy các lệnh của riêng mình. Tôi muốn xử lý TẤT CẢ các sự kiện được kích hoạt, tôi không muốn bỏ lỡ bất kỳ sự kiện nào, nhưng tôi cũng không muốn hệ thống của mình gặp sự cố, vì vậy đó là lý do tại sao tôi muốn một hàng đợi để xử lý các lệnh của tôi được kích hoạt từ chương trình bên ngoài.


Tôi tìm thấy liên kết này nơi họ thảo luận về gnu song song với semaphore và thực hiện một số nhận xét liên quan đến bộ đệm nhiệm vụ. Nó có thể hữu ích: unix.stackexchange.com/questions/168978/ trên

Câu trả lời:



4

Sử dụng ;

Ví dụ:
ls ; touch test ; ls

Điều đó sẽ liệt kê các thư mục. Chỉ sau khi lschạy, nó sẽ chạy touch testmột tệp có tên là test. Và chỉ sau khi hoàn thành nó sẽ chạy lệnh tiếp theo. (Trong trường hợp này, một lsnội dung khác sẽ hiển thị nội dung cũ và tệp mới được tạo).

Các lệnh tương tự là ||&&.

; sẽ luôn chạy lệnh tiếp theo.

&&sẽ chỉ chạy lệnh tiếp theo đó là thành công đầu tiên được trả về.
Thí dụ:rm -rf *.mp3 && echo "Success! All MP3s deleted!"

||sẽ chỉ chạy lệnh tiếp theo nếu lệnh đầu tiên trả về giá trị trả về thất bại (khác không). Thí dụ: rm -rf *.mp3 || echo "Error! Some files could not be deleted! Check permissions!"

Nếu bạn muốn chạy một lệnh trong nền, hãy thêm một dấu và ( &).
Thí dụ:
make bzimage &
mp3blaster sound.mp3
make mytestsoftware ; ls ; firefox ; make clean

Sẽ chạy hai lệnh int he nền (trong trường hợp này là một bản dựng kernel sẽ mất một chút thời gian và một chương trình để phát một số nhạc). Và trong các tiền cảnh, nó chạy một công việc biên dịch khác và, sau khi hoàn thành ls, firefox và làm sạch (tất cả tuần tự)

Để biết thêm chi tiết, xem man bash


[Chỉnh sửa sau khi bình luận]

trong mã giả, một cái gì đó như thế này?

Chương trình run_queue:

Trong khi (đúng)
{
   Wait_for_a_signal ();

   Trong khi (hàng đợi không trống)
   {
       chạy lệnh tiếp theo từ hàng đợi.
       loại bỏ lệnh này khỏi hàng đợi.
       // Nếu các lệnh được thêm vào hàng đợi trong khi thực hiện thì
       // hàng đợi không trống, tiếp tục xử lý tất cả.
   }
   // Hàng đợi hiện trống, quay lại Wait_for_a_signal
}
// 
// Đợi mãi các lệnh và thêm chúng vào hàng đợi
// Tín hiệu run_quueu khi một cái gì đó được thêm vào.
//
chương trình add_to_queue ()
{
   Trong khi (đúng)
   {
       Wait_for_event ();
       Nối lệnh để xếp hàng
       tín hiệu run_queue
   }    
}

Như đã cập nhật trong câu hỏi của tôi: Các giải pháp đơn giản như; hoặc && từ bash không hoạt động. Tôi cần lên lịch các lệnh này từ một chương trình bên ngoài, khi một sự kiện xảy ra. Tôi chỉ không muốn có hàng trăm phiên bản lệnh của mình chạy đồng thời, do đó cần một hàng đợi.
Andrei

À. Vâng, điều đó thay đổi nó một chút. :-) Làm thế nào để bạn phát hiện sự kiện? Ai đó nhấp vào một nút (thực sự dựa trên web)? Là một kịch bản bao bọc là một tùy chọn? (if (button_pressed &&! script_rucky) run_my_script. script: đặt tập lệnh cờ đang chạy, lệnh chạy, xóa cờ)
Hennes

Chương trình này là bên ngoài và sẽ kích hoạt một sự kiện trong đó tôi có thể thêm lệnh của riêng mình và về cơ bản tôi muốn xử lý TẤT CẢ các sự kiện được kích hoạt, tôi không muốn bỏ lỡ bất kỳ sự kiện nào, chỉ là tôi cũng không muốn hệ thống của mình gặp sự cố, vì vậy đó là lý do tại sao tôi muốn một hàng đợi để xử lý các lệnh của tôi được kích hoạt bởi chương trình bên ngoài.
Andrei

Đã thêm một số mã giả. add_to_queue () có thể được sửa đổi cho nhiều hàng đợi. Nhưng ... Nếu bạn sẽ dành nhiều nỗ lực đó thì một cái gì đó được xây dựng trước có thể tốt hơn.
Hennes

Vâng, bản thân tôi là một lập trình viên nên tôi có thể viết giải pháp của riêng mình; có lẽ câu hỏi của tôi đã gây hiểu nhầm. Vì tôi muốn chạy cái này trên Pogoplug, tôi đã hy vọng có một cái gì đó tương tự như lệnh "at" sẽ thực hiện những gì tôi muốn. Phần "bash" duy nhất của câu hỏi đề cập đến hy vọng của tôi rằng một giải pháp như vậy có thể được tìm thấy càng gần càng tốt (để có thể sử dụng tài nguyên rẻ, đáng tin cậy / đã được thử nghiệm và có sẵn trên hầu hết mọi thứ Linux).
Andrei

2

Cách đơn giản nhất là chạy các lệnh một cách tuần tự:

cmd1; cmd2; cmd3; cmdN

Nếu bạn muốn các lệnh tiếp theo để chạy chỉ nếu lệnh trước đó đã thoát thành công, sử dụng &&:

cmd1 && cmd2 && cmd3 && cmdN

Đó là cách bash bản địa duy nhất tôi biết để làm những gì bạn muốn. Nếu bạn cần kiểm soát công việc (thiết lập một số công việc song song, v.v.), bạn có thể thử cài đặt trình quản lý hàng đợi như TORQUE nhưng điều đó có vẻ như quá mức nếu tất cả những gì bạn muốn làm là khởi chạy tuần tự.


Cập nhật câu hỏi của tôi: Giải pháp đơn giản như; hoặc && từ bash không hoạt động. Tôi cần lên lịch các lệnh này từ một chương trình bên ngoài, khi một sự kiện xảy ra. Tôi chỉ không muốn có hàng trăm phiên bản lệnh của mình chạy đồng thời, do đó cần một hàng đợi.
Andrei

Hãy nhìn vào TORITE sau đó, bạn cũng có thể viết kịch bản gì đó. Có lẽ một sự kết hợp pgrep foo | wcđể đếm các quá trình đang chạy và hành động phù hợp.
terdon

1

Bạn đang tìm kiếm atngười anh em sinh đôi của mình : batch. Nó sử dụng cùng một daemon nhưng thay vì lên lịch một thời gian cụ thể, các công việc được xếp hàng và sẽ được chạy bất cứ khi nào mức trung bình tải hệ thống thấp.


Nhưng tôi muốn có quyền kiểm soát chính xác về vấn đề này, tôi không muốn hàng loạt quyết định cho tôi. bộ đệm nhiệm vụ có vẻ như có thể thực hiện công việc, nhưng đó là một chương trình hơi mơ hồ.
Andrei

1

Ngoại trừ bộ đệm nhiệm vụ, tôi thực sự không tìm thấy bất cứ thứ gì khác phục vụ nhu cầu này. Tsp là tuyệt vời, nhưng tôi không phải lúc nào cũng có thể biên dịch hoặc cài đặt trên mọi máy chủ mà tôi phải làm việc.

Tôi đã vật lộn với điều này trong một thời gian và sau 3 lần lặp (thực tế là từ phức tạp hơn đến ít hơn), tôi đã nghĩ ra một cách thực hiện bash thuần túy có vẻ hoạt động tốt cho đến nay. Bạn có thể tìm thấy nó tại https://github.com/sitaramc/bq .

Bq sử dụng thực tế là trên Unix, "mv" (trong cùng một hệ thống tệp) là một hoạt động nguyên tử, cho tất cả các nhu cầu khóa của nó.

Nó chỉ là một tập lệnh bash nên việc cài đặt là không đáng kể.

Kịch bản được bình luận tự do và bạn sẽ có thể xem lại trong vài phút nếu bạn muốn.


0

Ngoài các hệ thống xếp hàng chuyên dụng (như Sun Grid Engine ) mà bạn cũng có thể sử dụng cục bộ trên một máy và cung cấp hàng tá khả năng, bạn có thể sử dụng một cái gì đó như

 command1 && command2 && command3

đó là một thái cực khác - một cách tiếp cận rất đơn giản. Cái sau không cung cấp nhiều quá trình đồng thời cũng không làm đầy dần "hàng đợi".


Cập nhật câu hỏi của tôi: Giải pháp đơn giản như; hoặc && từ bash không hoạt động. Tôi cần lên lịch các lệnh này từ một chương trình bên ngoài, khi một sự kiện xảy ra. Tôi chỉ không muốn có hàng trăm phiên bản lệnh của mình chạy đồng thời, do đó cần một hàng đợi.
Andrei

0

Tôi đã đi trên cùng một tuyến đường tìm kiếm, thử bộ đệm nhiệm vụ và vân vân. Điều tốt nhất trong số tốt nhất là đây:

GNU Parallel --semaphore --fg Nó cũng có -j cho các công việc song song.


Câu trả lời này sẽ hữu ích hơn nếu bạn giải thích lệnh này làm gì và lý do sử dụng các tùy chọn / cờ đó.
Anthony Geoghegan
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.