Русские Блоги
Реализация Python добавляет, удаляет, запуск и отключает службу Windows
Обязательно просмотреть ссылку
# !/usr/bin/python3 # coding: utf-8 import os import time import traceback from tool import bat, reg class Service(object): def __init__(self, name, dir, app): # наименование услуги self.name = name # self.dir = dir # .bat или .exe self.app = app cwd = os.getcwd() self.instsrv = os.path.join(cwd, r"\extra\instsrv.exe") self.srvany = os.path.join(cwd, r"\extra\srvany.exe") def install(self): try: self.remove() print("Install service ..") # Administrator Privilege Runs Comd Command bat.runAdmin("%s %s %s" % (self.instsrv, self.name, self.srvany)) # Добавить параметры связанных с обслуживанием к реестре reg.addSrvParam(self.name, self.dir, self.app) print("%s install success" % self.name) except Exception as e: traceback.print_exc() raise e def status(self): status = os.popen("sc query %s" % self.name).read() Если «нет» в статусе: return -1 elif "START_PENDING" in status: return 0 if "RUNNING" in status: return 1 elif "STOP_PENDING" in status: return 2 elif "STOPPED" in status: return 3 else: return 4 def auto(self): try: # Администратор Privilege Run CMD Инструкция bat.runAdmin("sc config %s start = auto" % self.name) except Exception as e: raise e def start(self): status = self.status() if -1 == status: print("%s is uninstalled" % self.name) return elif 0 == status: print("%s is starting .." % self.name) return elif 1 == status: print("%s is running" % self.name) return elif 2 == status: print("%s is stopping .." % self.name) time.sleep(10) while 2 == self.status(): time.sleep(10) print("Start service ..") # Администратор Privilege Run CMD Инструкция bat.runAdmin("sc start %s" % self.name) print("%s startup success" % self.name) elif 3 == status: print("%s is stopped" % self.name) print("Start service ..") # Администратор Privilege Run CMD Инструкция bat.runAdmin("sc start %s" % self.name) print("%s startup success" % self.name) else: print("%s is in other status" % self.name) def stop(self): status = self.status() if -1 == status: print("%s is uninstalled" % self.name) return elif 0 == status: print("%s is starting .." % self.name) time.sleep(10) while 0 == self.status(): time.sleep(10) print("Stop Service ..") # Администратор Privilege Run CMD Инструкция bat.runAdmin("sc stop %s" % self.name) print("%s shutdown success" % self.name) elif 1 == status: print("%s is running" % self.name) print("Stop Service ..") # Администратор Privilege Run CMD Инструкция bat.runAdmin("sc stop %s" % self.name) print("%s shutdown success" % self.name) elif 2 == status: print("%s is stopping .." % self.name) return elif 3 == status: print("%s is stopped" % self.name) return else: print("%s is in other status" % self.name) def restart(self): status = self.status() if -1 == status: print("%s is uninstalled" % self.name) return elif 0 == status: print("%s is starting .." % self.name) return elif 1 == status: try: print("Stop Service ..") # Администратор Privilege Run CMD Инструкция bat.runAdmin("sc stop %s" % self.name) except: print(str(traceback.format_exc())) print("Start service ..") # Администратор Privilege Run CMD Инструкция bat.runAdmin("sc start %s" % self.name) print("%s startup success" % self.name) elif 2 == status: print("%s is stopping .." % self.name) time.sleep(10) while 2 == self.status(): time.sleep(10) print("Start service ..") # Администратор Privilege Run CMD Инструкция bat.runAdmin("sc start %s" % self.name) print("%s startup success" % self.name) elif 3 == status: print("%s is stopped" % self.name) print("Start service ..") # Администратор Privilege Run CMD Инструкция bat.runAdmin("sc start %s" % self.name) print("%s startup success" % self.name) else: print("%s is in other status" % self.name) def remove(self): try: status = self.status() if -1 == status: print("%s is uninstalled" % self.name) return self.stop() print("Remove service ..") # Администратор Privilege Run CMD Инструкция bat.runAdmin("%s %s remove" % (self.instsrv, self.name)) print("%s remove success" % self.name) except Exception as e: raise e
# Администратор Privilege Run CMD Инструкция bat.runAdmin(cmd)
# Добавить параметры связанных с обслуживанием к реестре reg.addSrvParam(srv, dir, app)
Связанные reg.py содержимое следующие
# !/usr/bin/python3 # coding: utf-8 import os import subprocess import traceback def addSrvParam(srv, dir, app): # only \\ in path, / or \ is not allowed dir = format(dir).replace("\\", "\\\\") app = format(app).replace("\\", "\\\\") # c = 'Windows Registry Editor Version 5.00\n' # Мудк c += '\n' # Добавить первичный ключ c += '[HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\services\%s\Parameters]\n' % srv # Добавить значение ключа c += '"AppDirectory"="%s"\n' % dir # Добавить значения ключа c += '"Application"="%s"\n' % app path = os.getcwd() + r"\tool\script\srv.reg" f = None try: f = open(path, 'w') f.write(c) except Exception as e: traceback.print_exc() raise e finally: if f: f.close() command(path, 1800000) def command(cmd, timeout=1800000): try: sp = subprocess.Popen( cmd, shell=True, stdout=subprocess.PIPE, stderr=subprocess.PIPE ) print("[PID] %s: %s" % (sp.pid, cmd)) sp.wait(timeout=timeout) stderr = str(sp.stderr.read().decode("gbk")).strip() stdout = str(sp.stdout.read().decode("gbk")).strip() if "" != stderr: raise Exception(stderr) Если stdout.find ("не удалось"> -1: raise Exception(stdout) except Exception as e: raise e def format(path): if path is None: return "" path = path.lstrip() path = path.rstrip() while path.find("/") >= 0: path = path.replace("/", "\\") while path.find("\\\\") >= 0: path = path.replace("\\\\", "\\") return path
Прикреплять
Python заметки
При работе в Windows приходится использовать некоторые службы, которые не нужны постоянно. Особенно, когда эта машина локальная, не серверная.
Например, sphinxsearh, MySQL, PostgreSQL, очереди сообщений и проч. нужны либо в момент работы над проектом, их использующим, либо при изучении их разработчиком.
Обычно пользователи Виндоус могут остановить службу через Панель Управления (Администрирование — Службы) или, кто попродвинутей, через командную строку. Оба этих способа подразумевают трату времени или на поиск службы в списке, или на узнавание имени службы.
Отсюда скачивайте последнюю версию pywin32 (там она вполне по x64 есть, не смущайтесь названием) под требуемую версию Питона, а отсюда ( ну или с Гитхаба) устанавливаем PyWinServiceManager.
from pywinservicemanager.WindowsServiceConfigurationManager import ServiceExists serviceName = 'TestService' serviceExists = ServiceExists(serviceName) print serviceExists
После исправления ошибки все запускается, однако, похоже, PyWinServiceManager писан для второго Питона. Или не для второго, но ошибок многовато и править их лень. Хотя сама библиотека задумана с размахом и может подойти для задач типа «запуск Python скрипта как windows сервис».
machine = None или вообще переписать без использования этого параметра (по сети не тестировал, но идея выглядит интересной)
machine = None service = 'postgresql-x64-9.5' action = 'restart'
Тут все хорошо, кроме того, что служба стартует не мгновенно, точнее, не так быстро, как ее статус опрашивается. Как следствие — при запуске и перезапуске (start / restart) вы будете получать сообщение, что запуск невозможен.
import win32serviceutil def service_running(service, machine): status = (win32serviceutil.QueryServiceStatus(service)[1] == 4) if not status: import time time.sleep(3) status = (win32serviceutil.QueryServiceStatus(service)[1] == 4) return status def service_info(action, machine, service): running = service_running(service, machine) servnam = 'service (%s) on machine(%s)'%(service, machine) action = action.lower( ) if action == 'stop': if not running: print ("Can't stop, %s not running"%servnam) return 0 win32serviceutil.StopService(service, machine) running = service_running(service, machine) if running: print ("Can't stop %s (. )"%servnam) return 0 print ('%s stopped successfully' % servnam) elif action == 'start': if running: print ("Can't start, %s already running"%servnam) return 0 win32serviceutil.StartService(service, machine) running = service_running(service, machine) if not running: print ("Can't start %s (. )"%servnam) return 0 print ('%s started successfully' % servnam) elif action == 'restart': if not running: print ("Can't restart, %s not running"%servnam) return 0 win32serviceutil.RestartService(service, machine) running = service_running(service, machine) if not running: print ("Can't restart %s (. )"%servnam) return 0 print ('%s restarted successfully' % servnam) elif action == 'status': if running: print ("%s is running" % servnam) else: print ("%s is not running" % servnam) else: print ("Unknown action (%s) requested on %s"%(action, servnam)) if __name__ == '__main__': machine = None service = 'postgresql-x64-9.5' action = 'restart' service_info(action, machine, service)
теперь, зная список служб, можно держать их в отдельном файле и стартовать/останавливать группой применительно к конкретной задаче.
P.S. конечно же, права на запуск должны быть Администратора. Т.е. или запускайте PyCharm c админ правами или классическое CMD c Run As Administrator опцией.