├── .gitignore ├── README.md ├── docs ├── Screen Shot 2015-12-06 at 12.47.53 PM.png └── Screen Shot 2015-12-06 at 12.48.10 PM.png └── ssh2 /.gitignore: -------------------------------------------------------------------------------- 1 | python_package/ 2 | devops/ -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # SSH to Your EC2 Instance Instantly 2 | SSH2 is an interactive command line tool which allows you to quickly ssh to an EC2 instance. You can select from a list of running servers under your account. 3 | 4 | ![](https://raw.githubusercontent.com/soheil/ssh2/master/docs/Screen%20Shot%202015-12-06%20at%2012.47.53%20PM.png) 5 | ![](https://raw.githubusercontent.com/soheil/ssh2/master/docs/Screen%20Shot%202015-12-06%20at%2012.48.10%20PM.png) 6 | 7 | ## Usage 8 | ``` 9 | $ ssh2 1 10 | ``` 11 | 12 | ``` 13 | $ ssh2 -h 14 | Usage: ssh2 [options] [server_number] 15 | server_number: a numeric value corresponding to the server number 16 | e.g.: 'ssh2 1' will ssh into the 1st server in the list. 17 | 18 | Options: 19 | -h, --help show this help message and exit 20 | -x, --bust-cache refetch servers list from AWS 21 | -u USER, --user=USER provide user (default: ubuntu) 22 | -i IDENTITY, --identity=IDENTITY 23 | provide identity file 24 | -p PROFILE, --profile=PROFILE 25 | provide AWS profile 26 | --ip=IP connect using IP instead of DNS 27 | -g GREP, --grep=GREP filter the server list 28 | ``` 29 | 30 | ### Filtering the list by EC2 instance name 31 | 32 | ``` 33 | $ ssh2 -g webrt 34 | 35 | Servers list: 36 | 37 | [1] ec2-XX-XX-XX-XX.us-west-2.compute.amazonaws.com webrtc-kurento 38 | 39 | Which server would you like to connect to [1]? 40 | 41 | $ ssh2 -g webrt 1 42 | 43 | Connecting to webrtc-kurento ec2-XX-XX-XX-XX.us-west-2.compute.amazonaws.com 44 | ``` 45 | 46 | 47 | 48 | ## Requirements 49 | * [AWS CLI](https://aws.amazon.com/cli/) 50 | * Python 51 | 52 | ## Installation 53 | ``` 54 | pip install ssh2 55 | ``` 56 | 57 | or 58 | 59 | without using Python package manager: 60 | ``` 61 | git clone https://github.com/soheil/ssh2.git 62 | cd ssh2 63 | ln -sf $(pwd)/ssh2 /usr/local/bin/ 64 | ``` 65 | 66 | ## Author 67 | Soheil Yasrebi, [@soheil](https://twitter.com/soheil) 68 | -------------------------------------------------------------------------------- /docs/Screen Shot 2015-12-06 at 12.47.53 PM.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/soheil-zz/ssh2/b1e0a83b62c6ef7abf966e185367835e7bacf5f6/docs/Screen Shot 2015-12-06 at 12.47.53 PM.png -------------------------------------------------------------------------------- /docs/Screen Shot 2015-12-06 at 12.48.10 PM.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/soheil-zz/ssh2/b1e0a83b62c6ef7abf966e185367835e7bacf5f6/docs/Screen Shot 2015-12-06 at 12.48.10 PM.png -------------------------------------------------------------------------------- /ssh2: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python 2 | import subprocess, json, os 3 | from optparse import OptionParser 4 | 5 | usage = "usage: %prog [options] [server_number]\n\ 6 | server_number: a numeric value corresponding to the server number\n\ 7 | e.g.: '%prog 1' will ssh into the 1st server in the list." 8 | 9 | parser = OptionParser(usage) 10 | parser.add_option("-x", "--bust-cache", action="store_true", 11 | help="refetch servers list from AWS") 12 | parser.add_option("-u", "--user", action="store", 13 | dest="user", default="ubuntu", 14 | help="provide user (default: ubuntu)") 15 | parser.add_option("-i", "--identity", action="store", 16 | dest="identity", default="", 17 | help="provide identity file") 18 | parser.add_option("-p", "--profile", action="store", 19 | dest="profile", default="", 20 | help="provide AWS profile") 21 | parser.add_option("-r", "--region", action="store", 22 | dest="region", default="", 23 | help="provide AWS region") 24 | parser.add_option("--ip", action="store", 25 | dest="ip", default=0, 26 | help="connect using IP instead of DNS") 27 | parser.add_option("-g", "--grep", action="store", 28 | dest="grep", default="", 29 | help="filter the server list") 30 | (options, args) = parser.parse_args() 31 | 32 | cache_dir = os.environ.get('XDG_CACHE_HOME', 33 | os.path.join(os.path.expanduser('~'), '.cache')) 34 | if not os.path.exists(cache_dir): 35 | os.makedirs(cache_dir) 36 | if options.region: 37 | cache_file_list = os.path.join(cache_dir, 'ssh2_list_' + options.region) 38 | cache_file_num = os.path.join(cache_dir, 'ssh2_num_' + options.region) 39 | else: 40 | cache_file_list = os.path.join(cache_dir, 'ssh2_list') 41 | cache_file_num = os.path.join(cache_dir, 'ssh2_num') 42 | 43 | num = '' 44 | if args: 45 | if not args[0].isdigit(): 46 | print "'server_number' must be a numeric value" 47 | exit() 48 | num = int(args[0]) 49 | 50 | 51 | def extract_name(instance): 52 | if 'Tags' in instance: 53 | for tag in instance['Tags']: 54 | if tag['Key'] == 'Name' and tag['Value']: 55 | return tag['Value'] 56 | return '.' 57 | 58 | if options.bust_cache or not os.path.exists(cache_file_list) \ 59 | or options.profile: 60 | 61 | print "Fetching servers..." 62 | if os.path.exists(cache_file_num): 63 | os.remove(cache_file_num) 64 | aws_cmd = 'aws ec2 describe-instances --output json' 65 | if options.profile: 66 | aws_cmd += ' --profile ' + options.profile 67 | if options.region: 68 | aws_cmd += ' --region ' + options.region 69 | 70 | child = subprocess.Popen(aws_cmd, 71 | shell=True, stdout=subprocess.PIPE, stderr=subprocess.PIPE) 72 | output = child.stdout.read() 73 | error = child.stderr.read() 74 | if error: 75 | print error 76 | print 'Unable to fetch any servers.' 77 | exit() 78 | with open(cache_file_list, 'w') as f: 79 | f.write(output) 80 | 81 | output = open(cache_file_list).read() 82 | parsed = json.loads(output) 83 | 84 | all_instances = [] 85 | if not parsed['Reservations']: 86 | print 'Coult not find any servers.' 87 | if os.path.exists(cache_file_list): 88 | os.remove(cache_file_list) 89 | exit() 90 | for instances in parsed['Reservations']: 91 | for instance in instances['Instances']: 92 | all_instances.append(instance) 93 | 94 | if options.grep: 95 | all_instances = [inst for inst in all_instances if options.grep in extract_name(inst)] 96 | 97 | if not num: 98 | print "\nServers list:\n" 99 | for i, instance in enumerate(all_instances, 1): 100 | choice = '[%d]' % i 101 | name = extract_name(instance) 102 | print '%-4s %-35s %-55s' % (choice, name + (35 - len(name)) * '.', instance['PublicDnsName']) 103 | 104 | default_num = 1 105 | if os.path.exists(cache_file_num): 106 | default_num = open(cache_file_num).read() 107 | ok = not not num 108 | while not ok or not num: 109 | try: 110 | num = raw_input("\nWhich server would you like to connect to [" + 111 | str(default_num) + "]? ") 112 | if not num: 113 | num = int(default_num) 114 | break 115 | ok = num.isdigit() and 1 <= int(num) <= i 116 | if ok: 117 | num = int(num) 118 | break 119 | print "ERR: please enter a value between 1 and " + str(i) 120 | except (EOFError, KeyboardInterrupt) as e: 121 | print "\nExiting..." 122 | exit() 123 | 124 | with open(cache_file_num, 'w') as f: 125 | f.write(str(num)) 126 | 127 | instance = all_instances[num - 1] 128 | dns = [instance['PublicDnsName'], instance['PrivateIpAddress']][options.ip] 129 | 130 | identity = '' 131 | if options.identity and os.path.exists(options.identity): 132 | identity = "-i %s " % options.identity 133 | 134 | print "\nConnecting to", extract_name(instance), dns 135 | os.system('ssh %s%s@%s' % (identity, options.user, dns)) 136 | --------------------------------------------------------------------------------