http://www.perlmonks.org?node_id=637205

I've recently made a move into the UNIX management side of things at $WORK. It's a mess: we have hundreds of UNIX machines, my user name is different on a lot of them, many require various different options to ssh to work properly, etc.

So, I whipped up a little tool today that lets me store the profiles of remote hosts in ~/.sshc/ using YAML format. Then, I can connect as simply as typing:

sshc myhost
And the proper username and parameters will be loaded from the profile. Yes, I could just use PuTTY on Windows, but I needed something scriptable (from other apps) and that would work on non-Win machines and from within Cygwin.

It's MIT licensed, but if you do find it useful, I'd appreciate knowing about it. ;-)

Update: before making use of this, be sure to read afresh1's excellent comments regarding OpenSSH's built-in equivalents. The script below is only really useful if you (like me) have a non-OpenSSH-based commercial client.

#!/usr/bin/perl package main; use strict; use warnings; use vars qw[$VERSION $RELEASE]; #===================================================================== +========= # $Id: sshc.pl,v 1.1 2007/09/05 16:45:56 dpmeyer Exp $ # Stores configs for SSH-ing to various servers #--------------------------------------------------------------------- +--------- # Created 09/05/07 10:34:19 CDT by Darren Meyer <darren.meyer@gmail.co +m> # See POD after __END__ for Usage and Changelog #--------------------------------------------------------------------- +--------- # NOTES: this is released under an MIT license, see POD for details #===================================================================== +========= BEGIN { ## Version will be based on release+CVS version number $RELEASE=0; $VERSION=sprintf '%d.%d.%03d',$RELEASE,q$Revision: 1.1 $=~/(\d+)\. +(\d+)/; } use YAML::Syck qw[LoadFile]; use File::Spec::Functions qw[catdir catfile]; use Getopt::Long; my $config_path=catdir($ENV{HOME},'.sshc'); my $hostname = shift @ARGV; GetOptions( 'config-file|f=s' => \$config_path ); die "Idiot: you need to supply a hostname to connect to\n" unless defined $hostname && length $hostname; Connect(); sub Connect { my $config_file = catfile($config_path,$hostname); die "I don't have a config file for the host '$hostname'\n" unless -f $config_file; my $config = LoadFile($config_file); system( 'ssh', @{$config->{options}}, $config->{user}.'@'.(defined $config->{host} ? $config->{host} + : $hostname), (defined $config->{command} ? $config->{command} : @ARGV), ); print STDERR "Exited with $?\n"; } __END__ =head1 NAME sshc.pl - Connect to an SSH server based on a YAML profile =head1 DESCRIPTION Connects to a host-profile specified in ~/.sshc/I<profile-name>, e.g.: sshc mywebserver It is usually expected that the profile name will match the name of th +e target host (the machine you're SSH-ing to), but this can be overridde +n by the C<host:> element in the profile. Profile files are YAML files that specify, at minimum, a user name and options to pass to the C<ssh> command: --- user: myusername options: [] The profile can also specify a command to run upon connection, and a hostname to use (which defaults to the name of the profile file): --- user: myusername options: - '-2' command: 'uname -a' host: areallylong.fqdn.com See YAML documentation at http://yaml.org for details on constructing +a valid YAML document. Commands to run, if not provided in the profile, will be taken from C< +@ARGV>. See L</USAGE> =head1 USAGE sshc profilename [-f config-file-dir] [-- command] =over 8 =item profilename The name of a file in ~/.sshc (or whichever directory is specified by C<config-file-dir>) from which to read the connection data. This will usually be the hostname, and if a host is not specified in the file, sshc will assume that it is the hostname. =item config-file-dir The directory in which to look for profile files. By default, this is ~/.sshc, but this can be overridden using the C<-f> command-line switc +h =item command If no command is specified by the profile, then this command will be run after connected to the remote host. B<NOTE:> the double-dash (C<-->) before the command is required if the command will contain any dash (C<->) characters; the author recommends that the double-dash always be used when specifying a command. =back =head1 LICENSE The MIT License Copyright (c) 2007 Darren Meyer <darren.meyer@gmail.com> Permission is hereby granted, free of charge, to any person obtaining +a copy of this software and associated documentation files (the "Software"), +to deal in the Software without restriction, including without limitation the +rights to use, copy, modify, merge, publish, distribute, sublicense, and/or s +ell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: The above copyright notice and this permission notice shall be include +d in all copies or substantial portions of the Software. THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRES +S OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILIT +Y, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHAL +L THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISIN +G FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS + IN THE SOFTWARE. =head1 CVS CHANGELOG $Log: sshc.pl,v $ Revision 1.1 2007/09/05 16:45:56 dpmeyer Initial import of unix script project
<radiant.matrix>
Ramblings and references
The Code that can be seen is not the true Code
I haven't found a problem yet that can't be solved by a well-placed trebuchet

Replies are listed 'Best First'.
Re: Cygwin/UNIX ssh connector with profiles
by afresh1 (Hermit) on Sep 06, 2007 at 16:21 UTC
    Shouldn't you have been able to use ssh_config (or more likely ~/.ssh/config)? AFAIK the ssh that comes with cygwin is OpenSSH as is the ssh in most other places, so you should be able to use the config file.
    Host myhost
      User differentuser
      Compression Yes
      Protocol 2
      Other_Options with_settings
    
    It doesn't allow you to specify a RemoteCommand to run, but that seems like an odd feature. It is a kewl hack anyway, but there might be different ways to go about it.
    --
    andrew

      Yes, I should probably reference that; my organization uses a commercial ssh client that doesn't have such config options, which was reason #1.

      Secondly, though -- there are a number of cases at my organization where the "standard hostname" is simply unmemorable (because each char has some "meaning" that no one can recall without a 3"-thick binder); the ability to have a "profile" name that specifies a different hostname is occasionally extremely useful, especially when on a machine where I can't alter /etc/hosts. (And they don't allow aliases in DNS except under very special circumstances. Bastards.)

      For example, I can 'sshc syslog13' and connect as 'radiant' to 'xsv3ncmnw19n20h3-13' (yes, that's a real hostname). It's equally useful when I have to use our long-ass FQDN's, like when I need to log in at the DMZ.

      <radiant.matrix>
      Ramblings and references
      The Code that can be seen is not the true Code
      I haven't found a problem yet that can't be solved by a well-placed trebuchet
        Not using OpenSSH, yes, that could make the script much more useful. You can use the config file for aliases though.
         HostName
                 Specifies the real host name to log into.  This can be used to
                 specify nicknames or abbreviations for hosts.  The default is the
                 name given on the command line.  Numeric IP addresses are also
                 permitted (both on the command line and in HostName specifica-
                 tions).
        
        So you could use something like:
        Host syslog13
            HostName xsv3ncmnw19n20h3-13
            User radiant
        
        Again, all useless with another ssh implementation. Oh well! l8rZ,
        --
        andrew
Re: Cygwin/UNIX ssh connector with profiles
by mr_mischief (Monsignor) on Sep 17, 2007 at 18:13 UTC
    This is a great workaround and indeed a CUFP.

    I call it a workaround and not a solution because there are two much better ways to do it.

    OpenSSH is one. You can get command-line ssh (including OpenSSH) for non-cygwin Windows. Plink, a tool from the PuTTY toolset, is one of my favorites.

    Centralized server administration, while a drastic step, should be considered for this many machines. Having your credentials served from a directory or database and your home directory served from a network location (via for example NFS) could allow you to have one password and one ssh private key. Short of networked home directories, rsync or similar in conjunction with the very type of multi-box script you're writing could keep your private keys synced. Unfortunately, this decision typically involves much more than just the person it would help the most, and it involves time and cost estimates for up-front infrastructure work vs. your ongoing costs.

    As an aside, I use both Cygwin and some native Windows ports of Unixish utils. http://gnuwin32.sourceforge.net/ is one source of these, and http://unxutils.sourceforge.net/ is another. I don't think either package includes ssh, but it's nice to have these for the odd one-or-two command task that doesn't need Cygwin. It's also much easier to carry these around to other systems than all of Cygwin. This type of package sure beats when I wrote rm and ls as DOS batch files.