[1+1=2]

OneAndOneIs2

« Take a tabletWeekly »

Wed, Apr 18, 2012

[Icon][Icon]Just read my mind and take me where I want to go!

• Post categories: Omni, FOSS, Technology, My Life, Programming, Helpful

I had a simple idea at work recently. It took over a hundred lines of perl to implement it. Ho-hum.

Basically, we have a bunch of servers with near-identical layouts at work. We frequently want to ssh to them, and go to one of a handful of directories. This tends to result in writing:

ssh longservername
cd /annoying/path/to/what/you/want

Now when only one server begins with an 'l', you wonder why you have to write 'longservername' in full - something like bash's tab-completion would be nice.

So I started to wonder about a "goto" command - something that would allow you to specify the shortest non-ambiguous string needed to go to a server.

In fact, go one better - what if it could go to the desired directory on the desired server? So you could do "goto l want" instead of the above?

So I sat down and wrote 'g2' - the shortest name I could get away with. And it all works, and it's easy to maintain. So I'm sharing it here - grab a copy, put in your own desired server list & destinations list, and away you go. It won't quite read your mind, but 'g2 d vl' is much nicer than 'ssh devel; cd /var/log

The part I actually found most interesting was the documentation - I took the approach of using the code to generate the docs so they'd always be up-to-date, because otherwise the list of servers & destinations would be bound to go out of date. It's quite cool how well it works, I'll have to try working it in to other places in future.

One other thing I discovered whilst writing: even when it's a laughably-simple concept you're bashing together in a trivial little script, global variables are a massive PITA - they caused me so many problems it was unreal.

P.S. If anyone has a better way of connecting directly to a specific directory on a specific server than ssh server -t 'cd directory/path/ && bash' I am all ears! :)

...

#!/usr/bin/perl

use v5.10;
use strict;
use warnings;

my $first = $ARGV[0];
exit unless $first;

# Handle requests to show help
show_help()     if ($first eq '-h' || $first eq '--help');
generate_help() if  $first eq '--gen_help';

# They didn't ask for help, so get the arguments they DID send in
my $server  = $first;
my $dest    = $ARGV[1];

# Get the full server name from whatever they sent in, or complain bitterly that we can't
my $servername = get_servername($server);

# Now that we know what server they want, start to work out what command we need to run
my $ssh_command = "ssh $servername";

# Do we have a valid destination command?
if ($dest and my $resp = destination($dest)) {
    $ssh_command .= " -t '" . $resp->{command} . " && bash'";
    }

# We have it all worked out. Execute the command
system("$ssh_command");

################################################################################
# Script is done, define the subs it uses here
################################################################################

# Possible destinations that can be specified
sub destination {
    my ($arg) = @_;
    my %dispatch = (
        vl => {
            purpose => "Take user to /var/log",
            command => "cd /var/log",
            },
        );
    if ($arg eq 'info') {
        foreach my $dest (sort keys %dispatch) {
            say "\t$dest\t- ".$dispatch{$dest}{purpose};
            }
        return;
        }
    return 0 unless exists $dispatch{$arg};
    return $dispatch{$arg};
    }

sub get_servername {
    my ($server) = @_;

    # List of known servers
    my %servers = (
        devel       => 'devel',
        localhost   => 'localhost',
        staging     => 'eustaging',
        web         => 'web',
        );

    # If they asked for info, print a list of servers then exit
    if ($server eq 'info') {
        foreach my $server (sort keys %servers) {
            say "\t$server ($servers{$server})";
            }
        return;
        }

    # Since they can supply a partial name, get all possible replies
    my @possibles = grep { /^$server/ } sort keys %servers;
    # If we didn't get any, there's nothing else we can do
    die "I don't know what server you mean" unless @possibles;
    # If we got at least one, return only the first
    return $servers{$possibles[0]};
    }

# The help should print the POD, plus the actual list of servers & flags
sub generate_help {
    # Because we can't trust this file to be in one specific place:
    my $file = __FILE__;
    say `perldoc $file`;
    # Now generate the list of servers & destinations from the code itself
    say 'Available servers (Can be abbreviated to first unique string)';
    get_servername('info');
    say "\nAvailable destinations (Cannot be abbreviated)";
    destination('info');
    exit;
    }
sub show_help {
    # App calls itself here so we can pipe its output to less
    # __FILE__ is only needed so a development version will call itself
    # instead of the normal version
    my $g2 = __FILE__;
    system("$g2 --gen_help | less");
    exit;
    }

=head1 g2

=head2 An application to get you where you want to go ASAP

B<Usage:> g2 <server> [<destination>]

example: You want to connect to the "development" server in the /var/log directory

The command might look something like:
C<g2 dev vl>

See C<g2 --help> for details of specified servers & flags

=cut

1 comment

pdh
Comment from: pdh [Visitor]
ssh server -t looks like your only way...

ssh is only a communication protocol.. what directory you are first put in is going to be down to the server you're talking to.
18/04/12 @ 18:45
 

[Links][icon] My links

[Icon][Icon]About Me

[Icon][Icon]About this blog

[Icon][Icon]My /. profile

[Icon][Icon]My Wishlist

[Icon]MyCommerce

[FSF Associate Member]


August 2014
Mon Tue Wed Thu Fri Sat Sun
 << <   > >>
        1 2 3
4 5 6 7 8 9 10
11 12 13 14 15 16 17
18 19 20 21 22 23 24
25 26 27 28 29 30 31

Search

User tools

XML Feeds

eXTReMe Tracker

Valid XHTML 1.0 Transitional

Valid CSS!

[Valid RSS feed]

powered by b2evolution