diff --git a/scripts/lib/__init__.py b/scripts/lib/__init__.py index 3d7750b..ad821c4 100644 --- a/scripts/lib/__init__.py +++ b/scripts/lib/__init__.py @@ -9,26 +9,13 @@ - 项目级配置管理 - 流式输出和交互式会话 - 批量并发操作 - -快速开始: - from ssh_skill import SSHConfigLoader - - # 加载配置 - client = SSHConfigLoader.from_file(".ssh_config/prod.json") - - # 执行命令 - result = client.execute("whoami && hostname") - print(result.stdout) - - # 批量操作 - from ssh_skill import SSHCluster - cluster = SSHCluster.from_directory(".ssh_config/cluster/") - results = cluster.execute_all("uptime", parallel=True) """ -from .client import SSHClient, SSHResult -from .config import SSHConfigLoader, ServerConfig -from .cluster import SSHCluster, SSHBatchOperations +from .config_v3 import SSHConfigLoaderV3 +from .native_ssh_client import NativeSSHClient, SSHResult +from .paramiko_client import ParamikoClient +from .cluster import SSHCluster +from .sftp_transfer import SFTPTransfer from .utils import ( check_ssh_available, get_ssh_version, @@ -38,15 +25,12 @@ __version__ = "0.1.0" __all__ = [ - # 核心类 - "SSHClient", + "SSHConfigLoaderV3", + "NativeSSHClient", + "ParamikoClient", "SSHResult", - "SSHConfigLoader", - "ServerConfig", "SSHCluster", - "SSHBatchOperations", - - # 工具函数 + "SFTPTransfer", "check_ssh_available", "get_ssh_version", "validate_key_file", diff --git a/scripts/lib/paramiko_client.py b/scripts/lib/paramiko_client.py index 00a198a..9406246 100644 --- a/scripts/lib/paramiko_client.py +++ b/scripts/lib/paramiko_client.py @@ -260,22 +260,25 @@ def _create_password_script(self) -> str: import stat import os - # 创建临时脚本文件 fd, script_path = tempfile.mkstemp(suffix='.sh' if os.name != 'nt' else '.bat', text=True) - - if os.name == 'nt': - # Windows 批处理脚本 - script_content = f'@echo off\necho {self.password}\n' - else: - # Unix shell 脚本 - script_content = f'#!/bin/sh\necho "{self.password}"\n' - - with os.fdopen(fd, 'w') as f: - f.write(script_content) - - # 设置可执行权限(Unix) - if os.name != 'nt': - os.chmod(script_path, stat.S_IRUSR | stat.S_IWUSR | stat.S_IXUSR) + try: + if os.name == 'nt': + script_content = f'@echo off\necho {self.password}\n' + else: + script_content = f'#!/bin/sh\necho "{self.password}"\n' + + with os.fdopen(fd, 'w') as f: + f.write(script_content) + fd = -1 # fd 已被 os.fdopen 接管并关闭 + + if os.name != 'nt': + os.chmod(script_path, stat.S_IRUSR | stat.S_IWUSR | stat.S_IXUSR) + except Exception: + if fd >= 0: + os.close(fd) + if os.path.exists(script_path): + os.unlink(script_path) + raise return script_path diff --git a/scripts/ssh_daemon.py b/scripts/ssh_daemon.py index 2832a41..42d4b53 100644 --- a/scripts/ssh_daemon.py +++ b/scripts/ssh_daemon.py @@ -54,7 +54,8 @@ def get_daemon_id(alias: str) -> str: def get_daemon_info_path(alias: str) -> str: """获取守护进程信息文件路径""" - os.makedirs(DAEMON_DIR, exist_ok=True) + os.makedirs(DAEMON_DIR, mode=0o700, exist_ok=True) + os.chmod(DAEMON_DIR, 0o700) return os.path.join(DAEMON_DIR, f'{get_daemon_id(alias)}.json') @@ -174,6 +175,7 @@ def start(self): info_path = get_daemon_info_path(self.alias) with open(info_path, 'w', encoding='utf-8') as f: json.dump(info, f, ensure_ascii=False, indent=2) + os.chmod(info_path, 0o600) # 输出启动信息到 stdout try: diff --git a/scripts/ssh_tunnel.py b/scripts/ssh_tunnel.py index 13f3ecf..1fa8b83 100644 --- a/scripts/ssh_tunnel.py +++ b/scripts/ssh_tunnel.py @@ -68,7 +68,8 @@ def get_tunnel_id(alias: str, local_port: int) -> str: def get_tunnel_info_path(tunnel_id: str) -> str: """获取 tunnel 信息文件路径""" - os.makedirs(TUNNEL_DIR, exist_ok=True) + os.makedirs(TUNNEL_DIR, mode=0o700, exist_ok=True) + os.chmod(TUNNEL_DIR, 0o700) # 使用 MD5 避免特殊字符问题 safe_id = hashlib.md5(tunnel_id.encode('utf-8')).hexdigest()[:16] return os.path.join(TUNNEL_DIR, f'{safe_id}.json') @@ -208,6 +209,7 @@ def start(self): info_path = get_tunnel_info_path(self.tunnel_id) with open(info_path, 'w', encoding='utf-8') as f: json.dump(info, f, ensure_ascii=False, indent=2) + os.chmod(info_path, 0o600) # 输出启动信息 print(json.dumps({