iotop脚本通过自定义脚本执行无法工作
我安装了CSF(配置安全防火墙),它有一个功能,可以让你在系统负载达到一定水平时执行自定义脚本。
我的脚本是:
##!/usr/bin/env bash
iotop -bto --iter=1 2>&1 | mail -s "$HOSTNAME iotop output" incidents@
这个脚本在bash命令行中运行得很好,但当它被lfd(CSF的监控进程)执行时,我得到了以下输出:
Traceback (most recent call last):
File "/usr/bin/iotop", line 9, in <module>
from iotop.ui import main
File "/usr/lib/python2.6/site-packages/iotop/ui.py", line 13, in
<module>
from iotop.data import find_uids, TaskStatsNetlink, ProcessList, Stats
File "/usr/lib/python2.6/site-packages/iotop/data.py", line 36, in
<module>
from iotop import ioprio, vmstat
File "/usr/lib/python2.6/site-packages/iotop/ioprio.py", line 52, in
<module>
__NR_ioprio_get = find_ioprio_syscall_number(IOPRIO_GET_ARCH_SYSCALL)
File "/usr/lib/python2.6/site-packages/iotop/ioprio.py", line 38, in
find_ioprio_syscall_number
bits = platform.architecture()[0]
File "/usr/lib64/python2.6/platform.py", line 1073, in architecture
output = _syscmd_file(executable, '')
File "/usr/lib64/python2.6/platform.py", line 1021, in _syscmd_file
rc = f.close()
IOError: [Errno 10] No child processes
有没有人能帮我解释一下这个问题?
2 个回答
0
通常,当你在自动执行命令时遇到问题,原因可能是执行命令的环境没有设置好变量(因为没有登录)。不过我觉得这不是这里的问题。我更怀疑的是,运行这个脚本的用户权限可能不够。
我建议你尝试用su命令切换到CSF运行脚本的那个用户,然后手动以那个用户的身份运行脚本。
1
内部实际上调用的是类似于:
import os
import sys
f = os.popen('file -b "%s" 2> %s' % (sys.executable, os.devnull))
f.read()
f.close()
为了让 popen()
正常工作,它需要接收到 SIGCHLD
信号,这个信号是用来告诉它子进程已经结束了。看起来执行 iotop
的环境中有一个自定义的回收进程,它会拦截 SIGCHLD
信号,导致 Python 无法收到子进程结束的通知。因此,当函数调用 .close()
时,Python 试图杀死一个已经结束的进程,这样就会从操作系统那里收到错误信息。
如果你无法重新配置环境以允许 SIGCHLD
信号通过,我想你可能需要采取一些不太优雅的黑客手段。
可以把 iotop
包装在一个脚本中,使用猴子补丁(monkey-patch)来修改 platform.architecture()
,让它总是返回相同的元组(比如 ('64bit', 'ELF')
——可以参考真实的 architecture()
输出)来让你继续进行。
另外,你也可以直接复制一份 platform.py
文件,并直接编辑它,然后为定时任务设置 PYTHONPATH
指向这个新文件。