我使用startx
启动X,这将评估我的.xinitrc
。在我的.xinitrc
中,我使用/usr/bin/mywm
启动了我的窗口管理器。现在,如果我杀了我的WM(为了测试其他一些WM),X也会因为.xinitrc
脚本达到EOF而终止。
所以我在.xinitrc
:
while true; do sleep 10000; done
这样,如果我杀了我的WM,X就不会终止。现在我的问题是:如何进行无限睡眠而不是循环睡眠?是否有一个命令会冻结脚本?
祝你好运
答案 0 :(得分:247)
sleep infinity
完全符合其建议,并且不会虐待猫。
答案 1 :(得分:64)
也许这看起来很丑陋,但为什么不运行cat
让它等待输入呢?
答案 2 :(得分:50)
tail
不会阻止一如既往:对于一切都有一个简短,易于理解,易于理解和完全错误的答案。此处tail -f /dev/null
属于此类别;)
如果你用strace tail -f /dev/null
看一下,你会注意到,这个解决方案远非阻止!它可能比问题中的sleep
解决方案更糟糕,因为它使用(在Linux下)宝贵的资源,如inotify
系统。写入/dev/null
的其他进程也会使tail
循环。 (在我的Ubuntu64 16.10上,这在已经繁忙的系统上每秒增加了10个系统调用。)
阅读:我不知道如何直接将它归档到shell。
所有信息(偶数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
(aka。stdin
)通常不是一个好的来源,因为它在用户注销时关闭。它也可能从tty
窃取一些输入。不太好。
要使read
阻止,我们需要等待fifo
之类的东西,它永远不会返回任何东西。在bash 4
中,有一个命令可以为我们提供这样的fifo
:coproc
。如果我们还等待阻止read
(我们的coproc
),我们就完成了。遗憾的是,这需要保持打开两个PID和fifo
。
fifo
如果您不打扰使用已命名的fifo
,则可以按以下方式执行此操作:
mkfifo "$HOME/.pause.fifo" 2>/dev/null; read <"$HOME/.pause.fifo"
在阅读中不使用循环有点草率,但您可以根据需要重复使用此fifo
,并使用read
生成touch "$HOME/.pause.fifo"
s终止(如果有不止一次读取等待,所有都立即终止。)
pause()
系统调用对于无限阻塞,有一个名为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 ...
替换当前shell,这将释放一个PID。解决方案也可以通过一些IO重定向进行改进,释放未使用的FD。这取决于你。)
这是如何工作的(我认为):ctypes.CDLL(None)
加载标准C库并在一些额外的循环中运行其中的pause()
函数。效率低于C版本,但有效。
保持循环睡眠状态。它易于理解,非常便携,并且在大多数情况下都会阻止。
答案 3 :(得分:20)
TL; DR:sleep infinity
实际上睡了允许的最长时间,这是有限的。
想知道为什么没有在任何地方记录这一点,我打扰阅读sources from GNU coreutils,我发现它大致执行以下内容:
strtod
将“无穷大”转换为双精度。因此,假设IEEE 754双精度,64位正无穷大值存储在seconds
变量中。xnanosleep(seconds)
(found in gnulib),然后调用dtotimespec(seconds)
(also in 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年;另见year 2038 problem)。
编辑:显然调用的nanoseconds
函数不是直接的系统调用,而是依赖于操作系统的包装器(也是defined in gnulib)。
结果还有一个额外步骤:对于HAVE_BUG_BIG_NANOSLEEP
为true
的某些系统,睡眠被截断为24天,然后循环调用。某些(或所有?)Linux发行版就是这种情况。请注意,如果 configure -time测试成功(source),则可能无法使用此包装。
特别是,24 * 24 * 60 * 60 = 2073600 seconds
(加上999999999纳秒);但是这是在循环中调用的,以便遵守指定的总睡眠时间。因此,先前的结论仍然有效。
总之,由此产生的睡眠时间并非无限但足以满足所有实际目的,即使由此产生的实际时间流逝不可移植;这取决于操作系统和架构。
要回答原来的问题,这显然已经足够好但是如果由于某种原因(非常资源受限的系统)你真的想避免一个无用的额外倒数计时器,我猜最正确另一种方法是使用其他答案中描述的cat
方法。
答案 4 :(得分:8)
sleep infinity
看起来最优雅,但有时因某种原因无效。在这种情况下,您可以尝试其他阻止命令,例如cat
,read
,tail -f /dev/null
,grep a
等。
答案 5 :(得分:5)
如何向自己发送SIGSTOP呢?
这应暂停该过程,直到收到SIGCONT。在你的情况下:永远不会。
kill -STOP "$$";
# grace time for signal delivery
sleep 60;
答案 6 :(得分:4)
让我解释一下sleep infinity
的工作原理,尽管它没有记载。 jp48's answer也很有用。
最重要的事情:通过指定inf
或infinity
(不区分大小写),您可以在实现允许的最长时间内睡眠(即HUGE_VAL
的较小值和TYPE_MAXIMUM(time_t)
。
现在让我们深入研究细节。 sleep
命令的源代码可以从coreutils/src/sleep.c中读取。本质上,该函数执行此操作:
double s; //seconds
xstrtod (argv[i], &p, &s, cl_strtod); //`p` is not essential (just used for error check).
xnanosleep (s);
xstrtod (argv[i], &p, &s, cl_strtod)
xstrtod()
根据gnulib/lib/xstrtod.c,对xstrtod()
的调用使用转换函数argv[i]
将字符串*s
转换为浮点值并将其存储到cl_strtod()
cl_strtod()
从coreutils/lib/cl-strtod.c可以看出,cl_strtod()
使用strtod()
将字符串转换为浮点值。
strtod()
根据man 3 strtod
,strtod()
将字符串转换为类型double
的值。手册页上说
(字符串的初始部分)预期的形式是...或(iii)无穷大,或者...
和无穷大定义为
不管大小写,无穷大都是“ INF”或“ INFINITY”。
尽管文件说明了
如果正确的值将导致溢出,则返回正负
HUGE_VAL
(HUGE_VALF
,HUGE_VALL
)
,尚不清楚如何处理无穷大。因此,让我们看一下源代码gnulib/lib/strtod.c。我们想读的是
else if (c_tolower (*s) == 'i'
&& c_tolower (s[1]) == 'n'
&& c_tolower (s[2]) == 'f')
{
s += 3;
if (c_tolower (*s) == 'i'
&& c_tolower (s[1]) == 'n'
&& c_tolower (s[2]) == 'i'
&& c_tolower (s[3]) == 't'
&& c_tolower (s[4]) == 'y')
s += 5;
num = HUGE_VAL;
errno = saved_errno;
}
因此,INF
和INFINITY
(均不区分大小写)被视为HUGE_VAL
。
HUGE_VAL
家庭
让我们使用N1570作为C标准。 {§12-3
中定义了HUGE_VAL
,HUGE_VALF
和HUGE_VALL
宏
宏
HUGE_VAL
扩展为正的双常量表达式,不一定可以表示为float。宏
HUGE_VALF
HUGE_VALL
分别是HUGE_VAL
的float和long double类似物。
在支持无限性的实现中,HUGE_VAL
,HUGE_VALF
和HUGE_VALL
可以是肯定无限性。
以及第7.12.1-5
条如果浮点结果溢出且默认舍入有效,则该函数根据返回类型返回宏
HUGE_VAL
,HUGE_VALF
或HUGE_VALL
的值
xnanosleep (s)
现在,我们了解了xstrtod()
的所有本质。根据上面的解释,很明显我们首先看到的xnanosleep(s)
实际上是指xnanosleep(HUGE_VALL)
。
xnanosleep()
根据源代码gnulib/lib/xnanosleep.c,xnanosleep(s)
实际上是这样做的:
struct timespec ts_sleep = dtotimespec (s);
nanosleep (&ts_sleep, NULL);
dtotimespec()
此函数将double
类型的参数转换为struct timespec
类型的对象。由于它非常简单,因此让我引用源代码gnulib/lib/dtotimespec.c。所有评论都是我添加的。
struct timespec
dtotimespec (double sec)
{
if (! (TYPE_MINIMUM (time_t) < sec)) //underflow case
return make_timespec (TYPE_MINIMUM (time_t), 0);
else if (! (sec < 1.0 + TYPE_MAXIMUM (time_t))) //overflow case
return make_timespec (TYPE_MAXIMUM (time_t), TIMESPEC_HZ - 1);
else //normal case (looks complex but does nothing technical)
{
time_t s = sec;
double frac = TIMESPEC_HZ * (sec - s);
long ns = frac;
ns += ns < frac;
s += ns / TIMESPEC_HZ;
ns %= TIMESPEC_HZ;
if (ns < 0)
{
s--;
ns += TIMESPEC_HZ;
}
return make_timespec (s, ns);
}
}
由于time_t
被定义为整数类型(请参见第7.27.1-3节),因此很自然地假设类型time_t
的最大值小于HUGE_VAL
输入double
),这意味着我们输入了溢出情况。 (实际上,不需要此假设,因为在所有情况下,过程基本上都是相同的。)
make_timespec()
我们要爬的最后一堵墙是make_timespec()
。非常幸运的是,引用源代码gnulib/lib/timespec.h非常简单。
_GL_TIMESPEC_INLINE struct timespec
make_timespec (time_t s, long int ns)
{
struct timespec r;
r.tv_sec = s;
r.tv_nsec = ns;
return r;
}
答案 7 :(得分:2)
我最近需要这样做。我提出了以下函数,它将允许bash永远无需调用任何外部程序就可以睡眠:
snore 0.1 # sleeps for 0.1 seconds
snore 10 # sleeps for 10 seconds
snore # sleeps forever
注意:我之前发布了一个版本,每次打开和关闭文件描述符,但我发现在某些系统上这样做数百次,最终会锁定。因此,新解决方案在文件描述符之间保持对函数的调用。无论如何,Bash会在退出时清理它。
这可以像/ bin / sleep一样调用,并且会在请求的时间内休眠。没有参数调用,它将永远挂起。
int calculateTriangles(int n) {
if(n < 0) return 1;
if(n == 0) return 0;
return ((2*n -2) *3) + calculateTriangles(n-2);
}
答案 8 :(得分:0)
如果可用,请尝试使用--replace
或-replace
运行新的窗口管理器,而不是杀死窗口管理器。
答案 9 :(得分:0)
这种方法不会消耗任何资源来使进程保持活动状态。
while :; do sleep 1; done & kill -STOP $! && wait $!
while :; do sleep 1; done &
在后台创建虚拟进程kill -STOP $!
停止后台进程wait $!
等待后台进程,它将永远被阻止,因为后台进程之前已被停止答案 10 :(得分:-2)
while :; do read; done
无需等待孩子睡觉过程。