シグナルを待ってバックグラウンドでアイドル状態のシェルスクリプトを作成しようとしています。スクリプトがユーザー入力を許可しないため、read
待っている間にスクリプトを無期限にブロックしたいと思います。
Bashでは、次のコードは期待どおりに動作しているように見え、SIGUSR1が受信されるたびに「信号」を出力します。
#!/bin/bash
trap "echo signal" SIGUSR1
read
$ ./test
signal
signal
...
ただし、BusyBox ashを使用して実行している場合は、#!/bin/sh
SIGUSR1を送信するとプログラムが終了します。
#!/bin/sh
trap "echo signal" SIGUSR1
read
$ ./test
signal
$
read
標準入力からEOFまたはIFSを読み込んだ後にのみ返すべきではありませんか?この場合、そのようなことは起こりません。それで返される原因は何ですか?
答え1
DashとBusyBoxはPOSIX仕様に準拠しているため、信号がread
すぐに終了する可能性があります。 Bash は、次の場合を除き、そうではありません。POSIXモード。このセクションは次のとおりです。シグナル状態
シェルがユーティリティのフォアグラウンドコマンドの実行が完了するのを待っている間にトラップセット信号が受信されると、その信号に関連するトラップはフォアグラウンドコマンドが完了するまで実行されません。
read
一つでもない特殊内蔵、同じプロセス内で実行しても「フォアグラウンドコマンドで実行されるユーティリティ」です。これはトラップを実行し、実行を続行するbash動作を排除しますread
。
このセクションは次のとおりです。実行環境ユーティリティの実行時に信号がどのように機能するかを明確にしました(非特殊組み込み機能も含む)。
ユーティリティがシェルスクリプトの場合、シェルによってキャプチャされたトラップはデフォルト値に設定され、シェルで無視されるトラップはユーティリティを無視に設定する必要があります。ユーティリティがシェルスクリプトでない場合、トラップ操作(デフォルトまたは無視)は次のように設定する必要があります。ユーティリティの適切な信号処理タスクにマッピング
組み込みスクリプトはシェルスクリプトではありませんが、まだスクリプトを実行しているシェルの一部として実行されているため、最初の句を適用できます。ただし、どちらの動作も、ユーティリティが親トラップを実行することを許可しません。可能な唯一の動作は、read
信号を無視、ブロック、またはすぐに返すことです。説明read
信号への言及がないため、標準信号に対するマスクの変更は許可されず、無視できません。read
間違いなく完了するまで信号を遮断できます(プログラムは内部目的のために一時的に信号を遮断できます)。しかし、これはread
入力を待っている間にSIGINTをブロックしたくない風と衝突します(Occamのかみそりの刃はそうすることは意味がないと言います)。 SIGINTの場合、これは動作です。したがって、read
SIGUSR1(mkshが機能する方法)で何もしないことは、技術的に規制に準拠することができますが、合理的な行動だとは思わない。
DashとBusyBoxはPOSIXと完全に互換性がありません。信号によって中断されると、両方(Ubuntu 22.04ベース)$?
1に設定されます。read
終了ステータス。
信号の受信によって終了するコマンドは、128を超える終了状態を報告する必要があります。
(実際にはATT kshが256+信号値であることを除いては128+信号値です。)