Skip to content

Instantly share code, notes, and snippets.

@mo-ya
Forked from migrs/ec2-ssh
Last active February 14, 2017 23:58
Show Gist options
  • Save mo-ya/5788098 to your computer and use it in GitHub Desktop.
Save mo-ya/5788098 to your computer and use it in GitHub Desktop.
#!/bin/sh
## EC2 automation login tool
#
# Original: http://m.igrs.jp/blog/2013/03/14/ec2-ssh/
# https://gist.github.com/migrs/5157665
# https://gist.github.com/MichinobuMaeda/5545875
#
# Changed by mo-ya (2013-07-06)
#
# - SSH Timeout value can be set by $EC2_SSH_TIMEOUT
# - Default mode is changed to quit. Verbose on/off is switched by $EC2_SSH_VERBOSE
# - If a cache file is not found, the file is created automatically
# - Valid duration of Cache is controlled by $EC2_SSH_CACHE_DAY (default: 1 day)
#
# Changed by mo-ya (2013-06-15)
#
# - Use Cache file
# - Public DNS, Elastic IP Information is stored in a cache file.
# The next access is performed without ec2-api-tools query.
# If the access is failed, Public DNS and Elastic IP are queried by ec2-api-tools,
# and caches are updated.
# - If $1 is undefined, help messages and cache contents are output
# - Verbose Mode is added (controlled by $ec2_ssh_verbose)
#
# Changed by mo-ya (2013-05-20)
#
# - Default user can be set as $EC2_SSH_DEFAULT_USER
# - Default ssh key path can be set as $EC2_SSH_KEY_PATH
# - Some verbose messages are output to STDERR
#
## Settings
set -e
ssh="ssh"
ssh_timeout="2"
ec2din="ec2-describe-instances"
ec2_ssh_host_cache_set="${HOME}/.ec2-ssh.hostcache"
verbose=
cache_day=1
## Post Settings
if [ -n "$EC2_SSH_TIMEOUT" ]; then
ssh_timeout="${EC2_SSH_TIMEOUT}"
fi
ec2_ssh_opt="-o ConnectTimeout=${ssh_timeout}"
if [ -n "$EC2_SSH_KEY_PATH" ]; then
ec2_ssh_opt="${ec2_ssh_opt} -i ${EC2_SSH_KEY_PATH}"
fi
if [ -n "$EC2_SSH_DEFAULT_USER" ]; then
ec2_ssh_user="${EC2_SSH_DEFAULT_USER}@"
fi
if [ -n "$EC2_SSH_CACHE_DAY" ]; then
cache_day="${EC2_SSH_CACHE_DAY}"
fi
if [ -n "$EC2_SSH_VERBOSE" ]; then
verbose="${EC2_SSH_VERBOSE}"
fi
## Functions
vmsg(){
if [ -n "${verbose}" ]; then
echo "$*" >&2
fi
}
msg(){
echo "$*" >&2
}
## Output Help Messages (If any arguments are not found)
if [ $# -lt 1 ]; then
cat <<END_OF_HELP
# [ec2-ssh] Usages
Basic Usage
$ ec2-ssh web1
$ ec2-ssh jonny@web1
Access Same Name Instances (#1, #2 ...)
$ ec2-ssh web#3
Port Fowarding
$ ec2-ssh -L 8080:127.0.0.1:80 web1
Command direct execution
$ ec2-ssh web1 ls -la
$ ec2-ssh web1 tail -f /var/log/nginx/access.log
$ ec2-ssh web1 vmstat 1
$ ec2-ssh web1 -t top
$ ec2-ssh web1 -t sudo service nginx restart
END_OF_HELP
if [ -f "${ec2_ssh_host_cache_set}" ]; then
cat <<END_OF_CACHE
# [ec2-ssh] Cache Lists (in "${ec2_ssh_host_cache_set}")
END_OF_CACHE
cat ${ec2_ssh_host_cache_set}
fi
exit 1
fi
## Display ENVs
if [ -n "$EC2_SSH_HOST_CACHE" ]; then
ec2_ssh_host_cache_set="$EC2_SSH_HOST_CACHE"
fi
vmsg "[ENV]"
vmsg " EC2_SSH_KEY_PATH = $EC2_SSH_KEY_PATH"
vmsg " EC2_SSH_DEFAULT_USER = $EC2_SSH_DEFAULT_USER"
vmsg " EC2_SSH_HOST_CACHE = $ec2_ssh_host_cache_set"
vmsg " EC2_SSH_TIMEOUT = $ssh_timeout"
vmsg " EC2_SSH_CACHE_DAY = $cache_day"
vmsg " EC2_SSH_VERBOSE = $verbose"
## Parse Command line options (host name & number informations)
while [ $# -gt 0 ]; do
case $1 in
-*)
if [ -z "$2" ]; then
break
elif [ "${2:0:1}" == "-" ]; then
args="$args $1"
shift
else
args="$args $1 $2"
shift 2
fi
;;
*)
if [ -n "$1" -a -z "$name" ]; then
name=$1
shift
fi
break
esac
done
if [ "$name" != "${name%\#*}" ]; then
num=${name#*\#}
name=${name%\#*}
fi
[ -z "$num" ] && num=1
if [ "$name" != "${name%@*}" ]; then
user=${name%@*}
name=${name#*@}
fi
## Load EC2 Information from Local Cache
cache_hit=
msg "[Load EC2 Information from Local Cache] ... "
if [ -f "${ec2_ssh_host_cache_set}" ]; then
host=`grep "^${name}#${num}" ${ec2_ssh_host_cache_set} | cut -f2`
reg_date=`grep "^${name}#${num}" ${ec2_ssh_host_cache_set} | cut -f3`
set +e
# for GNU date
valid_date=`date --date "${cache_day} day ago" "+%Y%m%d%H%M%S" 2>/dev/null`
if [ -z "${valid_date}" ]; then
# for BSD date
valid_date=`date -v-${cache_day}d "+%Y%m%d%H%M%S" 2>/dev/null`
fi
set -e
if [ -n "$host" ]; then
cache_old=
if [ -n "${reg_date}" ] && [ -n "${valid_date}" ];then
if [ "${reg_date}" -lt "${valid_date}" ];then
cache_old=1
fi
else
vmsg " WARNING: reg_date or valid_date is not found"
vmsg " reg_date = $reg_date"
vmsg " valid_date = $valid_date"
fi
if [ -z "${cache_old}" ]; then
cache_hit=1
msg " Cache HIT: $name => $host"
else
msg " Cache OLD: older than ${cache_day} day [${reg_date}]: $name => $host"
host=
fi
else
msg " Cache NOT FOUND: host is not found in Caches"
fi
else
msg " Cache file is not found."
fi
yet_connect=1
while [ -n "${yet_connect}" ]; do
## Get EC2 Information from AWS
if [ -z "$host" ]; then
msg "[Get EC2 Information from AWS] ... (wait a minutes)"
q="-F \"tag:Name=$name\""
host=`$ec2din $q --hide-tags | grep ^INSTANCE | cut -f4 | paste -s - | cut -f$num`
if [ -n "$host" ]; then
vmsg "[Target] $host"
else
msg "ec2-ssh: Could not find ec2 instance $name [$num]"
exit 1
fi
fi
## Save host information to cache
if [ -z "$cache_hit" ] ; then
if [ ! -f "${ec2_ssh_host_cache_set}" ]; then
touch ${ec2_ssh_host_cache_set}
fi
vmsg "[Save EC2 Information to Local Cache] ... "
cat ${ec2_ssh_host_cache_set} | grep -v "^${name}#${num}" > ${ec2_ssh_host_cache_set}.$$ | true
cat ${ec2_ssh_host_cache_set}.$$ > ${ec2_ssh_host_cache_set}
rm ${ec2_ssh_host_cache_set}.$$
reg_date=`date "+%Y%m%d%H%M%S"`
echo "${name}#${num} ${host} ${reg_date}" >> ${ec2_ssh_host_cache_set}
vmsg " Cache is updated."
fi
## Access the server
if [ -n "$user" ]; then
ssh_user_set="${user}@"
else
ssh_user_set="${ec2_ssh_user}"
fi
msg "[Connecting EC2] ..."
vmsg $ssh $ec2_ssh_opt $args ${ssh_user_set}$host $@
set +e
$ssh $ec2_ssh_opt $args ${ssh_user_set}$host $@
ssh_stat=$?
set -e
if [ "$ssh_stat" = 0 ]; then
yet_connect=
else
if [ -z "$cache_hit" ]; then
msg "ERROR: Cannot Connect to [Name=$name, PublicDNS=$host]"
msg " Please Check Server Settings."
exit 1
else
msg "WARNING: Cache Info may be obsoleted. Cache is ignored."
host=
cache_hit=
fi
fi
done
@mo-ya
Copy link
Author

mo-ya commented Jun 15, 2013

Public DNS, Elastic IP 情報をキャッシュファイルに保存しておいて、次回のアクセス時は ec2-api-tools による AWS への問い合わせをせずにすぐに EC2 にアクセスするようにしてみました。アクセスに失敗した場合は問い合わせし直してキャッシュを更新します。動作確認してるのは今のところ Mac OS 10.8.3 のみ。あとは個人的趣味なメッセージ出力系の変更。以下、変更内容詳細。

  • Use Cache file
    • Public DNS, Elastic IP Information is stored in a cache file.
      The next access is performed without ec2-api-tools query.
      If the access is failed, Public DNS and Elastic IP are queried by ec2-api-tools,
      and caches are updated.
  • If $1 is undefined, help messages and cache contents are output
  • Verbose Mode is added (controlled by $ec2_ssh_verbose)
  • Default user can be set as $EC2_SSH_DEFAULT_USER
  • Default ssh key path can be set as $EC2_SSH_KEY_PATH
  • Some verbose messages are output to STDERR

@mo-ya
Copy link
Author

mo-ya commented Jul 9, 2013

CentOS 6.4 でも動作することを確認しています。

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment