编辑
我通过 fork 进程而不是使用线程解决了这个问题。从评论中的评论和链接来看,我认为线程在这里不是正确的举动。
感谢大家的帮助。
完成编辑
我之前对线程的了解不多。我创建了一些简单的示例“Hello World”脚本,但实际上没有任何效果。
为了帮助我掌握它,我使用 Nagios 的二进制文件编写了一个简单的脚本来查询 HTTP 等服务。如果我有 10 个服务超时,这个脚本虽然超时为 1 秒,但该脚本将花费 10 秒以上的时间。
我想做的是并行运行所有检查。这应该会减少完成所需的时间。
我目前遇到了段错误,但并非总是如此。奇怪的是,当我在 processCheck 函数中检查主机时,我可以打印出所有主机。不过,在检查主机之后,hosts 变量仅打印集合中的一两个主机。我感觉这是一个命名空间问题,但我不确定如何解决。
我已经在此处发布了没有 MySQL 数据库的整个代码,但 service_list View 的结果看起来像这样。
非常感谢任何帮助。
6543L, 'moretesting.com', 'smtp')
(6543L, 'moretesting.com', 'ping')
(6543L, 'moretesting.com', 'http')
from commands import getstatusoutput
import MySQLdb
import threading
import Queue
import time
def checkHost(x, service):
command = {}
command['http'] = './plugins/check_http -t 1 -H '
command['smtp'] = './plugins/check_smtp -t 1 -H '
cmd = command[service]
cmd += x
retval = getstatusoutput(cmd)
if retval[0] == 0:
return 0
else:
return retval[1]
def fetchHosts():
hostList = []
cur.execute('SELECT veid, hostname, service from service_list')
for row in cur.fetchall():
hostList.append(row)
return hostList
def insertFailure(veid, hostname, service, error):
query = 'INSERT INTO failures (veid, hostname, service, error) '
query += "VALUES ('%s', '%s', '%s', '%s')" % (veid, hostname, service, error)
cur.execute(query)
cur.execute('COMMIT')
def processCheck(host):
#If I print the host tuple here I get all hosts/services
retval = checkHost(host[1], host[2])
#If I print the host tuple here, I get one host maybe two
if retval != 0:
try:
insertFailure(host[0], host[1], host[2], retval)
except:
pass
else:
try:
#if service is back up, remove old failure entry
query = "DELETE FROM failures WHERE veid='%s' AND service='%s' AND hostname='%s'" % (host[0], host[2], host[1])
cur.execute(query)
cur.execute('COMMIT')
except:
pass
return 0
class ThreadClass(threading.Thread):
def __init__(self, queue):
threading.Thread.__init__(self)
self.queue = queue
def run(self):
processCheck(queue.get())
time.sleep(1)
def main():
for host in fetchHosts():
queue.put(host)
t = ThreadClass(queue)
t.setDaemon(True)
t.start()
if __name__ == '__main__':
conn = MySQLdb.connect('localhost', 'root', '', 'testing')
cur = conn.cursor()
queue = Queue.Queue()
main()
conn.close()
请您参考如下方法:
MySQL 数据库驱动程序不是线程安全的。您在所有线程中同时使用同一个游标。
尝试在每个线程中创建一个新连接,或者创建一个线程可以使用的连接池(例如,将它们保存在一个队列中,每个线程获取一个连接,并在完成后将打包)。
