Cách chạy lệnh như trong hàng đợi


42

Tôi cần phải sao chép nhiều tập tin khác nhau vào các thư mục khác nhau. Tôi có thể thêm tất cả các lệnh sao chép của mình vào tập lệnh bash và sau đó chạy nó, nhưng sau đó tôi phải đợi cho đến khi nó kết thúc nếu tôi muốn thêm nhiều lệnh hơn vào "hàng đợi" sao chép đó.

Có cách nào để tôi có thể chạy các lệnh như một hàng đợi và sắp xếp thêm các lệnh vào hàng đợi đó trong khi mọi thứ đang chạy không?

Giải thích theo một cách khác, tôi muốn bắt đầu một nhiệm vụ dài. Trong khi nó đang chạy, tôi muốn bắt đầu một cái khác không thực sự bắt đầu cho đến khi cái đầu tiên được thực hiện. Và sau đó thêm một cái khác sau cái cuối cùng và cứ thế. Đây có phải là có thể bằng cách nào đó?


3
Tôi có thể đề nghị bạn chấp nhận một câu trả lời giải quyết vấn đề của bạn. Dường như có một vài trong số họ sẽ làm việc cho bạn.
holmb

2
Có bạn có thể, và tôi đã muốn. Vấn đề là tôi đã hỏi điều này khi tôi làm việc tại một công ty đang sử dụng máy Mac. Tôi không còn làm việc ở đó nữa, bản thân tôi cũng không có máy Mac nên tôi không có cách nào kiểm tra bất kỳ máy nào trong số này. Đừng cảm thấy thoải mái với việc đánh dấu một câu trả lời khi tôi không thể kiểm tra xem nó có thực sự hiệu quả hay không, vì vậy bây giờ tôi đã hy vọng rằng mọi người bỏ phiếu cho những câu trả lời mà họ thấy phù hợp với họ để "câu trả lời" có thể xuất hiện theo cách đó thay thế.
Svish

Câu trả lời:


25

Các attiện ích, nổi tiếng nhất để chạy các lệnh tại một thời điểm nhất định, cũng có một tính năng xếp hàng và có thể được yêu cầu để bắt đầu lệnh chạy ngay bây giờ. Nó đọc lệnh để chạy từ đầu vào tiêu chuẩn.

echo 'command1 --option arg1 arg2' | at -q myqueue now
echo 'command2 ...' | at -q myqueue now

Các batchlệnh tương đương với at -q b -m now( -mnghĩa là đầu ra lệnh, nếu có, sẽ được gửi đến bạn, giống như cron không). Không phải tất cả các biến thể unix đều hỗ trợ tên hàng đợi ( -q myqueue); bạn có thể bị giới hạn trong một hàng đợi được gọi b. Linux atbị giới hạn ở tên hàng đợi một chữ cái.


2
Trên linux ít nhất điều này dường như không chờ lệnh trước đó kết thúc.
wds 16/2/2015

@wds Hoạt động với tôi trên Debian wheezy. Nó đã phá vỡ ở đâu và như thế nào? Lưu ý rằng chỉ chờ lệnh kết thúc; nếu lệnh khởi chạy các quy trình con tồn tại lâu hơn cha mẹ của chúng, thì không chờ đợi các quy trình con.
Gilles 'SO- ngừng trở nên xấu xa'

Tôi đã thử trên CentOS 6. Tôi đã thử nghiệm chỉ với một "giấc ngủ x" đơn giản. Tôi không chắc chắn những gì sẽ làm để chạy nó nhưng tôi giả sử nó bắt đầu một subshell và subshell đó sẽ chờ kết quả (một cuộc gọi ngủ không trở lại ngay lập tức).
wds 17/215

Cũng như tên hàng đợi, 'bây giờ' cũng không xuất hiện tiêu chuẩn: bash trên
ubfox

@winwaed Ồ now, không -t now, xin lỗi. Tôi đã không nhận thấy tôi đã sai nó trong mã mẫu.
Gilles 'SO- ngừng trở nên xấu xa'

23

Nối &vào cuối lệnh của bạn để gửi nó đến nền, và sau đó waitvào nó trước khi chạy tiếp theo. Ví dụ:

$ command1 &
$ wait; command2 &
$ wait; command3 &
$ ...

2
vâng cú pháp này thật tuyệt vời khi bạn đã khởi động một cái gì đó và sau đó nhìn vào stackoverflow để tìm cách xếp hàng thứ gì đó sau nó
Erik Aronesty

2
Nếu bạn thay đổi suy nghĩ về bất kỳ lệnh nào trong thời gian đó, bạn có thể làm gì để hủy bỏ wait? Nó dường như không thấm vào tất cả các vụ giết người của tôi.
Ken Williams

1
Bạn chỉ cần giết lệnh. Việc waitđơn giản là dừng công việc cho đến khi những người trước kết thúc.
Gert Sønderby

Điều này sẽ làm việc với nohup?
Michael

11

Cả hai giải pháp của Brad và Mankoff đều là những gợi ý tốt. Một cách khác tương tự như sự kết hợp của cả hai sẽ là sử dụng GNU Screen để thực hiện hàng đợi của bạn. Điều này có lợi thế là có thể chạy trong nền, bạn có thể kiểm tra nó bất cứ khi nào và xếp hàng các lệnh mới chỉ dán chúng vào bộ đệm để được thực thi sau khi thoát lệnh trước đó.

Đầu tiên, chạy:

$ screen -d -m -S queue

(tình cờ, bây giờ là thời điểm tốt để chơi với một số tệp screenrc tuyệt vời )

Điều đó sẽ sinh ra một phiên màn hình nền cho hàng đợi được đặt tên của bạn.

Bây giờ, xếp hàng nhiều lệnh như bạn muốn:

screen -S queue -X stuff "echo first; sleep 4; echo second^M"

Tôi đang thực hiện nhiều lệnh ở trên chỉ để thử nghiệm. Trường hợp sử dụng của bạn có thể sẽ trông giống như:

screen -S queue -X stuff "echo first^M"
screen -S queue -X stuff "echo second^M"

Lưu ý rằng "^ M" trong dòng của tôi ở trên là cách để có được một dòng mới được nhúng sẽ được giải thích sau khi màn hình nhét nó vào vỏ bash hiện tại của bạn. Sử dụng "CTL-V" để có được chuỗi đó.

Sẽ khá dễ dàng để tạo một số tập lệnh shell đơn giản để tự động hóa lệnh đó và xếp hàng các lệnh. Sau đó, bất cứ khi nào bạn muốn kiểm tra trạng thái của hàng đợi nền, bạn sẽ đính kèm lại qua:

screen -S queue -r

Về mặt kỹ thuật, bạn thậm chí không cần đặt tên cho phiên màn hình của mình và nó sẽ hoạt động tốt, nhưng một khi bạn bị cuốn hút vào nó, bạn sẽ muốn để một cái chạy mọi lúc. ;-)

Tất nhiên, nếu bạn làm điều đó, một cách tốt khác để làm điều đó là đặt tên cho một trong các cửa sổ hiện tại là "xếp hàng" và sử dụng:

screen -S queue -p queue -X stuff "command"

Có vẻ như về cơ bản, đây chỉ là "gõ" lệnh trong phiên màn hình đang chạy, để khi shell được điều khiển lại sau khi lệnh đầu tiên kết thúc, lệnh này sẽ bắt đầu. Nói cách khác, nó tương đương với giải pháp của @ mankoff, nhưng sử dụng công cụ fancier để gõ.
Ken Williams

Khá nhiều - sự khác biệt chính là giải pháp màn hình hỗ trợ tự động hóa tốt hơn. Bạn có thể làm một số thứ bằng tay, những thứ khác với các tập lệnh, tất cả đều có giao diện đơn giản.
Jordan

@Jordan Rất tốt, nó làm việc cho tôi. Nhưng "công cụ" cho sau -X là gì?
Konstantin

@Konstantin gnu.org/software/screen/manual/html_node/Paste.html#Paste (TL; DR - nhét bất cứ thứ gì vào thiết bị đầu cuối như thể bạn đã nhập nó)
Jordan

@Jordan ơi, tôi hiểu rồi. Đó là một mệnh lệnh. Tôi nghĩ đó là một chuỗi tùy ý.
Konstantin

8

Có một tiện ích mà tôi đã sử dụng rất thành công cho chính xác trường hợp sử dụng mà bạn đang mô tả. Gần đây tôi đã chuyển máy tính xách tay chính của mình sang phần cứng mới, bao gồm việc chuyển một số tệp sang NAS và phần còn lại của chúng sang máy mới.

Đây là cách tôi đã làm nó.

  1. Thiết lập tất cả các máy liên quan đến kết nối mạng để chúng có thể liên lạc với nhau.

  2. Trên máy mà bạn đang di chuyển các tệp từ (sau đây gọi là máy nguồn), hãy cài đặt rsync với apt-get install rsyncvà Bộ đệm nhiệm vụ nước sốt bí mật (trang web http://vicerveza.homeunix.net/~viric/soft/ts/ ). Nếu bạn đang sử dụng Debian, tên gói tstask-spoolervà tệp thực thi được đổi tên tspđể tránh xung đột tên với tstệp thực thi từ moreutilsgói. Gói Debian được liên kết từ trang web hoàn toàn có thể cài đặt trên Ubuntu bằng dpkg -i task-spooler_0.7.3-1_amd64.debhoặc tương tự.

  3. Cũng đảm bảo rằng tất cả các máy đã cài đặt SSH apt-get install openssh-server. Trên máy nguồn, bạn cần thiết lập SSH để cho phép đăng nhập không mật khẩu vào các máy đích. Phương thức được sử dụng nhiều nhất là xác thực khóa công khai với ssh-agent(xem https://www.google.se/search?q=ssh+public+key+authentication để biết ví dụ về điều đó), nhưng đôi khi tôi sử dụng một phương thức dễ dàng hơn chỉ hoạt động cũng như với xác thực mật khẩu. Thêm phần sau vào cấu hình máy khách SSH của bạn (hoặc ~/.ssh/confighoặc /etc/ssh/ssh_config):

    Host *
         ControlMaster auto
         ControlPath ~/.ssh/master-%r@%h:%p
    

    Sau đó mở một thiết bị đầu cuối trên máy nguồn, đăng nhập bằng ssh target1, xác thực như bình thường và sau đó để thiết bị đầu cuối này mở. Lưu ý rằng có một tệp socket được đặt tên ~/.ssh/master-user@target1:22, đây là tệp sẽ giữ một phiên chính được xác thực mở và cho phép các kết nối không mật khẩu tiếp theo cho user(miễn là kết nối sử dụng cùng tên máy chủ và cổng đích).

    Tại thời điểm này, bạn cần xác minh rằng bạn có thể đăng nhập mà không được nhắc xác thực với các máy đích.

  4. Bây giờ chạy ts rsync -ave ssh bigfile user@target1:cho một tập tin duy nhất hoặc ts rsync -ave ssh bigdir user@target1:cho một thư mục. Với rsync, điều quan trọng là không bao gồm dấu gạch chéo trên thư mục ( bigdirso với bigdir/) hoặc rsync sẽ cho rằng bạn có nghĩa là tương đương với bigdir/*hầu hết các công cụ khác.

    Bộ đệm nhiệm vụ sẽ trả về dấu nhắc và cho phép bạn xếp hàng nhiều lệnh này liên tiếp. Kiểm tra hàng đợi chạy tsmà không có đối số.

Bộ đệm nhiệm vụ có nhiều tính năng như sắp xếp lại hàng đợi chạy, chỉ chạy một công việc cụ thể nếu một công việc khác chạy thành công, v.v. Xem trợ giúp với ts -h. Đôi khi tôi kiểm tra đầu ra lệnh trong khi nó đang chạy với ts -c.

Có các phương pháp khác để làm điều này nhưng đối với trường hợp sử dụng của bạn, tất cả chúng đều bao gồm Bộ đệm nhiệm vụ. Tôi chọn sử dụng rsync qua SSH để duy trì dấu thời gian của tệp, việc sao chép qua SMB sẽ không có.


cảm ơn vì câu trả lời của bạn mà tôi không biết ts, có vẻ rất mạnh mẽ và dễ sử dụng, chỉ cần rẽ nhánh trên github được tự động hóa và gỡ lỗi.
Alex

@Alex Tôi đã xem xét về ngã ba của bạn và đặc biệt quan tâm đến những gì đã được thực hiện liên quan đến tự động hóa và gỡ lỗi nguồn gốc, và nhìn vào cam kết của bạn, nó không có sẵn như là một nguồn khác với nguồn gốc. Bạn có phiền khi đẩy các cam kết mới trong bước 1. nhập nguồn gốc và 2. cam kết với các bổ sung của bạn không? Nó sẽ giúp ai đó duyệt nguồn của bạn (dễ dàng hơn) tin tưởng các bổ sung của bạn vào nguồn ban đầu. Đây là một trong số ít các gói tôi không cài đặt từ PPA hoặc tương tự, vì vậy sẽ rất tốt nếu bạn tự xây dựng nó bằng ngã ba của mình.
holmb

bạn biết tôi đã thay kính, tôi đã mất một phần câu trả lời của bạn về câu hỏi hiện có task-spooler:-) ... dù sao, trong nhận xét của bạn là một gợi ý rất hay, tôi sẽ làm rất sớm.
Alex

thực hiện, xóa và tạo lại kho lưu trữ với các cam kết lũy tiến, chỉ một vài lỗi (nên chuyển hóa nhiều cam kết cục bộ hơn trước khi đẩy)
Alex

4

Tôi cũng cần những thứ như thế này khá thường xuyên. Tôi đã viết một tiện ích nhỏ được gọi là afterthực thi lệnh bất cứ khi nào một quá trình khác kết thúc. Nó trông như thế này:

#!/usr/bin/perl

my $pid = shift;
die "Usage: $0 <pid> <command...>" unless $pid =~ /^\d+$/ && @ARGV;

print STDERR "Queueing process $$ after process $pid\n";
sleep 1 while -e "/proc/$pid";
exec @ARGV;

Sau đó, bạn chạy nó như vậy:

% command1 arg1 arg2 ...  # creates pid=2853
% after 2853 command2 arg1 arg2 ... # creates pid=9564
% after 9564 command3 arg1 arg2 ...

Lợi thế lớn cho điều này so với một số cách tiếp cận khác là công việc đầu tiên không cần phải được thực hiện theo bất kỳ cách đặc biệt nào, bạn có thể làm theo bất kỳ quy trình nào với công việc mới của mình.


Kịch bản hay @ken. Mặc dù tôi khuyên bạn nên dùng thử Bộ đệm nhiệm vụ vì đôi khi bạn dường như yêu cầu điều này. Xem câu trả lời của tôi.
holmb

Trông gọn gàng, cảm ơn. Một điều còn thiếu của TS dường như là khả năng theo dõi các công việc chưa bắt đầu dưới TS. Mặc dù tôi đoán bạn có thể bắt đầu một công việc TS mới với mục đích chỉ là chờ đợi một quy trình hiện có kết thúc.
Ken Williams

Thật. Đó là một khía cạnh hữu ích của giải pháp của bạn.
holmb

2

Lệnh1 && Lệnh2

  • "&&" có nghĩa là lệnh2 chỉ chạy sau khi lệnh1 kết thúc với mã trả về 0
  • Lưu ý: a | | có nghĩa là lệnh2 chỉ chạy sau khi lệnh1 kết thúc với mã trả về Khác 0

1

Bạn chỉ có thể thêm các lệnh vào dòng lệnh shell đang chạy lệnh.

Nhập cẩn thận hoặc nhập nó ở nơi khác, xác minh và cắt và dán. Ngay cả khi lệnh hiện tại đang phun ra các dòng đầu ra, bạn vẫn có thể nhập một cái gì đó mới, nhấn enter và nó sẽ chạy khi tất cả các lệnh chạy hoặc nhập trước khi hoàn thành.

Ví dụ sau. Bạn có thể cắt và dán toàn bộ, hoặc nhập các lệnh tiếp theo trong khi lệnh 1 đang chạy (nếu bạn gõ thực sự rất nhanh), hoặc nhiều khả năng trong khi thứ 2 đang chạy:

echo "foo"
sleep 10; echo "bar"
sleep 3
echo "baz"

0

cách tốt nhất tôi có thể nghĩ đến là duy trì "trạng thái" hàng đợi với các tệp khóa đơn giản trong / tmp. khi file1.sh đang thực hiện các lệnh cp của nó, nó sẽ giữ một tệp khóa (hoặc liên kết cứng) trong / tmp. Khi xong, xóa tệp. mọi tập lệnh khác sẽ phải tìm trong / tmp để tìm các tệp khóa với sơ đồ đặt tên bạn chọn. tự nhiên điều này là đối tượng của tất cả các loại thất bại, nhưng nó là tầm thường để thiết lập và hoàn toàn có thể thực hiện được trong bash.


Khó sử dụng trong thực tế, vì nó đòi hỏi rằng tất cả các công việc mà bạn muốn chạy cần phải được sửa đổi để giữ các tập tin khóa, và cần phải biết (hoặc chấp nhận như các thông số) khóa các tập tin để sử dụng. Bất cứ khi nào có thể, tốt nhất là có hàng đợi bên ngoài công việc.
Ken Williams
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.