web-dev-qa-db-ja.com

キューのようにコマンドを実行する方法

さまざまなファイルをさまざまなフォルダに大量にコピーする必要があります。すべてのコピーコマンドをbashスクリプトに追加して実行できますが、コピーする "キュー"にコマンドを追加する場合は、完了するまで待つ必要があります。

コマンドをキューとして実行し、実行中にコマンドをキューに追加する方法はありますか?

別の言い方で説明すると、長時間実行するタスクを開始したいと思います。それが実行されている間、私は最初のものが完了するまで実際に開始しない別のものを開始したいと思います。その後、最後の1つを追加します。これはどういうわけか可能ですか?

44
Svish

追加&をコマンドの最後に追加してバックグラウンドに送信し、次にwaitを実行してから次のコマンドを実行します。例えば:

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

at ユーティリティは、指定した時間にコマンドを実行することで最もよく知られており、キュー機能も備えており、コマンドの実行をすぐに開始するように要求できます。実行するコマンドを標準入力から読み取ります。

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

batch コマンドはat -q b -m nowと同等です(-mは、コマンド出力がある場合、cronのようにメールで送信されることを意味します)。すべてのUNIXバリアントがキュー名(-q myqueue)をサポートしているわけではありません。 bという単一のキューに制限される場合があります。 Linuxのatは、1文字のキュー名に制限されています。

ブラッドとマンコフの両方のソリューションが良い提案です。両方の組み合わせに似ているもう1つの方法は、キューを実装するために GNU Screen を使用することです。これには、バックグラウンドで実行できるという利点があり、いつでも確認でき、新しいコマンドをキューに入れると、それらのコマンドをバッファーに貼り付けて、前のコマンドが終了した後に実行されます。

ファーストラン:

$ screen -d -m -S queue

(ちなみに、今は素晴らしい. screenrcファイル で遊ぶ良い機会です)

これにより、名前付きキューのバックグラウンドスクリーンセッションが生成されます。

次に、好きなだけコマンドをキューに入れます。

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

上記のテストでは、複数のコマンドを実行しています。あなたのユースケースはおそらく次のようになります:

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

上記の私の行の "^ M"は、埋め込まれた改行を取得する方法であり、画面が既存のbashシェルに詰め込んだ後で解釈されることに注意してください。 「CTL-V」を使用して、そのシーケンスを取得します。

それを自動化してコマンドをキューに入れる簡単なシェルスクリプトを作成するのはかなり簡単です。次に、バックグラウンドキューのステータスを確認する場合は、次の方法で再接続します。

screen -S queue -r

技術的には、スクリーンセッションに名前を付ける必要すらなくても問題なく動作しますが、それに夢中になったら、とにかく常に1つを実行したままにしたいと思うでしょう。 ;-)

もちろん、これを行う場合、別の良い方法は、現在のウィンドウの1つに「キュー」という名前を付けて使用することです。

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

あなたが説明しているユースケースにぴったりの成功を収めたユーティリティがあります。最近、プライマリラップトップを新しいハードウェアに移動しました。これには、一部のファイルをNASに、残りのファイルを新しいマシンに移動することが含まれていました。

これは私がやった方法です。

  1. 相互に到達できるように、ネットワーク接続に関係するすべてのマシンをセットアップします。

  2. ファイルの移動元のマシン(以下、ソースマシンと呼びます)に、apt-get install rsyncとシークレットソースTask Spoolerを使用してrsyncをインストールします(ウェブサイト http://vicerveza.homeunix.net/~viric/soft/ts/ )。 Debianを使用している場合、tsのパッケージ名はtask-spoolerであり、tspパッケージのts実行可能ファイルと名前が競合しないように、実行可能ファイルの名前はmoreutilsに変更されます。ウェブサイトからリンクされたDebianパッケージは、dpkg -i task-spooler_0.7.3-1_AMD64.debまたは類似のものを使用してUbuntuに完全にインストールできます。

  3. また、すべてのマシンにSSHがapt-get install openssh-serverでインストールされていることを確認してください。ソースマシンでSSHを設定して、ターゲットマシンへのパスワードなしのログインを許可する必要があります。最も使用される方法は、ssh-agentを使用した公開鍵認証です(その例については https://www.google.se/search?q=ssh+public+key+authentication を参照してください) )ですが、パスワード認証と同じように機能する簡単な方法を使用することもあります。以下をSSHクライアント構成に追加します(~/.ssh/configまたは/etc/ssh/ssh_config)。

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

    次に、ソースマシンで1つのターミナルを開き、ssh target1でログインし、通常どおり認証し、このターミナルを開いたままにします。 ~/.ssh/master-user@target1:22という名前のソケットファイルがあることに注意してください。これは、認証されたマスターセッションを開いたままにして、userの後続のパスワードなしの接続を許可するファイルです(接続が同じターゲットホスト名とポートを使用する限り)。

    この時点で、ターゲットマシンへの認証を求められることなくログインできることを確認する必要があります。

  4. 次に、単一のファイルの場合はts rsync -ave ssh bigfile user@target1:を、ディレクトリの場合はts rsync -ave ssh bigdir user@target1:を実行します。 rsyncでは、ディレクトリに末尾のスラッシュを含めないことが重要です(bigdir/と比較してbigdir)。rsyncは、他のほとんどのツールでbigdir/*と同等のものを想定しています。

    タスクスプーラーはプロンプトを返し、これらのコマンドの多くを連続してキューに入れます。引数なしでtsを使用して実行キューを検査します。

タスクスプーラーには、実行キューの再配置、別のジョブが正常に実行された場合にのみ特定のジョブを実行するなど、多くの機能があります。ts -hでヘルプを表示してください。コマンド出力をts -cで実行中に検査することがあります。

これを行う方法は他にもありますが、ユースケースにはすべてタスクスプーラーが含まれています。 SSH経由のrsyncを使用して、SMBを介したコピーにはないファイルのタイムスタンプを保持することにしました。

8
holmb

私もかなり頻繁にこのようなものが必要です。他のプロセスが終了するたびにコマンドを実行するafterという小さなユーティリティを作成しました。次のようになります。

#!/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;

次に、次のように実行します。

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

他のいくつかのアプローチに対するこれの大きな利点は、最初のジョブを特別な方法で実行する必要がなく、新しいジョブで任意のプロセスを実行できることです。

4
Ken Williams

Command1 && Command2

  • 「&&」は、command1が戻りコード0で終了した後にのみcommand2が実行されることを意味します
  • 注:は、command1が戻りコード0以外で終了した後にのみcommand2が実行されることを意味します
2
naftuli

既にコマンドを実行しているシェルのコマンドラインにコマンドを追加するだけです。

慎重に入力するか、他の場所に入力して確認し、カットアンドペーストしてください。現在のコマンドが出力行を吐き出していても、何か新しいものを入力してEnterキーを押すと、すべてのコマンドが実行されるか、入力が完了する前に実行されます。

以下に例を示します。全体をカットアンドペーストするか、1番目のコマンドが実行されているときに次のコマンドを入力するか(本当に高速で入力した場合)、2番目のコマンドが実行されているときに入力することができます。

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

私が考える最も奇妙な方法は、/ tmpにある単純なロックファイルでキューの「状態」を維持することです。 file1.shがcpコマンドを実行しているときは、ロックファイル(またはハードリンク)を/ tmpに保持します。完了したら、ファイルを消去します。他のすべてのスクリプトは、選択した命名方式でロックファイルを探すために/ tmpを調べる必要があります。当然これはあらゆる種類の障害の影響を受けますが、セットアップするのは簡単で、bash内で完全に実行できます。

0
Brad Clawsie