views:

339

answers:

2

I have a script which runs inside a while loop and monitors a mysql data source every 2 seconds. If I run if from the command line, it runs and works fine. But If I attach it to a daemon, it throws an error saying "MySQL has gone" or something similar. I checked and found MySQL up and running. I could even execute queries from other tools.

I badly need help. I am running Ubuntu 10.04.

Error Code

Traceback (most recent call last):
  File "/home/masnun/Desktop/daemon/daemon.py", line 67, in <module>
    main()
  File "/home/masnun/Desktop/daemon/daemon.py", line 35, in main
    USERPROG()
  File "/home/masnun/Desktop/daemon/mymain.py", line 19, in main
    cursor.execute("select * from hits_logs where id > '" + str(last) + "'")
  File "/usr/lib/pymodules/python2.6/MySQLdb/cursors.py", line 166, in execute
    self.errorhandler(self, exc, value)
  File "/usr/lib/pymodules/python2.6/MySQLdb/connections.py", line 35, in defau$
    raise errorclass, errorvalue
_mysql_exceptions.OperationalError: (2006, 'MySQL server has gone away')

File: daemon

#! /bin/sh
# example python daemon starter script
# based on skeleton from Debian GNU/Linux
# [email protected]
# place the daemon scripts in a folder accessible by root. /usr/local/sbin is a good idea

PATH=/usr/local/sbin:/usr/local/bin:/sbin:/bin:/usr/sbin:/usr/bin
DAEMON=/home/masnun/Desktop/daemon/daemon.py
NAME=pydaemon
DESC="Example daemon"

test -f $DAEMON || exit 0

set -e

case "$1" in
  start)
    echo -n "Starting $DESC: "
    start-stop-daemon --start --quiet --pidfile /var/run/$NAME.pid \
        --exec $DAEMON
    echo "$NAME."
    ;;
  stop)
    echo -n "Stopping $DESC: "
    start-stop-daemon --stop --quiet --pidfile /var/run/$NAME.pid
    # \ --exec $DAEMON
    echo "$NAME."
    ;;
  #reload)
    #
    #   If the daemon can reload its config files on the fly
    #   for example by sending it SIGHUP, do it here.
    #
    #   If the daemon responds to changes in its config file
    #   directly anyway, make this a do-nothing entry.
    #
    # echo "Reloading $DESC configuration files."
    # start-stop-daemon --stop --signal 1 --quiet --pidfile \
    #   /var/run/$NAME.pid --exec $DAEMON
  #;;
  restart|force-reload)
    #
    #   If the "reload" option is implemented, move the "force-reload"
    #   option to the "reload" entry above. If not, "force-reload" is
    #   just the same as "restart".
    #
    echo -n "Restarting $DESC: "
    start-stop-daemon --stop --quiet --pidfile \
        /var/run/$NAME.pid
        # --exec $DAEMON
    sleep 1
    start-stop-daemon --start --quiet --pidfile \
        /var/run/$NAME.pid --exec $DAEMON
    echo "$NAME."
    ;;
  *)
    N=/etc/init.d/$NAME
    # echo "Usage: $N {start|stop|restart|reload|force-reload}" >&2
    echo "Usage: $N {start|stop|restart|force-reload}" >&2
    exit 1
    ;;
esac

exit 0

File: daemon.py

#!/usr/bin/env python

###########################################################################
# configure these paths:
LOGFILE = '/var/log/pydaemon.log'
PIDFILE = '/var/run/pydaemon.pid'

# and let USERPROG be the main function of your project
import mymain
USERPROG = mymain.main
###########################################################################


import sys, os

class Log:
    """file like for writes with auto flush after each write
    to ensure that everything is logged, even during an
    unexpected exit."""
    def __init__(self, f):
        self.f = f
    def write(self, s):
        self.f.write(s)
        self.f.flush()

def main():
    #change to data directory if needed
    os.chdir("/home/masnun/Desktop/daemon")
    #redirect outputs to a logfile
    sys.stdout = sys.stderr = Log(open(LOGFILE, 'a+'))
    #ensure the that the daemon runs a normal user
    os.setegid(1000)     #set group first "pydaemon"
    os.seteuid(1000)     #set user "pydaemon"
    #start the user program here:
    USERPROG()

if __name__ == "__main__":
    # do the UNIX double-fork magic, see Stevens' "Advanced
    # Programming in the UNIX Environment" for details (ISBN 0201563177)
    try:
        pid = os.fork()
        if pid > 0:
            # exit first parent
            sys.exit(0)
    except OSError, e:
        print >>sys.stderr, "fork #1 failed: %d (%s)" % (e.errno, e.strerror)
        sys.exit(1)

    # decouple from parent environment
    os.chdir("/")   #don't prevent unmounting....
    os.setsid()
    os.umask(0)

    # do second fork
    try:
        pid = os.fork()
        if pid > 0:
            # exit from second parent, print eventual PID before
            #print "Daemon PID %d" % pid
            open(PIDFILE,'w').write("%d"%pid)
            sys.exit(0)
    except OSError, e:
        print >>sys.stderr, "fork #2 failed: %d (%s)" % (e.errno, e.strerror)
        sys.exit(1)

    # start the daemon main loop
    main()

File: mymain.py

import MySQLdb
from ProxyChecker import ProxyChecker
from time import sleep

config = {"host":"localhost","username":"root","password":"masnun","database":"webtracc_db1"}
connection = MySQLdb.connect(config['host'],config['username'],config['password'],config['database'])
cursor = connection.cursor()




def main():
    while True:
        f = open("last","r")
        last = f.read().strip()
        f.close()
        if last == '': last = 0;
        last = int(last)
        cursor.execute("select * from hits_logs where id > '" + str(last) + "'")
        row = cursor.fetchall()
        for x in row:
            pc = ProxyChecker( x[2] )
            pc.start()
            last = x[0]

        f = open("last","w")
        f.write(str(last))
        f.close()
        sleep(2)

if __name__ == "__main__":
    main()


File:

ProxyChecker.py

#! /usr/bin/env python

from threading import Thread
from CheckProxy import CheckProxy

class ProxyChecker(Thread):
    def __init__(self, data):
        self.data = data
        Thread.__init__(self)

    def run(self):
        pc = CheckProxy()
        pc.check(self.data)

File: CheckProxy.py

#! /usr/bin/env python
import MySQLdb
import socket

class CheckProxy:
    def __init__(self):

            self.config = {"host":"localhost","username":"root","password":"masnun","database":"webtracc_db1"}
            self.portList = [80]

    def check(self,host):


            connection = MySQLdb.connect(self.config['host'],self.config['username'],self.config['password'],self.config['database'])
            cursor = connection.cursor()
            proxy = False

            try:
                for x in self.portList:
                    sock = socket.socket()
                    sock.connect((host,x))
                    #print "connected to: " + str (x)
                    sock.close()
                    cursor.execute("select count(*) from list_entries where list='1' and ip='"+ host + "' ")
                    data = cursor.fetchall()
                    #print data[0][0]
                    if data[0][0] < 1:
                        print 'ok'
                        proxy = True





            except socket.error, e:
                #print e          

              if proxy:
                cursor.execute("insert into list_entries (ip,list) values ('"+ host.strip() +"','1') ")
              else:
                cursor.execute("insert into list_entries (ip,list) values ('"+ host.strip() +"','2') ")








if __name__ == "__main__":
    print "Direct access not allowed!"
A: 

Hello Daniel,

I'm not sure if this will address your problem as I had encountered it when setting up Drupal/PHP/Mysql. If the data payload sent from a process to mysql is an excessive size, that can cause the above error. The solution is to increase max_allowed_packet in /etc/mysql/my.cnf. Set it to something high like 64/128mb.

Another thing to look at is your mysql logs. Check to see if the process is connecting. Sometimes logs are a mess so I do a tail -f then do something to watch the conversation between the two processes.

If you see any errors in your logs, pass them back and I'll see if I can give you a better answer.

Desolate Planet
+1  A: 

I haven't worked with Python, but it almost seems you are making a database connection, then forking. The other way around should work: fork at will, then connect in remaining process, possibly in your mymain.py:main() method.

Wrikken