web-dev-qa-db-ja.com

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

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

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

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

どうすれば両方を入手できますか?

12
Tyilo

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

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

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

これを{ba,z}shで行う方法を次に示します。

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

# Run the command given by "$@" in the background
silent_background() {
  if [[ -n $ZSH_VERSION ]]; then  # zsh:  https://superuser.com/a/1285272/365890
    setopt local_options no_notify no_monitor
    "$@" &
  Elif [[ -n $BASH_VERSION ]]; then  # bash: https://stackoverflow.com/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メッセージを生成します。

3
Tom Hale

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

ここでは、「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、「ジョブ」セクションを参照してください。 job control が無効の場合、これらの通知は表示されません。

[〜#〜]モニター[〜#〜]-m、ksh:-m

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

zsh_Prompt % setopt no_monitor
zsh_Prompt % true & echo true
true
zsh_Prompt %
zsh_Prompt % 

Bash

Bashは常に表示されているようです。 [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 $

結論

job control を無効にして通知を非表示にするのが良いことかどうかわかりません。

資源

2
Fólkvangr

zshを非インタラクティブシェルとして呼び出して、ジョブ通知を無効にすることができます。

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

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

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

0
Philippe

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

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

それはうまくいきます。必要なし ( ):不要なサブシェルを作成します。 { }は単なるグループ化コマンドです。

0
Gilles Quenot