web-dev-qa-db-ja.com

印刷ジョブおよびプロセスIDなしでバックグラウンドでbashコマンドを実行する

Bashでバックグラウンドでプロセスを実行するのは非常に簡単です。

$ echo "Hello I'm a background task" &
[1] 2076
Hello I'm a background task
[1]+  Done                    echo "Hello I'm a background task"

ただし、出力は冗長です。 1行目には、バックグラウンドタスクのジョブIDとプロセスIDが出力され、コマンドの出力があり、最後にジョブID、そのステータス、ジョブをトリガーしたコマンドがあります。

バックグラウンドタスクの実行の出力を抑制して、出力が最後にアンパサンドがない場合とまったく同じように見えるようにする方法はありますか?つまり:

$ echo "Hello I'm a background task" &
Hello I'm a background task

私が尋ねる理由は、タブ補完コマンドの一部としてバックグラウンドプロセスを実行したいので、そのコマンドの出力が意味をなさないように中断されない必要があるからです。

62
Alex Spurling

完了とは関係ありませんが、呼び出しをサブシェルに入れることでその出力を抑制することができます。

(echo "Hello I'm a background task" &)
76

Bashの一部の新しいバージョンおよびksh93では、サブシェルまたはプロセスグループで囲むことができます(つまり、{ ... })。

/home/shellter $ { echo "Hello I'm a background task" & } 2>/dev/null
Hello I'm a background task
/home/shellter $
11
shellter

@shellterの回答を基に、これは私にとってはうまくいきました。

tyler@Tyler-Linux:~$ { echo "Hello I'm a background task" & disown; } 2>/dev/null; sleep .1;
Hello I'm a background task
tyler@Tyler-Linux:~$

この背後にある理由はわかりませんが、古い投稿で、bownがプロセスIDを出力できないことが原因であると思い出しました。

10
Tyzoid

コマンドからstderrが通過できるようにする必要がある場合は、上記の回答に基づいてください。

f() { echo "Hello I'm a background task" >&2; }
{ f 2>&3 &} 3>&2 2>/dev/null
6
pajamian

この回答 に基づいて、私はより簡潔で正しいものを思いつきました:

silent_background() {
    { 2>&3 "$@"& } 3>&2 2>/dev/null
    disown &>/dev/null  # Prevent whine if job has already completed
}
silent_background date
5
Tom Hale

古い投稿への返信で申し訳ありませんが、私はこれが他の人にとって有用であり、Googleでの最初の返信であると考えています。

この方法(サブシェル)で問題が発生し、「待機」を使用していました。ただし、関数内で実行しているため、これを行うことができました。

function a {
    echo "I'm background task $1"
    sleep 5
}

function b {
    for i in {1..10}; do
        a $i &
    done
    wait
} 2>/dev/null

そして、私がそれを実行すると:

$ b
I'm background task 1
I'm background task 3
I'm background task 2
I'm background task 4
I'm background task 6
I'm background task 7
I'm background task 5
I'm background task 9
I'm background task 8
I'm background task 10

そして、プロンプトを戻すまでに5秒の遅延があります。

4
The Tomahawk

試してください:

user@Host:~$ read < <( echo "Hello I'm a background task" & echo $! )
user@Host:~$ echo $REPLY
28677

そして、output[〜#〜] pid [〜#〜]の両方を非表示にしました。 $ -REPLYから[〜#〜] pid [〜#〜]を取得できることに注意してください。

4
mark_infinite

サブシェルソリューションは動作しますが、バックグラウンドジョブで待機できるようにしたかった(そして最後に「完了」メッセージが表示されないようにしました)。 $!は、現在の対話型シェルでは「待機可能」ではありません。私のために働いた唯一の解決策は、非常に簡単な独自の待機関数を使用することでした:

myWait() {
  while true; do
    sleep 1; STOP=1
    for p in $*; do
      ps -p $p >/dev/null && STOP=0 && break
    done
    ((STOP==1)) && return 0
  done
}

i=0
((i++)); p[$i]=$(do_whatever1 & echo $!)
((i++)); p[$i]=$(do_whatever2 & echo $!)
..
myWait ${p[*]}

簡単です。

1
ExpertNoob1