3

(related to this question)

When using sshd server (Win32-OpenSSH) on windows (with key-based auth for automation), it doesn't work unless it has STDIN (or PTY). For example, running this (from Debian Jessie openssh client) works OK (returning windows username):

ssh -4 -T -o Batchmode=yes winserver whoami

However, those two do not (they simply terminated without executing command and without returning any output):

ssh -4 -T -o Batchmode=yes winserver whoami < /dev/null
ssh -4 -n -T -o Batchmode=yes winserver whoami

This presents problem as it is impossible to run non-interactive ssh commands from programs which do not have open STDIN (like cron(8) or atd(8)).

When using Debian openssh server, it of course works without any problems. Problem only happens with windows ssh servers (Fails with Win32-OpenSSH and FreeSSHD. Bitvise SSHD however seems to work OK, but we're looking at gratis solutions for windows ssh servers; open source, simple and maintained are bonuses)

This has been reported, but does anybody have solution or workaround in the meantime?

2

It the end, I've written this ssh wrapper to work around buggy windows OpenSSH servers which require STDIN even for noninteractive commands which do not use it:

#!/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);

It only uses hostname and command with arguments to run, no other parameters are allowed (I set them in ~/.ssh/config), so you run the script (for example) as myssh winserver whoami < /dev/null. It is just a wrapper around ssh client, which provides fake STDIN, and thus allows noninteractive ssh sessions to be run from cron(8) and atd(8)

1

Thanks Matija-Nalis for the question and solution. For other's gain, here's a crude python implementation.

ssh.py

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>

My use case was similar: Jenkins job failed to execute remote commands.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.