aiida-ssh2win 完全指南及实战案例

发布时间:2026/11/5 7:56:04
aiida-ssh2win 完全指南及实战案例

一、aiida-ssh2win 是什么

aiida-ssh2win是 AiiDA 生态中的一个传输插件(transport plugin),用于让运行在 Linux 或 macOS 上的 AiiDA 主节点,通过 SSH 连接到Windows 主机,并在 Windows 上执行命令、上传下载文件。它解决的核心问题是:AiiDA 原生的 SSH 传输层默认假设远端是类 Unix 系统,而 Windows 的默认 Shell(cmd.exe / PowerShell)在路径分隔符、命令语法、退出码、文件权限等方面与 Unix 差异很大,直接复用会导致大量兼容性问题。

简单来说,它把「AiiDA 的远程计算资源」这一抽象,扩展到了 Windows 机器上,使你可以把 Windows 上的计算软件(如 VASP、Quantum ESPRESSO 的 Windows 编译版、Materials Studio、自研的 .exe 程序)纳入 AiiDA 的工作流管理。

二、核心功能概览

  • SSH 连接管理:基于 Paramiko 建立到 Windows 主机的 SSH 会话,支持密码与密钥认证。
  • 命令执行:在 Windows 上通过 cmd.exe 或 PowerShell 执行命令,并正确解析退出码。
  • 文件传输:基于 SFTP 实现上传、下载、目录创建、删除、重命名等操作。
  • 路径适配:自动处理 Windows 的盘符路径(如C:\Users\aiida\work)与 POSIX 路径之间的转换。
  • 与 AiiDA Computer 集成:注册为 AiiDA 的 transport 类型,可直接在verdi computer setup中选用。
  • 作业调度对接:配合direct调度器(Windows 上通常没有 Slurm/PBS),实现「提交即执行」。

三、安装与环境准备

3.1 前置条件

项目要求
AiiDA 版本aiida-core >= 2.0
Python3.8 及以上
Windows 端Windows 10/11 或 Windows Server,已启用 OpenSSH Server
网络AiiDA 主节点可 SSH 访问 Windows 主机的 22 端口

3.2 在 Windows 上启用 OpenSSH Server

以管理员身份打开 PowerShell,执行:

Add-WindowsCapability -Online -Name OpenSSH.Server~~~~0.0.1.0 Start-Service sshd Set-Service -Name sshd -StartupType 'Automatic' New-NetFirewallRule -Name sshd -DisplayName 'OpenSSH Server' -Enabled True -Direction Inbound -Protocol TCP -Action Allow -LocalPort 22

随后确认默认 Shell。若希望使用 PowerShell 而非 cmd.exe,可执行:

New-ItemProperty -Path "HKLM:\SOFTWARE\OpenSSH" -Name DefaultShell ` -Value "C:\Windows\System32\WindowsPowerShell\v1.0\powershell.exe" -PropertyType String -Force

3.3 安装插件

pip install aiida-ssh2win verdi plugin list aiida.transports

若输出中出现ssh2win,说明插件已注册成功。

3.4 注册 AiiDA Computer

verdi computer setup \ --label win-node-01 \ --hostname 192.168.1.50 \ --transport ssh2win \ --scheduler direct \ --work-dir 'C:\aiida\work' \ --mpirun-command 'mpiexec -n {tot_num_mpiprocs}' \ --shebang ' ' verdi computer configure ssh2win win-node-01

配置过程中会提示输入用户名、端口、密钥路径、连接超时等参数。完成后用verdi computer test win-node-01验证连通性。

四、语法与参数详解

4.1 传输层配置参数

参数类型默认值说明
hostnamestr—Windows 主机地址或域名
portint22SSH 端口
usernamestr—Windows 登录用户名
passwordstrNone密码认证时使用,建议改用密钥
key_filenamestrNone私钥文件路径
key_policystrAutoAddPolicy主机密钥策略,生产环境建议 RejectPolicy
timeoutint60连接与命令执行超时(秒)
allow_agentboolTrue是否使用 SSH Agent
look_for_keysboolTrue是否自动搜索 ~/.ssh 下的密钥
shellstrcmd远端 Shell 类型,可选cmd或powershell
use_login_shellboolFalse是否以登录 Shell 方式执行
path_separatorstr\远端路径分隔符

4.2 常用方法

from aiida.transports.plugins.ssh2win import Ssh2WinTransport with Ssh2WinTransport(hostname='192.168.1.50', username='aiida', key_filename='/home/aiida/.ssh/id_rsa') as transport: # 执行命令 retcode, stdout, stderr = transport.exec_command_wait('dir C:\\aiida\\work') # 文件操作 transport.putfile('/local/input.in', 'C:\\aiida\\work\\input.in') transport.getfile('C:\\aiida\\work\\output.out', '/local/output.out') # 目录操作 transport.mkdir('C:\\aiida\\work\\calc_001') transport.chdir('C:\\aiida\\work\\calc_001') print(transport.getcwd()) # 判断与列举 print(transport.isdir('C:\\aiida\\work')) print(transport.listdir('C:\\aiida\\work'))

4.3 关键方法说明

方法返回值说明
exec_command_wait(cmd)(retcode, stdout, stderr)同步执行命令并等待结束
putfile(src, dst)None上传单个文件
puttree(src, dst)None递归上传目录
getfile(src, dst)None下载单个文件
gettree(src, dst)None递归下载目录
mkdir(path)None创建目录,已存在时抛异常
rmtree(path)None递归删除目录
copyfile(src, dst)None远端内部复制文件
rename(src, dst)None重命名或移动
path_exists(path)bool判断路径是否存在
isdir / isfilebool类型判断
get_attribute(path)dict获取大小、修改时间等属性

五、16 个实际应用案例

案例 1:验证 Windows 主机连通性

from aiida.transports.plugins.ssh2win import Ssh2WinTransport with Ssh2WinTransport(hostname='192.168.1.50', username='aiida', key_filename='/home/aiida/.ssh/id_rsa') as t: code, out, err = t.exec_command_wait('hostname') print(code, out.strip())

用于排查网络、认证与 Shell 是否正常,是最基础的健康检查。

案例 2:在 Windows 上创建计算工作目录

with Ssh2WinTransport(hostname='192.168.1.50', username='aiida') as t: workdir = r'C:\aiida\work\calc_20240101' if not t.path_exists(workdir): t.mkdir(workdir) t.chdir(workdir) print(t.getcwd())

案例 3:上传单个输入文件

with Ssh2WinTransport(hostname='192.168.1.50', username='aiida') as t: t.putfile('/home/aiida/inputs/INCAR', r'C:\aiida\work\calc_001\INCAR')

案例 4:递归上传整个输入目录

with Ssh2WinTransport(hostname='192.168.1.50', username='aiida') as t: t.puttree('/home/aiida/inputs/vasp_case', r'C:\aiida\work\vasp_case')

适合包含多个输入文件(INCAR、POSCAR、POTCAR、KPOINTS)的场景。

案例 5:下载计算结果文件

with Ssh2WinTransport(hostname='192.168.1.50', username='aiida') as t: t.getfile(r'C:\aiida\work\calc_001\OUTCAR', '/home/aiida/results/OUTCAR')

案例 6:递归下载整个输出目录

with Ssh2WinTransport(hostname='192.168.1.50', username='aiida') as t: t.gettree(r'C:\aiida\work\calc_001', '/home/aiida/results/calc_001')

案例 7:执行 Windows 原生可执行程序

with Ssh2WinTransport(hostname='192.168.1.50', username='aiida') as t: t.chdir(r'C:\aiida\work\calc_001') code, out, err = t.exec_command_wait(r'C:\software\vasp.exe') print('retcode =', code) print(out[:500])

案例 8:使用 PowerShell 执行脚本

with Ssh2WinTransport(hostname='192.168.1.50', username='aiida', shell='powershell') as t: code, out, err = t.exec_command_wait( 'Get-ChildItem C:\\aiida\\work | Measure-Object | Select-Object -ExpandProperty Count') print('文件数量:', out.strip())

案例 9:通过 mpiexec 并行运行

with Ssh2WinTransport(hostname='192.168.1.50', username='aiida') as t: t.chdir(r'C:\aiida\work\calc_001') code, out, err = t.exec_command_wait( r'mpiexec -n 8 C:\software\vasp_std.exe') print(code)

案例 10:检查远端文件是否存在并读取大小

with Ssh2WinTransport(hostname='192.168.1.50', username='aiida') as t: path = r'C:\aiida\work\calc_001\OUTCAR' if t.path_exists(path): attr = t.get_attribute(path) print('大小:', attr.get('st_size'), '字节')

案例 11:列出目录内容并筛选

with Ssh2WinTransport(hostname='192.168.1.50', username='aiida') as t: files = t.listdir(r'C:\aiida\work\calc_001') outcars = [f for f in files if f.lower().endswith('.outcar')] print(outcars)

案例 12:远端复制与重命名结果文件

with Ssh2WinTransport(hostname='192.168.1.50', username='aiida') as t: src = r'C:\aiida\work\calc_001\OUTCAR' bak = r'C:\aiida\work\calc_001\OUTCAR.bak' t.copyfile(src, bak) t.rename(bak, r'C:\aiida\work\calc_001\OUTCAR_20240101.bak')

案例 13:清理临时目录

with Ssh2WinTransport(hostname='192.168.1.50', username='aiida') as t: tmp = r'C:\aiida\work\tmp' if t.path_exists(tmp): t.rmtree(tmp) t.mkdir(tmp)

案例 14:在 AiiDA CalcJob 中使用

from aiida.engine import CalcJob from aiida.common.datastructures import CalcInfo, CodeInfo class WindowsVaspJob(CalcJob): @classmethod def define(cls, spec): super().define(spec) spec.input('parameters', valid_type=orm.Dict) spec.input('structure', valid_type=orm.StructureData) spec.output('output_parameters', valid_type=orm.Dict) def prepare_for_submission(self, folder): folder.write_text_file('INCAR', self.inputs.parameters.get_dict()['incar']) calcinfo = CalcInfo() calcinfo.codes_info = [CodeInfo()] calcinfo.codes_info[0].cmdline = [r'C:\software\vasp_std.exe'] calcinfo.retrieve_list = ['OUTCAR', 'OSZICAR'] return calcinfo

配合direct调度器与ssh2win传输层,即可把 Windows 上的 VASP 纳入 AiiDA 工作流。

案例 15:批量提交多个计算任务

from aiida.engine import submit from aiida.orm import load_code, Dict code = load_code('vasp-win@win-node-01') for i, params in enumerate(param_list): inputs = {'code': code, 'parameters': Dict(dict=params)} node = submit(WindowsVaspJob, **inputs) print(f'任务 {i} 已提交,PK = {node.pk}')

案例 16:异常重试与日志记录

import logging, time from aiida.transports.plugins.ssh2win import Ssh2WinTransport logger = logging.getLogger(__name__) def run_with_retry(cmd, retries=3, delay=5): for attempt in range(1, retries + 1): try: with Ssh2WinTransport(hostname='192.168.1.50', username='aiida', timeout=120) as t: code, out, err = t.exec_command_wait(cmd) if code == 0: return out logger.warning('第 %d 次执行失败,retcode=%d, stderr=%s', attempt, code, err) except Exception as exc: logger.error('第 %d 次连接异常: %s', attempt, exc) time.sleep(delay) raise RuntimeError(f'命令执行失败: {cmd}')

六、常见错误与排查

错误现象可能原因解决方案
Connection refusedWindows 未启动 sshd 或防火墙拦截启动 sshd 服务并放行 22 端口
Authentication failed用户名格式错误或密钥未授权Windows 用户名区分大小写;将公钥写入C:\Users\<user>\.ssh\authorized_keys
FileNotFoundError: C:\...路径分隔符被转义错误使用原始字符串r'C:\path'或双反斜杠
命令返回码恒为 0cmd.exe 不传递退出码改用 PowerShell 或在命令后追加&& exit /b %ERRORLEVEL%
中文路径乱码编码不一致统一使用 UTF-8,或在 PowerShell 中设置[Console]::OutputEncoding
Permission denied写入失败Windows 目录 ACL 限制为 aiida 用户授予工作目录的写权限
上传大文件超时默认 timeout 过短调大timeout参数至 300 以上
Host key verification failed主机密钥未记录首次连接时确认指纹,或配置known_hosts

七、使用注意事项

  • 优先使用密钥认证:密码认证在自动化场景中不安全,且部分 Windows 配置下不稳定。
  • 路径统一用原始字符串:Python 中\n、\t会被转义,务必使用r'C:\path'。
  • 明确 Shell 类型:cmd 与 PowerShell 的命令语法差异大,配置时显式指定shell参数。
  • 退出码不可靠时显式判断:建议在命令末尾追加退出码输出,或解析 stdout 中的关键字。
  • 避免在 Windows 上依赖 Unix 权限模型:AiiDA 的chmod相关操作在 Windows 上可能无效,需在插件层做兼容处理。
  • 调度器选择 direct:Windows 上通常没有 Slurm/PBS,使用direct调度器最稳妥。
  • 注意并发连接数:Windows OpenSSH 对并发会话有限制,批量提交时建议控制并发。
  • 日志与审计:开启 AiiDA 的 transport 日志,便于排查远端执行问题。
  • 版本兼容性:升级 aiida-core 后需确认插件版本匹配,避免 API 变更导致失败。

八、总结

aiida-ssh2win填补了 AiiDA 在 Windows 计算资源管理上的空白。通过它,你可以把 Windows 上的商业软件、自研程序与 AiiDA 的工作流、 provenance 追踪能力结合起来。掌握其配置参数、路径处理规则与退出码语义,是稳定运行的关键。建议先在测试机上跑通本文的 16 个案例,再逐步迁移到生产环境。

《AI提示工程必知必会》为读者提供了丰富的AI提示工程知识与实战技能,主要包括各类提示词的应用,如问答式、指令式、状态类、建议式、安全类和感谢类提示词,以及如何通过实战演练掌握提示词的使用技巧;使用提示词进行文本摘要、改写重述、语法纠错、机器翻译等语言处理任务,以及在数据挖掘、程序开发等领域的应用;AI在绘画创作上的应用,百度文心一言和阿里通义大模型这两大智能平台的特性与功能,以及市场调研中提示词的实战应用。通过阅读《AI提示工程必知必会》,读者可掌握如何有效利用AI提示工程提升工作效率,创新工作流程,并在职场中脱颖而出。