バックグラウンドで静かにタスクを開始する


12

これを使用してプロセスがバックグラウンドで開始され、プロセスがバックグラウンドで実行されたときや、そのように実行されたときに通知を受け取らないことを知っています。

(コマンド&)&> / dev / null

ただし、これにより、プロセスが終了したときにトラップするオプションが削除されます(trap child_done CHLD)。

どうすれば両方ができますか?

回答:


5

task-spoolerが役立つかもしれません。

同様にfreshmeat.net

タスクスプーラーは、スプールされたタスクが次々と実行されるUnixバッチシステムです。一度に実行するジョブの数はいつでも設定できます。各システムの各ユーザーには、独自のジョブキューがあります。タスクは任意のシェル/プロセスから正しいコンテキスト(エンキューのコンテキスト)で実行され、その出力/結果を簡単に監視できます。コマンドが多くのRAM、多くのディスク使用量に依存している、大量の出力が得られている、または何らかの理由でコマンドを同時に実行しない方がよいとわかっている場合は、非常に役立ちます。リソースを最大限に活用するために忙しい。そのインターフェースにより、スクリプトで簡単に使用できます。

タスクスプーラーはDebian、Ubuntu、その他のディストリビューションで利用できます。

実行するタスクのキューを用意し、必要に応じてその出力にアクセスできます。

例えば:

$ tsp sleep 5
0 
$ tsp sleep 5 
1
$ tsp
ID   State      Output               E-Level  Times(r/u/s)   Command [run=1/1]
2    running    /tmp/ts-out.ZWn6Le                           sleep 5
1    finished   /tmp/ts-out.Fhlcle   0        5.00/0.00/0.01 sleep 5

バックグラウンドで多くのジョブを実行する場合、それは間違いなく役立ちます。

それらを順番に実行することも、事前設定されたスロット数で実行することもできます。(実行あなたはまた、タスク間の依存関係を確立することができますタスク1をする場合にのみtask0が正常に完了しました)。


3

両方で行う方法は次のとおり{ba,z}shです。

関数を使用すると、を使用してzshmonitor変数の状態を保存および復元する必要がなくなりますsetopt local_options

# Run the command given by "$@" in the background
silent_background() {
  if [[ -n $ZSH_VERSION ]]; then  # zsh:  /superuser//a/1285272/365890
    setopt local_options no_notify no_monitor
    "$@" &
  elif [[ -n $BASH_VERSION ]]; then  # bash: /programming//a/27340076/5353461
    { 2>&3 "$@"& } 3>&2 2>/dev/null
  else  # Unknownness - just background it
    "$@" &
  fi
}

これを次のように使用します。

trap 'echo child done' CHLD
silent_background sleep 1

期待されるchild doneメッセージを生成します。


希望に満ちた説明については、unix.stackexchange.com / q / 456549/4778を参照してください。
ctrl-alt-delor 2018

2

ジョブが非同期に開始されたときにシェルによって通知が送信されるため、コマンド出力のリダイレクトは無関係であると思われます。より正確には、ジョブ制御に関連するシェル機能(機能)です。

ここでは、「Bashリファレンスマニュアル」の「ジョブコントロール」の章のセクション1から引用しています。

シェルは、JOBを各パイプラインに関連付けます。現在実行中のジョブのテーブルを保持しますjobs。これは、コマンドでリストされる場合があります。Bashが非同期でジョブを開始すると、次のような行が出力されます。

[1] 25647

このジョブがジョブ番号1であり、このジョブに関連付けられたパイプラインの最後のプロセスのプロセスIDが25647であることを示しています。単一のパイプラインのすべてのプロセスは、同じジョブのメンバーです。Bashはジョブ制御の基礎としてJOB抽象化を使用します。

シェルスクリプトはこの通知を表示しないことに注意してください。

$ cat test
#!/bin/bash

true & echo true
$ ./test
true

実際には

Zsh

Zshのドキュメントには、これらの通知に関する同様の表示が含まれていman 1 zshmiscます。「JOBS」のセクションを参照してください。ジョブ制御が無効になっている場合、これらの通知は表示されません。

モニター-m、ksh:-m

    ジョブ制御を許可します。対話型シェルではデフォルトで設定されます。

zsh_prompt % setopt no_monitor
zsh_prompt % true & echo true
true
zsh_prompt %
zsh_prompt % 

バッシュ

Bashは常にegを表示するようです[1] 25647。「最終通知」[1]+ Done trueは、ジョブ制御が無効になっている場合などには表示されません。

bash_prompt $ true & echo true
[1] 25647
true
bash_prompt $ 
[1]+  Done                    true

ジョブ制御が無効になっています

bash_prompt $ set +m       # disable job control
bash_prompt $ true & echo true
[1] 25685
bash_prompt $
bash_prompt $

結論

ジョブコントロールを無効にして通知を非表示にするのが良いことかどうかわかりません。

資源


1

zsh非対話型シェルとして起動して、ジョブ通知を無効にすることができます。

zsh -c '
   trap "echo trapped child_done" CHLD
   sleep 5 &
   #wait
   sleep 10 # simulate other running cmds
   echo script done
'

0

次の例を参照してください。

trap 'echo "DONE"' 0
{ find /usr & } &> /dev/null
wait

それはうまくいきます。不要( ):それは不要なサブシェルになります。{ }コマンドをグループ化するだけです。


これはと[2] 49591[2] + 49591 exit 1 find /usr印刷します。
Tyilo、2012年

申し訳ありませんが、あなたの質問を誤解しています。
Gilles Quenot、2012年

0

これは古い質問ですが、可能な答え(bashではzshでテストされていません)は、サブシェルでジョブコントロールを使用することです。 (command & wait)

注:bashはサブシェルでバックグラウンドジョブの開始/終了メッセージを抑制し、リダイレクトする必要はありません。


トラップのある部分を逃したと思います。サブプロセスを開始する必要があるという質問を理解している限り、supprocessの実行中に何かが行われ、サブプロセスが終了したときに何かが実行されます。ソリューションでは、サブプロセスを開始してサブシェルで待機し、メインシェルはサブシェルを待機します。これはメッセージを取り除きますが、並行して何かを行うことはできません。
Raphael Ahrens 2017

いいえ、(sleep 5 & wait)5秒遅れます。
トム・ヘイル
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.