Bash read 的超时由谁决定?

发布于 2023-02-02 20:20:05 字数 1880 浏览 93 评论 0

症状

事情的起因是我想将系统检查脚本收集到的数据发送到一个服务器中汇集起来存入数据库中,于是用 shell 写了个简单的脚本,大概是这样的:

nc -kl 1234 |while read a b c d;do
    echo "insert into baseline values('$a','$b','$c','$d');"
done |sqlite3 baseline.db

然后我发现很奇怪的,每隔一段时间 nc 进程就会退出,导致发送检查数据时提示连接服务器端口失败。

排查

使用 ps 抓取进程变动情况,发现每隔一段时间 while 循环的那个 bash 进程就会消失

刚开始的进程是这样的:

lujun9972:~/ $ ps -elf |grep 2357400|grep -v grep
0 S lujun99+  200407 2357400  0  80   0 -   763 -      15:53 pts/0    00:00:00 nc -l 1234
1 S lujun99+  200408 2357400  0  80   0 -  4111 -      15:53 pts/0    00:00:00 bash
0 S lujun99+ 2357400 2357398  0  80   0 -  4176 -      3月27 pts/0   00:00:01 bash

过了一会变成了:

lujun9972:~/ $ ps -elf |grep 2357400|grep -v grep
0 S lujun99+  200407 2357400  0  80   0 -   763 -      15:53 pts/0    00:00:00 nc -l 1234
0 S lujun99+ 2357400 2357398  0  80   0 -  4176 -      3月27 pts/0   00:00:01 bash

这很明显是 while 循环被退出了呀。但是我并没有使用 read 的 -t 选项指定超时时间啊?

经过搜索 man bash,终于发现罪魁祸首原来是 TMOUT 这个环境变量。关于 TMOUT 的说明, man bash 中是这么说的:

TMOUT  如果设置为大于  0  的值,TMOUT 被当作内建命令 read
       的默认超时 等待时间。如果等待终端输入时, TMOUT 秒
       之后仍然没有输入,   select   命令将终止。在交互的
       shell 中,它的值被解释为显示了  主提示符之后等待输
       入的秒数。如果经过这个秒数之后仍然没有输入,  Bash
       将退出。

原来,为了安全期间,生产环境的主机都设置了 TMOUT 参数,在操作员一段时间未操作的情况下自动断开与主机的连接。 而这个 TMOUT 又同时作为 read 命令的默认超时时间,而read在超时后返回码为 142,所以就退出了 while 循环了,while 循环退出后 nc 再收到网络发来的数据后就会由于输出句柄被关闭而退出了。

解决

将命令改成

nc -kl 1234 |while TMOUT="" read a b c d;do
    echo "insert into baseline values('$a','$b','$c','$d');"
done |sqlite3 baseline.db

后问题得到了解决。

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。
列表为空,暂无数据

关于作者

永不分离

暂无简介

文章
评论
835 人气
更多

推荐作者

櫻之舞

文章 0 评论 0

弥枳

文章 0 评论 0

m2429

文章 0 评论 0

野却迷人

文章 0 评论 0

我怀念的。

文章 0 评论 0

    我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
    原文