シェルスクリプトでは、(1)バックグラウンドでコマンドを開始する方法(2)x秒待機する方法(3)そのコマンドの実行中に2番目のコマンドを実行する方法を教えてください。


11

これは私が起こる必要があるものです:

  1. バックグラウンドでプロセスAを開始
  2. x秒待つ
  3. フォアグラウンドでプロセスBを開始

どうすれば待機を実現できますか?

「スリープ」はすべてを停止するように見えますが、実際にはプロセスAが完全に終了するのを「待機」したくありません。時間ベースのループをいくつか見てきましたが、もっときれいなものがあるかどうか疑問に思っています。


4
あなたがすでに試したことの簡単な例を提供することによって、この質問を強化することをお勧めします。
アンディダルトン2017

10
sleepプロセスA を停止する印象はどこで得られますか?使用しているテストプロセス、またはこれを示す出力を表示できますか?プロセスA 停止している場合、に関連するものではなく、バックグラウンドで実行中に端末から読み取りを試み、その理由で停止している可能性が高くなりsleepます。
チャールズダフィー

3
それがあれば... である場合、process_a </dev/null &にその標準入力を添付します/dev/nullむしろTTYよりも、それは問題を回避するのに十分であり得ます。
チャールズダフィー

私の経験では、睡眠は現在のプロセスのみをブロックし、したがって&でバックグラウンドで以前に開始されたプロセスはブロックしません
MADforFUNandHappy

回答:


28

私があなたの質問を誤解していない限り、それはこの短いスクリプトで簡単に達成できます:

#!/bin/bash

process_a &
sleep x
process_b

waitスクリプトprocess_aが終了する前に終了するのを待つ場合は、最後に追加を追加します)。

(@BaardKopperudによって提案されているように)スクリプトを必要とせずに、これをワンライナーとして実行することもできます。

process_a & sleep x ; process_b

6
その必要はないことに注意してbashください。システムのを含むシェルはすべてsh実行するため、スクリプトのbashに依存関係を追加する必要はありません。
ステファンChazelas

4
または単に:process_a&sleep x; process_b
Baard Kopperud

9

あなたは使用することができ、バックグラウンド制御演算子(&)を背景としてプロセスを実行するためsleepのコマンドすなわち、第二のプロセスを実行する前に待機します:

#!/usr/bin/env bash
# script.sh

command1 &
sleep x
command2

次に、タイムスタンプ付きのメッセージを出力する2つのコマンドの例を示します。

#!/usr/bin/env bash

# Execute a process in the background
echo "$(date) - Running first process in the background..."
for i in {1..1000}; do
    echo "$(date) - I am running in the background";
    sleep 1;
done &> background-process-output.txt &

# Wait for 5 seconds
echo "$(date) - Sleeping..."
sleep 5 

# Execute a second process in the foreground
echo "$(date) - Running second process in the foreground..."
for i in {1..1000}; do
    echo "$(date) - I am running in the foreground";
    sleep 1;
done

それを実行して、目的の動作を示すことを確認します。

user@host:~$ bash script.sh

Fri Dec  1 13:41:10 CST 2017 - Running first process in the background...
Fri Dec  1 13:41:10 CST 2017 - Sleeping...
Fri Dec  1 13:41:15 CST 2017 - Running second process in the foreground...
Fri Dec  1 13:41:15 CST 2017 - I am running in the foreground
Fri Dec  1 13:41:16 CST 2017 - I am running in the foreground
Fri Dec  1 13:41:17 CST 2017 - I am running in the foreground
Fri Dec  1 13:41:18 CST 2017 - I am running in the foreground
Fri Dec  1 13:41:19 CST 2017 - I am running in the foreground
Fri Dec  1 13:41:20 CST 2017 - I am running in the foreground
...
...
...

2
質問は、「プロセスBをフォアグラウンドで開始する」ように求めます。
スパーホーク2017

1
@Sparhawkうわー。完全に誤解-説明なし。ヘッドアップをありがとう-コードが修正されました。あなたのユーザー名からの深刻な郷愁、ところで。
igal 2017

1
心配ない!(また、ユーザー名は元々このchapへの参照でしたが、後になってそれがエディングスのキャラクターであることに気づきました!そして、私はそれらの本を
もう一度

5

私は@ dr01の答えが好きですが、彼は終了コードをチェックしないので、あなたが成功したかどうかはわかりません。

終了コードをチェックするソリューションは次のとおりです。

#!/bin/bash

# run processes
process_a &
PID1=$!
sleep x
process_b &
PID2=$!
exitcode=0

# check the exitcode for process A
wait $PID1    
if (($? != 0)); then
    echo "ERROR: process_a exited with non-zero exitcode" >&2
    exitcode=$((exitcode+1))
fi

# check the exitcode for process B
wait $PID2
if (($? != 0)); then
    echo "ERROR: process_b exited with non-zero exitcode" >&2
    exitcode=$((exitcode+1))
fi
exit ${exitcode}

通常、PIDをbash配列に格納し、pidチェックはforループです。


2
あなたのようなスクリプトの終了ステータスでそれらの終了コードを反映することをお勧めしますA & sleep x; B; ret=$?; wait "$!" || exit "$ret"
ステファンChazelas

1
@StéphaneChazelasいい考えです。コードを更新して、1つまたは両方が失敗した場合にゼロ以外の終了コードが返されるようにしました。
トレバーボイドスミス

OP process_bはフォアグラウンドで実行することを望んでいます。おそらく実行process_a中に終了する可能性process_bがありますがwait、フォアグラウンドの終了ステータスprocess_b$?直接、通常の方法で収集した後でも、そのままで終了ステータスを取得できます。
ピーターコーデス
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.