Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
34 changes: 9 additions & 25 deletions scripts/lib/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -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,
Expand All @@ -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",
Expand Down
33 changes: 18 additions & 15 deletions scripts/lib/paramiko_client.py
Original file line number Diff line number Diff line change
Expand Up @@ -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

Expand Down
4 changes: 3 additions & 1 deletion scripts/ssh_daemon.py
Original file line number Diff line number Diff line change
Expand Up @@ -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')


Expand Down Expand Up @@ -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:
Expand Down
4 changes: 3 additions & 1 deletion scripts/ssh_tunnel.py
Original file line number Diff line number Diff line change
Expand Up @@ -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')
Expand Down Expand Up @@ -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({
Expand Down