使用Paramiko通过SSH向Ultimaker S3发G-code命令出现-c标识报错如何解决
报错原因
Ultimaker的SSH服务端没有使用标准系统Shell作为登录后默认程序,而是直接启动了自定义的G代码指令接收程序。Paramiko的exec_command接口默认会向远程发送[默认shell] -c 你传入的命令格式的请求,-c参数会被自定义接收程序识别为输入内容的一部分,因此触发语法报错。
解决方案
方案1:使用Paramiko交互式Shell通道(无额外依赖)
改用invoke_shell()方法创建交互式会话,完全模拟手动SSH登录输入命令的行为,不会自动拼接-c参数,同时支持批量发送多行G代码:
import paramiko import time # SSH初始化逻辑不变 ssh = paramiko.SSHClient() ssh.load_system_host_keys() ssh.set_missing_host_key_policy(paramiko.AutoAddPolicy()) ssh.connect( router_ip, username=router_username, password=router_password, look_for_keys=False ) # 启动交互式会话 shell = ssh.invoke_shell() # 等待远程自定义程序加载完成 time.sleep(1) # 单条命令发送示例 shell.send("sendgcode G28\n") time.sleep(2) output = shell.recv(4096).decode() print(output) # 多行G代码批量发送示例 gcode_list = [ "G28", "G1 X10 Y10 F3000", "G1 Z5 F1000" ] for cmd in gcode_list: shell.send(f"sendgcode {cmd}\n") time.sleep(0.5) # 可选读取返回结果做执行校验 res = shell.recv(1024).decode() print(res) # 会话关闭 shell.close() ssh.close()
如果需要同时运行本地其他进程,将SSH交互逻辑放到单独线程执行即可,不会阻塞主进程任务。
方案2:调用系统原生SSH客户端(兼容性最好)
如果不想处理Paramiko的交互逻辑,可以直接调用操作系统自带的SSH客户端,和手动操作行为完全一致,无兼容问题:
import subprocess from subprocess import PIPE import threading def send_gcode_task(): proc = subprocess.Popen( ["ssh", f"{router_username}@{router_ip}"], stdin=PIPE, stdout=PIPE, stderr=PIPE, text=True ) # 发送多条G代码 gcode_list = ["G28", "G1 X0 Y0", "M107"] for cmd in gcode_list: proc.stdin.write(f"sendgcode {cmd}\n") proc.stdin.flush() print(proc.stdout.readline()) # 结束会话 proc.stdin.write("exit\n") proc.stdin.close() proc.wait() # 放到子线程执行,不阻塞本地其他任务 threading.Thread(target=send_gcode_task, daemon=True).start()
其他可选库
如果你的本地程序采用异步架构,可以使用AsyncSSH库,它对交互式SSH会话的封装比Paramiko更简洁,异步IO的模式也更适合同时运行多任务的场景,不会出现自动加-c参数的问题。
内容的提问来源于stack exchange,提问作者AD1617
相关产品推荐
相关产品推荐

