修改
我通过分支进程而不是使用线程解决了这个问题。从评论中的评论和链接来看,我认为线程化是不正确的。
感谢大家的帮助。
完成编辑
我之前没有做太多线程。我创建了一些简单的示例“Hello World”脚本,但实际上没有任何工作。
为了帮助我掌握它,我使用Nagios中的二进制文件编写了一个简单的脚本来查询HTTP等服务。如果我有10个服务超时,这个脚本有效,但超时为1秒,脚本将花费超过10秒的时间。
我想要做的是彼此并行运行所有检查。这应该减少完成所需的时间。
我目前正在收到段错误,但不是所有时间。奇怪的是,我在processCheck函数中检查主机,我可以打印出所有主机。在检查主机之后,hosts变量仅打印集合中的一个或两个主机。我觉得这是命名空间问题,但我不确定如何解决。
我在这里发布了整个代码没有MySQL数据库,但是他的service_list视图的结果看起来像。
非常感谢任何帮助。
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()
答案 0 :(得分:8)
MySQL DB驱动程序不是线程安全的。您在所有线程中同时使用相同的游标。
尝试在每个线程中创建一个新连接,或创建一个线程可以使用的连接池(例如,将它们保存在Queue
,每个线程get
sa连接,以及{{1}它完成时就打包了。)
答案 1 :(得分:0)
您应该首先构建并填充队列。构建并填充整个队列时,您应该构造一些线程,然后在循环中轮询队列并处理队列中的项目。
答案 2 :(得分:0)