GNU/Linux >> Linux の 問題 >  >> Linux

Bash:無限スリープ (無限ブロッキング)

tail ブロックしません

いつものように、すべてについて、短く、理解しやすく、従うのが簡単で、完全に間違っている答えがあります.こちら tail -f /dev/null このカテゴリに分類されます;)

strace tail -f /dev/null で見ると このソリューションはブロックにはほど遠いことに気付くでしょう。おそらく sleep よりもさらに悪いです inotify のような (Linux の下で) 貴重なリソースを使用するため、問題の解決策 システム。 /dev/null に書き込む他のプロセスも tail にする ループ。 (私の Ubuntu64 16.10 では、これにより、既にビジー状態のシステムに 1 秒あたり 10 回のシステムコールが追加されます。)

問題はブロッキング コマンドでした

残念ながらそんなことはありません..

読む:これをシェルで直接アーカイブする方法がわかりません。

すべて (sleep infinity でも) ) 何らかの信号によって中断される可能性があります。したがって、例外的に返されないことを本当に確認したい場合は、 sleep で既に行ったように、ループで実行する必要があります . (Linux では) /bin/sleep であることに注意してください。 明らかに 24 日間が上限です (strace sleep infinity を見てください)。 )、したがって、おそらくできる最善のことは次のとおりです。

while :; do sleep 2073600; done

(私は sleep を信じていることに注意してください) は 24 日を超える値に対して内部的にループしますが、これは次のことを意味します。ブロックしているのではなく、非常にゆっくりとループしています。では、このループを外側に移動してみませんか?)

..しかし、名前のない fifo でかなり近づくことができます

プロセスにシグナルが送信されない限り、実際にブロックするものを作成できます。以下は bash 4 を使用しています 、2 つの PID と 1 つの fifo :

bash -c 'coproc { exec >&-; read; }; eval exec "${COPROC[0]}<&-"; wait'

strace でこれが実際にブロックされていることを確認できます よろしければ:

strace -ff bash -c '..see above..'

これがどのように構築されたか

read 入力データがない場合はブロックします(他の回答を参照してください)。ただし、tty (別名 stdin ) は、ユーザーがログアウトすると閉じられるため、通常は適切なソースではありません。また、tty からの入力を盗む可能性もあります。 .良くない。

read にする fifo のようなものを待つ必要があります。 これは何も返しません。 bash 4 で そのような fifo を正確に提供できるコマンドがあります :coproc .ブロッキング read も待つ場合 (これは coproc です )、これで完了です。悲しいことに、これは 2 つの PID と fifo を開いたままにしておく必要があります .

fifo という名前のバリアント

名前付きの fifo をわざわざ使用しない場合 、これは次のように行うことができます:

mkfifo "$HOME/.pause.fifo" 2>/dev/null; read <"$HOME/.pause.fifo"

読み取りでループを使用しないのは少しずさんですが、この fifo を再利用できます 好きなだけ read を作ってください touch "$HOME/.pause.fifo" を使用した終端 (複数の読み取り待機がある場合は、すべてが一度に終了します)。

または Linux pause() を使用します システムコール

無限ブロッキングには、pause() と呼ばれる Linux カーネル呼び出しがあります。 、これは私たちが望むことを行います:永遠に (シグナルが到着するまで) 待ちます。ただし、このためのユーザー空間プログラムは (まだ) ありません。

C

このようなプログラムを作成するのは簡単です。 pause という非常に小さな Linux プログラムを作成するためのスニペットを次に示します。 無期限に一時停止します (diet が必要です) 、 gcc など):

printf '#include <unistd.h>\nint main(){for(;;)pause();}' > pause.c;
diet -Os cc pause.c -o pause;
strip -s pause;
ls -al pause

python

自分で何かをコンパイルしたくないが、python がある場合 これを Linux で使用できます:

python -c 'while 1: import ctypes; ctypes.CDLL(None).pause()'

(注:exec python -c ... を使用してください 現在のシェルを置き換えるために、これにより 1 つの PID が解放されます。このソリューションは、未使用の FD を解放して、いくつかの IO リダイレクトでも改善できます。これはあなた次第です。)

これがどのように機能するか (私は思う):ctypes.CDLL(None) 標準 C ライブラリをロードし、pause() を実行します いくつかの追加ループ内で機能します。 C バージョンよりも効率は劣りますが、機能します。

おすすめ:

ループスリープにとどまります。理解しやすく、移植性が高く、ほとんどの場合ブロックされます。


sleep infinity それが示唆することを正確に実行し、猫の虐待なしで機能します.


Linux
  1. bash エクスポート コマンド

  2. bash で複数のバックグラウンド コマンドを 1 行で実行するにはどうすればよいですか?

  3. jenkins パイプラインで bash コマンドを実行する

  1. Bashスクリプト(I)

  2. BashスクリプトでのLinuxスリープコマンドの使用

  3. bash または ksh で 1 ミリ秒間スリープする方法

  1. Bashエクスポート変数

  2. Bash待機コマンド

  3. bash での並べ替え