如何通过SSH在远程设备执行命令?已尝试多种方法均失败求解决
看起来你遇到的是SSH非交互式执行命令时会话被远程主机强制关闭的问题,我来帮你一步步排查和解决:
第一步:确认基础连接是否正常
先试试能不能正常交互式登录远程主机:
ssh user@IP
如果能成功登录,说明SSH的基础连接和认证是没问题的,问题出在非交互式命令执行的环节;如果连交互式登录都失败,那先解决基础连接问题(比如防火墙、SSH服务状态、账号权限等)。
第二步:排查远程用户的Shell启动脚本
这是最常见的原因——远程用户的~/.bashrc、~/.profile或者~/.bash_profile这类shell启动脚本里,有导致会话直接退出的逻辑。比如:
- 脚本里直接写了
exit命令 - 有判断是否为交互式shell的逻辑,比如
[ -z "$PS1" ] && exit(非交互式会话下PS1为空,触发退出)
解决方法:
登录到远程主机,编辑对应的启动脚本,把会终止会话的逻辑调整为只在交互式会话下执行。比如把:
[ -z "$PS1" ] && exit
改成:
# 只有交互式会话才执行后续配置 if [ -n "$PS1" ]; then # 这里放原来的交互式专属配置,比如设置提示符、别名等 fi
或者直接注释掉导致退出的命令。
第三步:测试最简命令,排除命令本身问题
先不要执行复杂的my command,试试执行一个最简单的命令,比如:
ssh user@IP "echo 'Hello World'"
如果这个命令能成功返回结果,说明你的原始命令可能有问题(比如权限不足、路径错误、依赖缺失等),需要单独排查命令本身;如果最简命令也失败,继续往下排查。
第四步:检查远程SSH服务器配置
登录到远程主机,查看/etc/ssh/sshd_config文件,重点检查以下配置:
- ForceCommand:如果这个配置被设置,远程服务器会强制执行指定的命令,完全忽略你通过SSH发送的命令。如果存在这个配置,要么删除它,要么调整为符合你需求的命令。
- PermitUserEnvironment:如果这个配置是
no,可能会影响shell环境变量的加载,导致命令执行失败。可以尝试临时改为yes,重启sshd后测试。
修改配置后,记得重启SSH服务:
# CentOS/RHEL systemctl restart sshd # Debian/Ubuntu systemctl restart ssh
第五步:查看远程服务器的SSH日志
远程服务器的日志会告诉你连接被关闭的具体原因,这是最直接的排查依据:
- CentOS/RHEL:查看
/var/log/secure - Debian/Ubuntu:查看
/var/log/auth.log
搜索包含你本地IP或者用户名的日志条目,里面会有类似Connection closed by ...的详细原因,比如权限不足、命令执行失败、shell脚本错误等。
针对Perl Net::OpenSSH的额外调试
如果用Net::OpenSSH还是失败,可以开启调试模式,查看详细的SSH连接日志:
#!/bin/perl use strict; use Net::OpenSSH; my $hostname = "IP"; my $username = "user"; my $password = "password"; my $cmd = "command"; # 开启调试模式,输出详细日志 my $ssh = Net::OpenSSH->new( host=>"$hostname", user=>"$username", port=>22, password=>"$password", master_opts => [-v] # 开启SSH verbose模式 ); $ssh->system($cmd);
运行脚本后,会输出大量SSH连接的细节,从中可以找到连接被关闭的具体原因。
其他尝试
如果以上方法都不行,可以试试显式指定shell执行命令:
ssh user@IP 'bash -c "my command"'
或者用ssh -T参数禁用伪终端(和-t相反):
ssh -T user@IP "my command"
内容的提问来源于stack exchange,提问作者Александр Кандрин




