我正在开发一个python程序,它包含一个守护进程,为不同的用户和服务启动一个子进程。 这是感兴趣的代码:
'''
Created on 13.02.2014
@author: Richard Neumann
'''
import os, zmq, signal, threading, time, sys
from homie import Syslog, Config
from homie.lib.files import FieldsFile
from homie.service import Service
from homie.lib.user import User
from homie.lib.log import LogLvl, ErrLvl, LogEntry
from homie.lib.ipc import SocketClient
class Daemon():
'''
Class to represent the system service
'''
def __get_user(self, user_name):
'''
Gets a user securely
'''
user = False
try:
user = User(user_name)
except:
self.log('No such user "' + user_name + '"', LogLvl.DEFAULT, ErrLvl.ERROR)
return user
def __get_service_data(self, user, service_name):
'''
Returns the PID and the listening port of a service of a user
'''
service_data = user.get_runfile().get_data(service_name)
''' Runfile file contains "<service_name>=<pid>[tab]<port>" '''
service_data = service_data.split('\t')
pid = service_data[0] if len(service_data) >= 1 else None
port = service_data[1] if len(service_data) >= 2 else None
return pid, port
def __get_pid(self, user, service_name):
'''
Returns the PID of a service of a user
'''
pid, __ = self.__get_service_data(user, service_name)
if pid:
try:
pid = int(pid)
return pid
except:
self.log('No PID for service "' + service_name + '" for user "' + str(user) + '"', LogLvl.DEFAULT, ErrLvl.ERROR)
return None
def __get_port(self, user, service_name):
'''
Returns the listening port of a service of a user
'''
__, port = self.__get_service_data(user, service_name)
if port:
try:
port = int(port)
return port
except:
self.log('No listening port for service "' + service_name + '" for user "' + str(user) + '"', LogLvl.DEFAULT, ErrLvl.ERROR)
return None
def __start(self, user_name, service_name):
'''
Starts a service for a user
'''
print('Starting service "' + service_name + '" for user "' + user_name + '"\t\t'),
if self.__status(user_name, service_name):
''' Service is already running for user '''
print('[ALREADY RUNNING]')
return True
else:
user = self.__get_user(user_name)
if user:
''' We have a valid user '''
if service_name in user.get_services():
''' The service is enabled for the user '''
try:
ServiceClass = Service.by_classname(service_name)
except:
print('[NO SUCH SERVICE]')
return False
pid = os.fork()
if pid != 0:
''' Daemon: Return OK '''
print('[OK]')
return True
else:
''' Child: Start new service '''
os.setuid(user.get_uid()) # Do this first!
service_instance = ServiceClass(user)
service_instance.init()
service_instance.start()
return True
else:
print('[NOT ENABLED]')
return False
else:
print('[NO SUCH USER]')
return False
print('[FAILED]')
return False
def __stop(self, user_name, service_name):
'''
Stops a service for a user
'''
print('Stopping service "' + service_name + '" for user "' + user_name + '"\t\t'),
if self.__status(user_name, service_name):
pid = self.__get_pid(self.__get_user(user_name), service_name)
''' Kill the process '''
try:
os.kill(pid, signal.SIGTERM)
''' And remove runfile entry '''
user = self.__get_user(user_name)
runfile = user.get_runfile()
runfile.remove(service_name)
print('[OK]')
return True
except:
print('[FAILED]')
return False
else:
print('[NOT RUNNING]')
return True
def __status(self, user_name, service_name, quiet=True):
'''
Determines status of the daemon
'''
if not quiet: print('Service "' + service_name + '" for user "' + user_name + '" is\t\t'),
user = self.__get_user(user_name)
if user:
pid = self.__get_pid(user, service_name)
try:
os.kill(pid, 0)
status = '[UP'
try:
port = self.__get_port(self.__get_user(user_name), service_name)
sc = SocketClient(port)
if sc.query('status') == 'RUNNING':
status += ' & RUNNING]'
else:
status += ' & STOPPED]'
except:
status += ' & UNDETERMINED]'
if not quiet: print(status)
except:
if not quiet: print('[DOWN]')
return False
return True
else:
if not quiet: print('[NO SUCH USER]')
return False
def start(self, user_name=None, service_name=None):
'''
Starts the daemons
'''
if user_name:
''' Start user's services '''
if service_name:
self.__start(user_name, service_name)
else:
user = self.__get_user(user_name)
if user:
for service_name in user.get_services():
self.start(user_name, service_name)
else:
print('No such user: ' + user_name)
else:
for user in User.fetch(Config.CUSTOMERS_GROUP):
self.start(str(user), service_name)
def stop(self, user_name=None, service_name=None):
'''
Stops the daemons
'''
if user_name:
''' Start user's services '''
if service_name:
self.__stop(user_name, service_name)
else:
user = self.__get_user(user_name)
if user:
for service_name in user.get_services():
self.stop(user_name, service_name)
else:
print('No such user: ' + user_name)
else:
for user in User.fetch(Config.CUSTOMERS_GROUP):
self.stop(user.get_name(), service_name)
def status(self, user_name=None, service_name=None):
'''
Determines status of the daemons
'''
if user_name:
''' Start user's services '''
if service_name:
self.__status(user_name, service_name, quiet=False)
else:
user = self.__get_user(user_name)
if user:
for service_name in user.get_services():
self.status(user_name, service_name)
else:
print('No such user: ' + user_name)
else:
for user in User.fetch(Config.CUSTOMERS_GROUP):
self.status(user.get_name(), service_name)
def restart(self, user_name=None, service_name=None):
'''
Restarts the daemons
'''
self.stop(user_name, service_name)
self.start(user_name, service_name)
def reload(self, user_name=None, service_name=None):
'''
Reloads the deamons
'''
# TODO: Just reload
self.restart(user_name, service_name)
def log(self, message, loglvl, errlvl):
'''
Logging
'''
entry = LogEntry(self, message, loglvl, errlvl)
Syslog.log(entry)
现在奇怪的是,如果我在一个用户配置了多个服务时运行该程序,它会将输出写入两次,第二次写入与最后一行中用户test2相同的行:< / p>
# /etc/init.d/homied start
Starting service "ExposeAgent" for user "test" [OK]
Starting service "ExposeAgent" for user "test2" [OK]
Starting service "Someservice" for user "test2" [NO SUCH SERVICE]
Starting service "ExposeAgent" for user "test3" [OK]
Starting service "ExposeAgent" for user "test4" [OK]
Starting service "ExposeAgent" for user "test5" [OK]
Starting service "ExposeAgent" for user "test6" [OK]
Starting service "ExposeAgent" for user "test7" [OK]
Starting service "ExposeAgent" for user "test8" [OK]
Starting service "ExposeAgent" for user "test9" [OK]
Starting service "ExposeAgent" for user "test2" Starting service "Someservice" for user "test2" [NO SUCH SERVICE]
我怀疑错误是在__start()方法中的某个地方:
def __start(self, user_name, service_name):
'''
Starts a service for a user
'''
print('Starting service "' + service_name + '" for user "' + user_name + '"\t\t'),
if self.__status(user_name, service_name):
''' Service is already running for user '''
print('[ALREADY RUNNING]')
return True
else:
user = self.__get_user(user_name)
if user:
''' We have a valid user '''
if service_name in user.get_services():
''' The service is enabled for the user '''
try:
ServiceClass = Service.by_classname(service_name)
except:
print('[NO SUCH SERVICE]')
return False
pid = os.fork()
if pid != 0:
''' Daemon: Return OK '''
print('[OK]')
return True
else:
''' Child: Start new service '''
os.setuid(user.get_uid()) # Do this first!
service_instance = ServiceClass(user)
service_instance.init()
service_instance.start()
return True
else:
print('[NOT ENABLED]')
return False
else:
print('[NO SUCH USER]')
return False
print('[FAILED]')
return False
但我不明白哪里出了问题。 我很欣赏任何提示。
此致
理查德