原文地址:https://www.lujun9972.win/blog/2021/07/27/aix中的timeout脚本/index.html
目录
AIX 下没有现成的 timeout 命令来限时运行命令,于是就想着自己实现一个类似的脚本。本来以为挺简单的一件事情,结果埋者一堆坑。
最初的结果如下:
#! /usr/bin/ksh waitfor=$1 shift command=$* $command & commandpid=$! (sleep $waitfor;kill $commandpid) & # 坑1 watchdogpid=$! wait $commandpid kill $watchdogpid # 坑2
这里有两个需要关注的地方:
(sleep $waitof;kill $commandpid) &在超时杀掉工作命令后就退出了,工作命令被杀掉之后wait $commandpid执行完成,主进程继续执行kill $watchdogpid. 然而由于监控进程早已退出,在忙碌的系统中,可能出现$watchdogpid被其他进程重复使用,导致误杀其他进程的风险。 要解决这一风险,可以让监控进程在杀掉工作进程后再等待一段时间,以便让主进程杀掉监控进程。kill $watchdogpid在ksh中并不会把子进程一起杀掉,也就是说sleep $waitfor这个进程依然在运行,只不过父进程从$watchdogpid变成了1. 不仅如此AIX上的kill居然不支持PID为负数的情况,这使得妄想通过kill -$watchdogpid杀掉整个进程组变得不可能。
最后经过尝试,发现在ksh交互模式下,用 kill %jobID 的方式是能够将整个 JOB 杀干净的,因此最后的结果如下:
#! /usr/bin/ksh -i waitfor=$1 shift command=$* $command & commandpid=$! (sleep $waitfor;kill $commandpid;sleep 1) & wait $commandpid kill %2 >/dev/null 2>&1
不过这种实现有个比较大的缺点就是由于整个实现实在交互式ksh环境中执行的,因此会污染 ksh 的 history 命令历史。
UPDATE:
教新的 AIX 上搭载的 kill 命令是支持通过将 PID 设置为负值来杀掉整个进程组的,这样一来 timeout 的实现就简单很多了:
timeout() { waitfor=$1 shift command=$* $command & commandpid=$! (sleep $waitfor;kill $commandpid;sleep 1) & watchdogpid=$! wait $commandpid kill -$watchdogpid # 杀掉整个进程组 }
本文介绍了在AIX操作系统中由于缺乏内置的timeout命令,作者自行编写了一个脚本来实现在指定时间后终止命令的功能。初始实现存在监控进程可能被其他进程误杀的问题,最终通过使用交互式ksh的job控制解决了这个问题。但这种方法会污染命令历史。更新提到新版AIX的kill命令支持负数PID,简化了timeout脚本的实现。
340

被折叠的 条评论
为什么被折叠?



