dayton has asked for the wisdom of the Perl Monks concerning the following question:

I'm trying to setup a script using Net::SSH::Perl to connect to several hosts and need some insight.. I'm able to connect either with password or rsa/dsa key as long as I specify the username - however on a few hosts the user name is different (and defined in my ~/.ssh/config) How can I get my script to grab the "User" value from the "Hostname" in my config file?

foreach $host (@HOSTS) { $ssh = Net::SSH::Perl->new("$host",debug=>1,option +s => ["ConnectTimeout=5","StrictHostKeyChecking=no"]); $ssh->login($user); ($out, $err, $exit)=$ssh->cmd($exec_cmd); }

per the debug, it's reading my config but not getting the User for a particular host:

Host host2 hostname host2.mydomain User user1
my_host: Reading configuration data /home/djones/.ssh/config my_host: Reading configuration data /etc/ssh_config my_host: Connecting to host2, port 22. my_host: Remote version string: SSH-2.0-OpenSSH_5.3p1 Debian-3ubuntu7. +1 my_host: Remote protocol version 2.0, remote software version OpenSSH_ +5.3p1 Debian-3ubuntu7.1 my_host: Net::SSH::Perl Version 1.36, protocol version 2.0. .y_host: No compat match: OpenSSH_5.3p1 Debian-3ubuntu7.1 my_host: Connection established. my_host: Sent key-exchange init (KEXINIT), wait response. my_host: Algorithms, c->s: 3des-cbc hmac-sha1 none my_host: Algorithms, s->c: 3des-cbc hmac-sha1 none my_host: Entering Diffie-Hellman Group 1 key exchange. my_host: Sent DH public key, waiting for reply. my_host: Received host key, type 'ssh-dss'. my_host: Host 'host2' is known and matches the host key. my_host: Computing shared secret key. my_host: Verifying server signature. my_host: Waiting for NEWKEYS message. my_host: Send NEWKEYS. my_host: Enabling encryption/MAC/compression. my_host: Sending request for user-authentication service. my_host: Service accepted: ssh-userauth. my_host: Trying empty user-authentication request. my_host: Authentication methods that can continue: publickey,password. my_host: Next method to try is publickey. my_host: Publickey: testing agent key '/home/djones/.ssh/id_dsa' my_host: Authentication methods that can continue: publickey,password. my_host: Next method to try is publickey. my_host: Next method to try is password. my_host: Trying password authentication. my_host: Will not query passphrase in batch mode. my_host: Authentication methods that can continue: publickey,password. my_host: Next method to try is publickey. my_host: Publickey: testing agent key '/home/djones/.ssh/id_dsa' my_host: Authentication methods that can continue: publickey,password. my_host: Next method to try is publickey. Received disconnect message: Too many authentication failures for djon +es at /usr/share/perl5/vendor_perl/Net/SSH/Perl/AuthMgr.pm line 143.

Replies are listed 'Best First'.
Re: Net::SSH::Perl and getting User from config
by salva (Canon) on May 02, 2015 at 06:52 UTC
    As you seem to be running your script in a Linux/Unix box, you should consider using Net::OpenSSH instead. It runs on top OpenSSH and uses its configuration.
Re: Net::SSH::Perl and getting User from config
by pme (Monsignor) on May 02, 2015 at 07:23 UTC
    Hi dayton,

    Have you checked the permissions?

    $ chmod 700 ~/.ssh $ chmod 600 ~/.ssh/config
Re: Net::SSH::Perl and getting User from config
by Don Coyote (Hermit) on May 02, 2015 at 08:21 UTC

    Hello. The problem is not in the connecting logic, but in the extraction of the users from the config file. To suggest solution to this we need to see your config extraction code.

    As an exercise, I have assumed the config file is not extracted automatically from an ssh method.

    Untested

    #/usr/bin/perl -T use strict; use warnings; my( $index_of_host, %HOSTLIST ); OLOOP: while(<DATA>){ s/^\s*// , s/\s*$//; # eradicate outer whitespace next OLOOP until m/^Host\s+(\w+)$/; # untaint $1 $index_of_host = $1; ILOOP: while(defined $index_of_host && my $line = <DATA>){ $line =~ s/^\s*//; # eradicate inner outer whitespace $line =~ s/\s*$//; # assume an empty line between 'Host' lists in config file undef $index_of_host && last ILOOP unless $line; if( $line =~ m/^hostname\s+(\w+)$/ ){ # untaint $1; $hostname = $1 && next ILOOP; } if( $line =~ m/^User\s+(\w+)$/ ){ # untaint $1; push @{$HOSTLIST{$index_of_host}->{$hostname}}, $1; } } } __DATA__ #hosts Host host1 hostname host1.mydomain User user1 Host host2 hostname host2.mydomain User user1

    Now your users are inside an anonymous array, keyed by the hostname, in an anonymous hash, keyed by the index of hosts. To retrieve:

    foreach my $indhost( keys %HOSTLIST ){ foreach my $hname( keys %$indhost ){ foreach my $user ( @{ $hname } ){ #host print $hname #user print $user } } }

    Using a similar approach, you can optimise down the config file and potentially remove the 'index_of_hosts' level from the %HOSTLISTS hash This would make the extraction logic simpler.

    # optimised config file host1.mydomain user1 user2 #hostundef #user1 #user2 host2.mydomain user1 user2

    Many Meek Monks Monikers Mention Meekness
      Thanks all for the replies/pointers...

      The answer was much simpler... the "Host" section in my .ssh/config file had extra whitespace in the name so it didn't match... After I trimmed the whitespace, this is working as expected with no further edits to my script...