| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333 | import osimport subprocessimport loggingimport timefrom pathlib import Pathimport shutil# 配置日志logging.basicConfig(    level=logging.INFO,    format='%(asctime)s - %(levelname)s - %(message)s',    handlers=[        logging.StreamHandler(),        logging.FileHandler('postgres_service_manager.log')    ])logger = logging.getLogger(__name__)def get_postgres_service_name():    """获取 PostgreSQL 服务名称"""    service_names = [        "postgresql-x64-16",        "postgresql-x64-15",        "postgresql-x64-14",        "postgresql-x64-13",        "postgresql-x64-12",        "postgresql"    ]        # 检查服务状态    for service in service_names:        try:            result = subprocess.run(                ["sc", "query", service],                 capture_output=True,                 text=True,                encoding='utf-8',                errors='ignore'            )            if "RUNNING" in result.stdout or "STOPPED" in result.stdout:                return service        except Exception:            continue        return service_names[0] if service_names else "postgresql"def is_service_running(service_name=None):    """检查服务是否正在运行"""    if not service_name:        service_name = get_postgres_service_name()        try:        result = subprocess.run(            ["sc", "query", service_name],             capture_output=True,             text=True,            encoding='utf-8',            errors='ignore'        )        return "RUNNING" in result.stdout    except Exception as e:        logger.error(f"检查服务状态失败: {str(e)}")        return Falsedef stop_postgres_service():    """停止 PostgreSQL 服务"""    try:        service_name = get_postgres_service_name()        logger.info(f"尝试停止 PostgreSQL 服务: {service_name}")                # 使用 net stop 停止服务        result = subprocess.run(            ["net", "stop", service_name],             capture_output=True,             text=True,            encoding='utf-8',            errors='ignore'        )                if result.returncode == 0:            logger.info(f"PostgreSQL 服务 '{service_name}' 已停止")            return True                # 如果 net stop 失败,尝试 sc stop        result = subprocess.run(            ["sc", "stop", service_name],             capture_output=True,             text=True,            encoding='utf-8',            errors='ignore'        )                if result.returncode == 0:            logger.info(f"PostgreSQL 服务 '{service_name}' 已停止")            return True                # 如果服务未停止,尝试强制终止进程        logger.warning("服务未正常停止,尝试终止进程")        subprocess.run(            ["taskkill", "/F", "/IM", "postgres.exe"],             capture_output=True,            encoding='utf-8',            errors='ignore'        )        logger.info("PostgreSQL 进程已终止")        return True            except Exception as e:        logger.error(f"停止 PostgreSQL 服务失败: {str(e)}")        return Falsedef start_postgres_service():    """启动 PostgreSQL 服务"""    try:        service_name = get_postgres_service_name()        logger.info(f"尝试启动 PostgreSQL 服务: {service_name}")                # 使用 net start 启动服务        result = subprocess.run(            ["net", "start", service_name],             capture_output=True,             text=True,            encoding='utf-8',            errors='ignore'        )                if result.returncode == 0:            logger.info(f"PostgreSQL 服务 '{service_name}' 已启动")            return True                # 如果 net start 失败,尝试 sc start        result = subprocess.run(            ["sc", "start", service_name],             capture_output=True,             text=True,            encoding='utf-8',            errors='ignore'        )                if result.returncode == 0:            logger.info(f"PostgreSQL 服务 '{service_name}' 已启动")            return True                raise RuntimeError("启动 PostgreSQL 服务失败")            except Exception as e:        logger.error(f"启动 PostgreSQL 服务失败: {str(e)}")        return Falsedef restart_postgres_service():    """重启 PostgreSQL 服务"""    try:        if stop_postgres_service():            time.sleep(3)  # 等待服务完全停止        return start_postgres_service()    except Exception as e:        logger.error(f"重启 PostgreSQL 服务失败: {str(e)}")        return Falsedef get_postgres_data_dir():    """获取 PostgreSQL 数据目录"""    possible_paths = [        r"D:/app/postgresql/data",        r"C:/Program Files/PostgreSQL/15/data",        r"C:/Program Files/PostgreSQL/14/data",        r"C:/Program Files/PostgreSQL/13/data",        r"C:/Program Files/PostgreSQL/12/data",    ]        env_path = os.environ.get('PGDATA')    if env_path and Path(env_path).exists():        return Path(env_path)        for path in possible_paths:        if Path(path).exists():            return Path(path)        raise FileNotFoundError("无法找到 PostgreSQL 数据目录")def fix_postgres_service():    """修复 PostgreSQL 服务启动问题"""    try:        logger.info("开始修复 PostgreSQL 服务启动问题...")                # 1. 停止服务        if not stop_postgres_service():            logger.warning("无法停止服务,尝试强制修复")                # 2. 检查数据目录        try:            data_dir = get_postgres_data_dir()            logger.info(f"找到 PostgreSQL 数据目录: {data_dir}")                        # 3. 检查并处理恢复配置文件            recovery_signal = data_dir / "recovery.signal"            recovery_done = data_dir / "recovery.done"            auto_conf = data_dir / "postgresql.auto.conf"                        if recovery_signal.exists():                logger.info("发现 recovery.signal 文件,尝试完成恢复过程")                if recovery_done.exists():                    recovery_done.unlink()                recovery_signal.rename(recovery_done)                logger.info("已将 recovery.signal 重命名为 recovery.done")                        # 4. 删除可能引起问题的自动配置文件            if auto_conf.exists():                backup_auto_conf = auto_conf.with_suffix(".auto.conf.bak")                shutil.copy(auto_conf, backup_auto_conf)                auto_conf.unlink()                logger.info("已备份并删除 postgresql.auto.conf 文件")                        # 5. 检查 postgresql.conf 文件            conf_file = data_dir / "postgresql.conf"            if conf_file.exists():                logger.info("检查 postgresql.conf 文件完整性")                # 这里可以添加更多的配置文件检查逻辑                    except FileNotFoundError as e:            logger.warning(f"无法找到数据目录: {str(e)}")                # 6. 确保所有 PostgreSQL 进程已终止        subprocess.run(            ["taskkill", "/F", "/IM", "postgres.exe"],             capture_output=True,            encoding='utf-8',            errors='ignore'        )                # 7. 尝试启动服务        time.sleep(2)        if start_postgres_service():            logger.info("PostgreSQL 服务修复成功")            return True        else:            logger.error("修复后仍无法启动服务")            return False                except Exception as e:        logger.error(f"修复过程中发生错误: {str(e)}")        return Falsedef check_service_status():    """检查服务状态并显示详细信息"""    service_name = get_postgres_service_name()    is_running = is_service_running(service_name)        print(f"服务名称: {service_name}")    print(f"运行状态: {'运行中' if is_running else '已停止'}")        if is_running:        try:            # 尝试连接数据库验证服务状态            import psycopg2            try:                conn = psycopg2.connect(                    dbname='postgres',                    user='postgres',                    password='abc@1234',                    host='localhost',                    port='5432'                )                conn.close()                print("数据库连接: 正常")            except Exception as e:                print(f"数据库连接: 异常 ({str(e)})")        except ImportError:            print("数据库连接: 未安装 psycopg2 库,无法测试连接")        return is_runningdef main():    """主函数:提供命令行界面"""    print("=" * 50)    print("PostgreSQL 服务管理工具")    print("=" * 50)        while True:        print("\n请选择操作:")        print("1. 检查服务状态")        print("2. 启动服务")        print("3. 停止服务")        print("4. 重启服务")        print("5. 修复服务启动问题")        print("6. 退出")                choice = input("请输入选项 (1-6): ").strip()                if choice == "1":            print("\n检查服务状态...")            check_service_status()                    elif choice == "2":            print("\n启动服务...")            if start_postgres_service():                print("服务启动成功")            else:                print("服务启动失败,请尝试修复")                        elif choice == "3":            print("\n停止服务...")            if stop_postgres_service():                print("服务停止成功")            else:                print("服务停止失败")                        elif choice == "4":            print("\n重启服务...")            if restart_postgres_service():                print("服务重启成功")            else:                print("服务重启失败")                        elif choice == "5":            print("\n修复服务启动问题...")            if fix_postgres_service():                print("服务修复成功")            else:                print("服务修复失败,请查看日志文件")                        elif choice == "6":            print("退出程序")            break                    else:            print("无效选项,请重新选择")                    # input("\n按回车键继续...")if __name__ == "__main__":    # 直接运行测试    print("正在启动 PostgreSQL 服务管理工具...")    main()
 |