47

bashを使用して、バックグラウンドで並列でいくつかのコマンドを実行しようとしています。これが私がやろうとしていることです:

forloop {
  //this part is actually written in perl
  //call command sequence
  print `touch .file1.lock; cp bigfile1 /destination; rm .file1.lock;`;
}

バックティック( ``)の間の部分は、新しいシェルを生成し、コマンドを連続して実行します。つまり、元のプログラムへの制御は、最後のコマンドが実行された後にのみ戻ります。ステートメント全体をバックグラウンドで実行したいのですが(出力/戻り値は期待していません)、ループを実行し続けたいと思います。

呼び出し元のプログラム(ループを持つプログラム)は、生成されたすべてのシェルが終了するまで終了しません。

perlのスレッドを使用して、さまざまなシェルを呼び出すさまざまなスレッドを生成することもできますが、それはやり過ぎのようです...

シェルを起動し、一連のコマンドを与えて、バックグラウンドに移動するように指示できますか?

4

15 に答える 15

32

私はこれをテストしていませんが、どうですか

print `(touch .file1.lock; cp bigfile1 /destination; rm .file1.lock;) &`;

括弧はサブシェルで実行することを意味しますが、それは問題ありません。

于 2008-10-02T08:24:17.067 に答える
21

ありがとうございます。

adrianp@frost:~$ (echo "started"; sleep 15; echo "stopped")
started
stopped
adrianp@frost:~$ (echo "started"; sleep 15; echo "stopped") &
started
[1] 7101
adrianp@frost:~$ stopped

[1]+  Done                    ( echo "started"; sleep 15; echo "stopped" )
adrianp@frost:~$ 

他のアイデアは、コマンド シーケンスではなくバックグラウンドで各コマンドを開始するため、機能しません (私の場合はこれが重要です)。

ありがとうございました!

于 2008-10-02T08:42:23.560 に答える
14
for command in $commands
do
    "$command" &
done
wait

コマンドの末尾にあるアンパサンドは、コマンドをバックグラウンドで実行しwait、バックグラウンド タスクが完了するまで待機します。

于 2008-10-02T08:02:41.063 に答える
5

GavinCattellが最も近い(bash、IMOの場合)が、Mad_Adyが指摘したように、「ロック」ファイルを処理しませんでした。これは次のようになります。

保留中の他のジョブがある場合、待機はそれらも待機します。コピーだけを待つ必要がある場合は、それらのPIDを累積して、それらだけを待つことができます。そうでない場合は、「pids」を使用して3行を削除できますが、より一般的です。

さらに、コピーを完全に回避するためのチェックを追加しました。

pids=
for file in bigfile*
do
    # Skip if file is not newer...
    targ=/destination/$(basename "${file}")
    [ "$targ" -nt "$file" ] && continue

    # Use a lock file:  ".fileN.lock" for each "bigfileN"
    lock=".${file##*/big}.lock"
    ( touch $lock; cp "$file" "$targ"; rm $lock ) &
    pids="$pids $!"
done
wait $pids

ちなみに、新しいファイルをFTPリポジトリ(または同様のもの)にコピーしているようです。もしそうなら、あなたはロックファイルの代わりにコピー/名前変更戦略を検討することができます(しかしそれは別のトピックです)。

于 2009-11-05T20:11:52.683 に答える
3

あなたが探している bash の機能は と呼ばれCompound Commandsます。詳細については、man ページを参照してください。

複合コマンド 複合コマンドは、次のいずれかです。

   (list) list  is  executed  in a subshell environment (see COMMAND EXECUTION ENVIRONMENT below).  Variable assignments and
          builtin commands that affect the shell's environment do not remain in effect after  the  command  completes.   The
          return status is the exit status of list.

   { list; }
          list  is  simply  executed in the current shell environment.  list must be terminated with a newline or semicolon.
          This is known as a group command.  The return status is the exit status of list.  Note that unlike the metacharac‐
          ters  (  and  ),  {  and  } are reserved words and must occur where a reserved word is permitted to be recognized.
          Since they do not cause a word break, they must be separated from list by whitespace or another shell  metacharac‐
          ter.

他にもありますが、これらはおそらく最も一般的な 2 つのタイプです。最初の括弧は、サブシェルで一連のコマンドのリストを実行しますが、2 番目の中括弧は、現在のシェルで一連のコマンドのリストを実行します。

括弧

% ( date; sleep 5; date; )
Sat Jan 26 06:52:46 EST 2013
Sat Jan 26 06:52:51 EST 2013

中括弧

% { date; sleep 5; date; }
Sat Jan 26 06:52:13 EST 2013
Sat Jan 26 06:52:18 EST 2013
于 2013-01-26T12:05:49.843 に答える
2

at ジョブを使用してコマンドを実行します。

# date
# jue sep 13 12:43:21 CEST 2012
# at 12:45
warning: commands will be executed using /bin/sh
at> command1
at> command2
at> ...
at> CTRL-d
at> <EOT>
job 20 at Thu Sep 13 12:45:00 2012

結果はメールでアカウントに送信されます。

于 2012-09-13T10:52:40.503 に答える
2

サブシェルでコマンドを実行します。

(command1 ; command2 ; command3) &
于 2016-11-19T10:18:19.670 に答える
2

ここでこのスレッドに出くわし、チェーンされたステートメントをバックグラウンド ジョブとして生成するコード スニペットをまとめることにしました。Linux 用の BASH、IBM AIX 用の KSH、および Android 用の Busybox の ASH でこれをテストしたので、 Bourne のようなシェルで動作すると言っても過言ではありません。

processes=0;
for X in `seq 0 10`; do
   let processes+=1;
   { { echo Job $processes; sleep 3; echo End of job $processes; } & };
   if [[ $processes -eq 5 ]]; then
      wait;
      processes=0;
   fi;
done;

このコードは、同時実行ジョブの特定の制限まで、多数のバックグラウンド ジョブを実行します。たとえば、これを使用して、大量のプロセスがメモリ全体を消費し、コンピューターをスローさせることxzなく、gzip で圧縮された多数のファイルを再圧縮できます。この場合、 のリストとして使用すると、バッチ ジョブはする。xz*forgzip -cd "$X" | xz -9c > "${X%.gz}.xz"

于 2014-04-08T21:48:18.920 に答える
1

なぜ誰も適切な解決策で答えなかったのか分かりません:

my @children;
for (...) {
    ...
    my $child = fork;
    exec "touch .file1.lock; cp bigfile1 /destination; rm .file1.lock;" if $child == 0;
    push @children, $child;
}
# and if you want to wait for them to finish,
waitpid($_) for @children;

これにより、Perlは子を生成して各コマンドを実行し、続行する前にすべての子が完了するのを待つことができます。

ところで、

print `some command`

system "some command"

同じ内容をstdoutに出力しますが、Perlは " some command"の出力をすべてキャプチャする必要があるため、最初の方がオーバーヘッドが高くなります。

于 2008-10-03T21:45:55.243 に答える
1

for ループでフォークする:

for i in x; do ((a; b; c;)&); done

例:

for i in 500 300 100; do ((printf "Start $i: "; date; dd if=/dev/zero of=testfile_$i bs=1m count=$i 2>/dev/null; printf "End $i: "; date;)&) && sleep 1; done

于 2014-11-01T02:53:59.517 に答える
1

次のように、&s を使用してコマンドを中括弧で囲みます。

{command1 & ; command2 & ; command3 & ; }

これはサブシェルを作成しませんが、コマンドのグループをバックグラウンドで実行します。

HTH

于 2008-10-02T08:05:24.177 に答える
0

GNUparallelコマンドを使用して、ジョブを並行して実行できます。速いほど安全です。

複数の大きなファイルをソースから宛先にコピーしようとしていると思います。そのために、以下のステートメントと並行してそれを行うことができます。

$ ls *|parallel -kj0 --eta 'cp {} /tmp/destination'

オプションを使用したため-j0、すべてのファイルが並行してコピーされます。並列プロセスの数を減らす必要がある場合は、実行する並列プロセスの数を使用でき-j<n>ます<n>

Parallel はまた、プロセスの出力を収集し、-k他のジョブ制御メカニズムでは実行できない順次的な方法 (オプションを使用) で報告します。

--etaオプションは、進行中のプロセスの詳細な統計を提供します。そのため、プロセスのどれくらいが完了したか、完了するまでにどれくらいの時間がかかるかを知ることができます。

于 2014-11-01T07:23:02.933 に答える