暗くて風の多い夜。突然銃声が出ました!

暗くて風の多い夜。突然銃声が出ました!

ターミナルエミュレータを使用してUbuntu 16.04を実行しています。

2つのスクリプトがあります:a.shb.sh。  a.sh着信電話b.sh

a.sh

echo "a is running"
sleep 5s
bash b.sh
sleep 5s
echo "a is still running"

b.sh

echo "b is now running"
sleep 1000s
echo "Bananas"

a.sh実行して完了する前にb.sh(バナナを印刷する前に)停止し、a.sh実行を完了して「a is still running」を印刷する方法はありますか?

pkill -f b.sh入れてみようとしましたが、a.shどちらもa.sh終わるb.sh前に停止しましたa.sh

答え1

ある瞬間に欲しいものに近づいたようです。

a.sh

#!/bin/sh

echo "a.sh running"
sleep 10s
(sleep 10s; pkill -f b.sh) &
bash b.sh
sleep 10s
pkill -f b.sh
echo "a.sh still running"

b.sh    (あなたのバージョンと同じ)

echo "b is now running"
sleep 1000s
echo "Bananas"

(sleep 10s; pkill -f b.sh) &a.sh の行は、10秒間休止してから終了するサブシェルを作成しますb.sh。その後、サブシェルをバックグラウンドに配置してa.sh実行し続けることができます。  a.sh次に実行してb.sh実行しますsleep 1000s。 10秒後にsleep 10sサブシェルが完了し、そのサブシェルが実行され、プロセスが  pkill -f b.sh終了します。その後、ジョブを再開します。 2番目のプロセスはすでに終了しているため、何もしません。b.sha.shpkill -f b.shb.sh

実行すると、次のことが起こります。

$./a.sh
再実行                                              #即時
bは今実行中です                                          #上記の内容から約10秒後
./a.sh: 6行目: 13684 bash b.sh 終了     #上記の内容から約10秒後
a.shはまだ実行中です。                                        #上記の内容から約10秒後
$                                                         #上の直後

a.shすぐに完了するとすぐに再開できるという利点があります。 10秒以上実行されているb.sh場合にのみ開始されます。もう一つの答えでは、それが終わっても時間がかかる前にアイドル状態でなければなりません。b.shpkilla.shsleeppkillb.sh


他のユーザー解放するコメント(現在は削除されました)さんが言った

わかりました。

./a.sh
a.sh running
b is now running
Terminated

あなたが報告した内容ではありません。どんなアイデアがありますか?

暗くて風の多い夜。突然銃声が出ました!

        暗くて嵐の夜だ、スヌーピー 著者:チャールズM.シュルツ

pgrepand の引数pkillは正規表現です。特に拡張正規表現1です。2つをcat同時にcut実行してみてください。その後、実行すると両方のPIDが一覧表示されていることを確認できます。 pgrep c.tpscatcut

もしそうだったら正確に私が言ったように、あなたも私と同じ結果を得なければなりません。しかし、私はあなたが何か他のことをしたことに42人のZorkmidsを歩きたいと思います。あなたは次のいずれかを行います:

  1. a.sh#!/bin/bash代わりにshe-bang(最初の行)で始まる#!/bin/sh
  2. a.sh代わりに実行しbash a.shてください./a.sh

突然銃声が出ました!

b.shb 後ろにランダムな文字が続き、後ろに続く正規表現です。sh自体(b.sh)と一致しb!shb~sh、 、b&shなどb7shにも一致します。bushそして…(待ってください)…やっぱりうまくいきますbash

したがって、pkill -f b.shすべてのbashプロセス、およびb.sh名前に含まれる他のプロセスも終了します。私が実行しているものを実行すると、私のログインシェル(少なくとも部分的にbashの影響を受けませんpkill)はbashですがa.sh実行中です/bin/sh (しかしb.sh実行中ですbash)。このpkill -f b.shコマンドには以下がbash b.sh含まれているため、プロセスを終了します。両方 bashそしてb.sh。しかし、/bin/sh実行中のものはa.sh影響を受けません。

私が信じるように実行すると仮定すると(2つのオプションのうちの1つ)、 みんなスクリプトプロセスが実行中ですbash。だからpkill -f b.sh命令が死んだみんなスクリプトプロセス。

pkill -f b.sh(エスケープポイントに変更してpkill -f 'b\.sh' 一致させます。ただ文字以外の点)正しい結果を得る必要があります。
________
1 pgrep(1)
2 2つの端末(シェルウィンドウ)がある場合は、cat | cut -f11つの端末で実行(端末の入力を使用)し、p別の端末で-コマンドを実行します。端末のみがある場合は実行し、sleep 42 | cat | cut -f1 & (そうでない場合はsleepパイプラインがすぐにクラッシュする)、p同じウィンドウで-commandsを実行します。

答え2

銀行:

bash b.sh

スクリプトが完了するのを待ってb.sh制御できないため、スクリプトが終了するまでスクリプトで何もできません。b.sha.sh

b.shスクリプトをバックグラウンドに移動して再制御を許可するには、a.sh次のようなコマンドを使用します。

bash b.sh &

これにより、すぐに制御権が返され、a.sh次のスクリプトを取得できます。

#!/bin/bash 

echo "a is running"
sleep 1s
bash b.sh &
sleep 2
pkill -f 'b\.sh'
sleep 1s
echo "a is still running"

スクリプトはb.shまだ次のようになります。

#!/bin/bash
echo "b is now running"
sleep 1000s
echo "Bananas"

実行後、次のようになります。

$ ./a.sh
a is running
b is now running
./a.sh: line 7:  8424 Terminated              bash b.sh
a is still running

「ジョブ制御メッセージ」を避けるには、サブシェルを使用して次のようbash b.sh &に変更します。

(bash b.sh &)

そして実行すると、次のようになります。

$ ./a.sh
a is running
b is now running
a is still running

編集する:

「kill」応答で報告した問題は、実行したpkillコマンドがパラメータをpkill -f b.sh正規表現で使用していることです。正規表現は、後に続くbすべての文字と一致します。これは「bash」という名前と一致し、プログラムも実行を開始します。これは、プログラムが終了した理由を説明します。 pkillコマンドを次のように変更します。.sha.sha.sh

pkill -f 'b\.sh'

一致する正規表現が通常の文字列 "b.sh"であることを確認してください。

次のように入力して、pkillが一致するプロセスを確認できます。

ps -f -o pid,cmd,args |grep 'b.sh'

pkillの直前。

grep 'b\.sh'実際に1つのpidだけが一致することを確認するように修正されました。

答え3

スクリプトを早期に終了するには、スクリプトをバックグラウンドジョブとして実行するa.sh必要があります。b.sh

バックグラウンドジョブとして実行されるため、対応するb.shプロセスID(PID)にアクセスできます。つまり、killこれを使用して信号をエクスポートできます。これはpkill、提供されたパターンに一致する他のプロセスに信号を送信するための使用よりも安全です。

以下では、次のことができますa.sh

#!/bin/sh

echo "A: I'm alive!"
./b.sh & bpid=$!

echo 'A: Sleeping for a short while'
sleep 2

echo 'A: Signalling B'
kill "$bpid"

echo "A: I'm done here"

$!最後に開始されたバックグラウンドジョブのPIDに展開されます。

b.sh:

#!/bin/sh

echo "B: I'm alive!"

echo 'B: Sleeping for longer than A does'
sleep 10

echo "B: I'm done here"

実行してください:

$ ./a.sh
A: I'm alive!
A: Sleeping for a short while
B: I'm alive!
B: Sleeping for longer than A does
A: Signalling B
A: I'm done here

呼び出しが完了するまでb.sh実際に終了しないことがあります。 、およびの場合は該当しますが、sleepすぐには終了しません。bashdashzshpdkshksh93b.sh

答え4

私は次の方法を使用しました。必要に応じて動作するようにb.shに行を追加しました。

a.shスクリプトは同じです。

script a.sh

echo "a is running"
sleep 5s
bash b.sh
sleep 5s
echo "a is still running"

================================================== ===

script b.sh

echo "b is now running"
sleep 20s

exit

==>exit コマンドがスクリプトから出力されます。

echo "Bananas"

出力

   a is running
b is now running
a is still running

関連情報