iotop script does not work via custom script execution
I have CSF installed (configure safe firewall), it has a function to allow you to have custom scripts executed on load average events.
My script:
##!/usr/bin/env bash
iotop -bto --iter=1 2>&1 | mail -s "$HOSTNAME iotop output" incidents@
It works fine via bash shell but when executed by lfd (the monitoring process of CSF), I get the following output:
Traceback (most recent call last):
File "/usr/bin/iotop", line 9, in <module>
from iotop.ui import main
File "/usr/lib/p开发者_JS百科ython2.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
Can anyone shed some light on this?
Internally it calls an equivalent of:
import os
import sys
f = os.popen('file -b "%s" 2> %s' % (sys.executable, os.devnull))
f.read()
f.close()
For popen()
to work it has to be able to get the SIGCHLD
signal telling it that a child process exited. It seems that the environment that executes iotop
has a custom reaper process that intercepts SIGCHLD
and prevents python from getting notified about the process exiting. Thus when the function calls .close()
, python tries to kill the process that is already dead and gets an error from the operating system.
If you cannot reconfigure the environment to let SIGCHLD
pass, I think you'll have ro resort to ugly hacking.
Wrapping iotop
in a script that monkey-patches platform.architecture()
with a function that always returns the same tuple (something like ('64bit', 'ELF')
—consult the output of real architecture()
) should let you progress.
Alternatively, you can just make a local copy of the platform.py
file and edit that directly, setting PYTHONPATH
for the cron job to point to that new file.
Normally when you have problems automating commands, it's because the thing that's running the command automatically does not have the same environment variables defined (because there's no login). I don't think that's the case here, though. I would sooner suspect the user that the script is running as doesn't have the same rights.
I would try to su to the user CSF is running the script as, and try running it manually as that user.
精彩评论