我想less(1)
在我们公司的生产服务器上为命令设置超时。我们每天都会在其上生成大型日志文件,尽管每晚都有批处理作业来归档/删除它们,但有时我们会收到磁盘使用率过高的警报,因为(长时间)运行的进程可能会阻止文件unlink(2)
因引用而物理地被 -ed - POSIX 文件系统的语义计数。
为了避免此类烦恼的最常见情况,我编写了一个包装器,在less
其下运行它timeout(1)
以便空闲less
进程在几个小时后自动终止,而不在文件系统中保留打开的文件。
但结果却表现得很糟糕:当命令通过环境变量man(1)
启动包装器时,它停止响应任何键盘输入。这是一个最小的可重现测试用例:man
PAGER
$ PAGER='timeout 12h /bin/less' man man
运行后,ps fx
输出如下所示:
19415 pts/1 SNs 0:00 \_ -bash
19854 pts/1 SN+ 0:00 \_ man man
19867 pts/1 SN 0:00 \_ timeout 12h /bin/less
19869 pts/1 TN 0:00 \_ /bin/less
我只能kill -KILL 19869
重新获得对终端的访问权限。
我在这里做错了什么?为什么less
进程处于T
状态,而不是S
?
答案1
回答我自己的问题,因为我无法通过谷歌搜索真正找到任何提示。
strace(1)
实际上可以显示SIGTTOU
已发送到less
进程的信息。
这与 类似
SIGTTIN
,但当后台作业中的进程尝试写入终端或设置其模式时生成。 ...剪断...
显然timeout(1)
默认情况下将管理下的进程置于后台:
--foreground
不要创建单独的后台程序组,以便托管命令可以正常使用前台TTY。 ...剪断...
所以我的问题的解决方案是
$ PAGER='/bin/timeout --foreground 12h /bin/less' man man
(以及我的包装中的等效内容)