startx
を使用してXを起動し、.xinitrc
を評価します。 .xinitrc
で、/usr/bin/mywm
を使用してウィンドウマネージャーを起動します。さて、WMを(他のWMをテストするために)強制終了すると、.xinitrc
スクリプトがEOFに達したため、Xも終了します。 .xinitrc
の最後にこれを追加しました:
while true; do sleep 10000; done
このように、WMを殺してもXは終了しません。ここで私の質問:スリープをループする代わりに無限スリープを実行するにはどうすればよいですか?スクリプトをフリーズするようなコマンドがありますか?
宜しくお願いします
sleep infinity
は、猫が虐待することなく、提案したとおりに機能します。
これはthisいように思えるかもしれませんが、なぜcat
を実行して入力を永遠に待たせないのでしょうか?
tail
はブロックしませんいつものように、すべてに答えは短く、理解しやすく、従いやすく、完全に間違っています。ここで_tail -f /dev/null
_はこのカテゴリに分類されます;)
_strace tail -f /dev/null
_で見ると、この解決策はブロッキングにはほど遠いことに気づくでしょう! (_Linux)sleep
システムのような貴重なリソースを使用するため、問題のinotify
ソリューションよりもさらにひどいでしょう。 _/dev/null
_に書き込む他のプロセスもtail
ループを作成します。 (私のUbuntu64 16.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
sを_touch "$HOME/.pause.fifo"
_を使用して終端することができます単一の読み取り待機、すべてが一度に終了します)。
pause()
syscallを使用します無限ブロッキングには、pause()
と呼ばれるLinuxカーネル呼び出しがあります。これは、必要な処理を行います:永遠に待機します(シグナルが到着するまで)。ただし、このためのユーザー空間プログラムはまだありません。
このようなプログラムの作成は簡単です。 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 ...
_を使用します。これによりPIDが1つ解放されます。ソリューションはIOリダイレクトも使用して改善できます。 )
これがどのように機能するか(私は思う):ctypes.CDLL(None)
は標準Cライブラリをロードし、追加のループ内でpause()
関数を実行します。 Cバージョンよりも効率的ではありませんが、動作します。
ループスリープ状態を維持します。理解しやすく、移植性が高く、ほとんどの場合ブロックされます。
TL; DR:_sleep infinity
_は、実際には許容される最大時間(有限です)スリープします。
なぜこれがどこにも文書化されていないのか疑問に思ったので、 sources from GNU coreutils を読むことに悩まされました。
strtod
を使用して、 'infinity'を倍精度に変換します。したがって、IEEE 754の倍精度を仮定すると、64ビットの正の無限大値がseconds
変数に格納されます。xnanosleep(seconds)
を呼び出します( gnulibにあります )、これはdtotimespec(seconds)
( gnulibにもあります )を呼び出してdouble
を_struct timespec
_に。struct timespec
_は、整数部分(秒単位)と小数部分(ナノ秒単位)の単なる数字のペアです。単純に正の無限大を整数に変換すると、未定義の動作になり(C標準の6.3.1.4を参照)、代わりにTYPE_MAXIMUM (time_t)
に切り捨てられます。TYPE_MAXIMUM (time_t)
の実際の値は標準では設定されていません(sizeof(time_t)
でさえ設定されていません)。例として、最近のLinuxカーネルからx86-64を選択してみましょう。これは、Linuxカーネルでは_TIME_T_MAX
_であり、次のように定義されています( _time.h
_ )
_(time_t)((1UL << ((sizeof(time_t) << 3) - 1)) - 1)
_
_time_t
_は___kernel_time_t
_であり、_time_t
_はlong
;です。 LP64データモデルが使用されるため、sizeof(long)
は8(64ビット)です。
結果:_TIME_T_MAX = 9223372036854775807
_。
つまり、_sleep infinite
_は、9223372036854775807秒(10 ^ 11年)の実際のスリープ時間になります。また、32ビットLinuxシステムの場合(sizeof(long)
は4(32ビット)):2147483647秒(68年。 2038年問題 も参照)。
Edit:明らかに、呼び出されるnanoseconds
関数は直接syscallではなく、OS依存のラッパーです(また gnulib )。
結果として余分なステップがあります:_HAVE_BUG_BIG_NANOSLEEP
_がtrue
であるシステムでは、スリープは24日に切り捨てられ、ループで呼び出されます。これは、一部の(またはすべての)Linuxディストリビューションの場合です。 configure-timeテストが成功した場合(- source )、このラッパーは使用できないことに注意してください。
特に、それは_24 * 24 * 60 * 60 = 2073600 seconds
_(プラス999999999ナノ秒)になります。ただし、これは、指定された合計スリープ時間を尊重するためにループで呼び出されます。したがって、以前の結論は引き続き有効です。
結論として、結果の睡眠時間は無限ではありませんが、実際の時間経過が移植可能でない場合でも、すべての実用的な目的に十分な長さです。それはOSとアーキテクチャに依存します。
元の質問に答えるために、これは明らかに十分ですが、何らかの理由で(非常にリソースに制約のあるシステム)、無駄な余分なカウントダウンタイマーを避けたい場合は、最も正しい代替方法は、他の回答で説明されているcat
メソッドを使用することです。
sleep infinity
は最もエレガントに見えますが、何らかの理由で機能しない場合があります。その場合は、cat
、read
、tail -f /dev/null
、grep a
などの他のブロックコマンドを試すことができます。
[〜#〜] sigstop [〜#〜] を自分自身に送信するのはどうですか?
これにより、SIGCONTが受信されるまでプロセスが一時停止します。それはあなたの場合です:決して。
kill -STOP "$$";
# grace time for signal delivery
sleep 60;
私は最近これを行う必要がありました。外部プログラムを呼び出さずにbashを永久にスリープ状態にできる次の関数を思い付きました。
snore()
{
local IFS
[[ -n "${_snore_fd:-}" ]] || { exec {_snore_fd}<> <(:); } 2>/dev/null ||
{
# workaround for MacOS and similar systems
local fifo
fifo=$(mktemp -u)
mkfifo -m 700 "$fifo"
exec {_snore_fd}<>"$fifo"
rm "$fifo"
}
read ${1:+-t "$1"} -u $_snore_fd || :
}
注:以前に毎回ファイル記述子を開いたり閉じたりするこのバージョンを投稿しましたが、一部のシステムではこれを1秒間に数百回行うと最終的にロックされることがわかりました。したがって、新しいソリューションは、関数の呼び出し間でファイル記述子を保持します。 Bashはとにかく終了時にクリーンアップします。
これは/ bin/sleepと同じように呼び出すことができ、要求された時間だけスリープします。パラメータなしで呼び出されると、永久にハングします。
snore 0.1 # sleeps for 0.1 seconds
snore 10 # sleeps for 10 seconds
snore # sleeps forever
このアプローチは、プロセスを維持するためのリソースを消費しません。
while :; do sleep 1; done & kill -STOP $! && wait $!
while :; do sleep 1; done &
バックグラウンドでダミープロセスを作成しますkill -STOP $!
バックグラウンドプロセスを停止しますwait $!
バックグラウンドプロセスを待ちます。これは永久にブロックされるため、バックグラウンドプロセスが停止する前にウィンドウマネージャーを強制終了する代わりに、--replace
または -replace
可能な場合は。