![Windows 上的 OpenSSH 服务器即使在非交互模式下,如果没有 STDIN 也无法工作](https://linux22.com/image/700121/Windows%20%E4%B8%8A%E7%9A%84%20OpenSSH%20%E6%9C%8D%E5%8A%A1%E5%99%A8%E5%8D%B3%E4%BD%BF%E5%9C%A8%E9%9D%9E%E4%BA%A4%E4%BA%92%E6%A8%A1%E5%BC%8F%E4%B8%8B%EF%BC%8C%E5%A6%82%E6%9E%9C%E6%B2%A1%E6%9C%89%20STDIN%20%E4%B9%9F%E6%97%A0%E6%B3%95%E5%B7%A5%E4%BD%9C.png)
(相关这个问题)
使用 sshd 服务器时(Win32的OpenSSH) 在 Windows 上(使用基于密钥的身份验证进行自动化),除非有 STDIN(或 PTY),否则它不起作用。例如,运行此命令(从 Debian Jessie openssh 客户端)可以正常工作(返回 Windows 用户名):
ssh -4 -T -o Batchmode=yes winserver whoami
但是,这两个却没有(它们只是终止了,没有执行命令,也没有返回任何输出):
ssh -4 -T -o Batchmode=yes winserver whoami < /dev/null
ssh -4 -n -T -o Batchmode=yes winserver whoami
这会带来问题,因为无法从没有打开 STDIN 的程序(例如cron(8)或者艾滋病毒(8))。
使用 Debian openssh 服务器时,它当然可以正常工作。问题只发生在 windows ssh 服务器上(失败Win32的OpenSSH和自由SSHD。Bitvise SSHD但是似乎工作正常,但我们正在寻找适用于 Windows ssh 服务器的免费解决方案;开源、简单和维护是优势)
这已经已报告,但与此同时有人有解决方案或解决方法吗?
答案1
最后,我编写了这个 ssh 包装器来解决有缺陷的 Windows OpenSSH 服务器,这些服务器甚至对于不使用 STDIN 的非交互式命令也需要 STDIN:
#!/usr/bin/perl
use strict;
use warnings;
use Net::OpenSSH;
my $HOSTNAME = shift;
my $ssh = Net::OpenSSH->new($HOSTNAME);
my ($in_pipe, undef, undef, $pid) =
$ssh->open_ex( { stdin_pipe => 1 }, @ARGV) or die "open_ex failed: " . $ssh->error;
waitpid($pid, 0);
它只使用主机名和带参数的命令来运行,不允许使用其他参数(我在 中设置了它们~/.ssh/config
),因此您可以将脚本(例如)作为 运行myssh winserver whoami < /dev/null
。它只是 ssh 客户端的包装器,它提供了伪造的 STDIN,因此允许从 运行非交互式 ssh 会话cron(8)和艾滋病毒(8)
答案2
感谢 Matija-Nalis 提出的问题和解决方案。为了其他人的利益,这里有一个粗略的 Python 实现。
ssh工具
import sys
import paramiko
client = paramiko.SSHClient()
client.set_missing_host_key_policy(paramiko.AutoAddPolicy())
client.connect(sys.argv[2], username=sys.argv[1])
stdin, stdout, stderr = client.exec_command(sys.argv[3])
errlines = stderr.readlines()
outlines = stdout.readlines()
for l in outlines:
print l.rstrip()
if len(errlines):
print "WARNING: stderr generated:"
for l in errlines:
print l.rstrip()
exit(stdout.channel.recv_exit_status())
python ssh.py <user> <hostname> <command>
我的用例类似:詹金斯作业无法执行远程命令。