问题描述

大家可能和我一样,平时在AWS上启动一台安装有Linux EC2实例作为远程开发机。

(注:这里的EC2实例是配置用私钥进行登录的)

通常,你可以选择申请一个Elastic IP绑定到这台开发机上,同时,在本地配置好ssh config的配置文件

  • windows: C:\Users{yourname}.ssh\config
  • Mac\Linux: /home/{yourname}/.ssh/config

节点配置:

Host workstation
HostName {elastic_ip_address}
User ec2-user
Port 22
IdentityFile C:\Users\{yourname}\.ssh\{private_key_name}.pem

然后打开各种终端输入ssh命令,远程连接到EC2 Linux实例

(windows上安装GIT后,就可以使用ssh命令了; Mac\Linux的终端自带ssh命令)

ssh workstation

一般性,不工作的时候,会关闭EC2节省开支。但大家有没有注意到,Elastic IP在没有绑定到EC2实例的空置期是要付费的,虽然付费不多,一个月20多人民币左右,但蚊子肉也是肉啊!哈哈。

妥协的方案是:不绑定Elastic IP, 每次启动完EC2实例后,到AWS Console查看IP地址,接着手动修改ssh config文件,然后用ssh命令连接。

我开始的确就是这么做的,但每天都要来一次,很不爽!秉着Don't repeat yourself 的做事原则,决定自动化整个过程。

思路和解决方案

大体思路是这样的:

  • 用awscli启动远程EC2实例
  • 获取动态IP地址
  • 将IP地址设置到ssh config文件中

封装了一个启动、停止、获取IP 的EC2实例脚本, 保存为 ec2.sh

COMMAND=$1
EC2_NAME=$2 function start() {
local INSTANCE_ID=$1
local EC2_NAME=$2
echo "starting ${EC2_NAME}"
local EC2_STATUS=$(status ${INSTANCE_ID})
if [[ ${EC2_STATUS} != "running" ]]; then
aws ec2 start-instances --instance-ids ${INSTANCE_ID}
aws ec2 wait instance-running --instance-ids ${INSTANCE_ID}
fi echo "${EC2_NAME} has started"
} function stop() {
local INSTANCE_ID=$1
echo "stopping ${EC2_NAME}"
aws ec2 stop-instances --instance-ids ${INSTANCE_ID}
aws ec2 wait instance-stopped --instance-ids ${INSTANCE_ID}
echo "${EC2_NAME} has stopped"
} function status() {
echo $(aws ec2 describe-instances \
--filters "Name=tag:Name,Values=${EC2_NAME}" \
--query 'Reservations[*].Instances[*].[State.Name]' \
--output text)
} function getInstanceId() {
local EC2_NAME=$1
INSTANCE_ID=$(aws ec2 describe-instances \
--filters "Name=tag:Name,Values=${EC2_NAME}" \
--query 'Reservations[*].Instances[*].[InstanceId]' \
--output text)
echo ${INSTANCE_ID}
} function restart() {
local INSTANCE_ID=$1
local EC2_NAME=$2
local EC2_STATUS=$(status ${INSTANCE_ID})
if [[ ${EC2_STATUS} = "running" ]]; then
stop ${INSTANCE_ID}
fi start ${INSTANCE_ID} ${EC2_NAME}
} function ipAddress() {
local EC2_NAME=$1
ipAddress=$(aws ec2 describe-instances \
--filters "Name=tag:Name,Values=${EC2_NAME}" \
--query Reservations[*].Instances[*].[PublicIpAddress] \
--output text)
echo ${ipAddress}
} INSTANCE_ID=$(getInstanceId ${EC2_NAME}) case ${COMMAND} in
start)
start ${INSTANCE_ID} ${EC2_NAME}
;;
stop)
stop ${INSTANCE_ID}
;;
status)
status ${EC2_NAME}
;;
restart)
restart ${INSTANCE_ID} ${EC2_NAME}
;;
ipAddress)
ipAddress ${EC2_NAME}
;;
*)
echo "wrong command, current supported commands: start, stop, status, restart"
;;
esac

在Github上找到一个开源项目,可以方便操作ssh config文件,做了轻微修改,用来适配windows的Git Bash,保存为sshconfig

#!/bin/bash
# Copyright (C) 2015 Arash Shams <xsysxpert@gmail.com>.
#
# This program is free software: you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
# the Free Software Foundation, either version 3 of the License, or
# (at your option) any later version.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with this program. If not, see <http://www.gnu.org/licenses/>.
CONFIGFILE="$HOME/.ssh/config"
TEMPFILE="$HOME/.ssh/.ssctemp" if [ ! -f $CONFIGFILE ]; then
mkdir -p $HOME/.ssh && touch $CONFIGFILE
fi is_integer() {
printf "%d" $1 > /dev/null 2>&1
return $?
} do_check_names() {
grep "^Host" $CONFIGFILE | cut -f2- -d " "
exit 0
} success() {
printf "\n \033[32mSuccess: %s\033[0m\n\n" "$@"
# exit 0
} error() {
printf "\n \033[31mError: %s\033[0m\n\n" "$@"
exit 1
} print() {
printf " \033[36m%10s\033[0m : \033[90m%s\033[0m\n" "$1" "$2"
} do_add_process() {
if [[ "$#" -eq 6 || "$#" -eq 4 ]]; then
name=$2
username=$3
hostname=$4
if [[ -n $6 ]]; then
id=$5
port=$6
else
port=22
fi
elif [[ "$#" -eq 5 ]]; then
if is_integer $5; then
name=$2
username=$3
hostname=$4
port=$5 else
name=$2
username=$3
hostname=$4
id=$5
port=22
fi
else
error "ssc $1 NAME USERNAME HOSTNAME [IdentityKey] [PORT]"
fi if [[ $(do_check_names | grep --count "^$name$") != 0 ]]; then
error "This name is already used. Try again with another name."
fi if [ -n "$id" ]; then
cat << EOB >> $CONFIGFILE Host $name
HostName $hostname
User $username
Port $port
IdentityFile $id
EOB
else
cat << EOB >> $CONFIGFILE Host $name
HostName $hostname
User $username
Port $port
EOB
fi
success "\"$name\" added successfuly to host list"
} do_remove_process() {
if [ "$#" != 2 ]; then
error "Usage : ssc $1 NAME"
fi
name=$2
if [[ $(do_check_names | grep --count "^$name$") != 0 ]]; then
sed -ie "/^Host $name$/,/^$/d" $CONFIGFILE
success "\"$name\" Removed successfully"
# exit 0
else
error "Sorry, \"$name\" is not in list"
fi
} do_list_process() {
if [ -n "$2" ]; then
name=$2
if [[ $(do_check_names | grep --count "^$name$") != 0 ]]; then
awk -v name="$name" -v green="\033[0;32m" -v reset="\033[0m" -v RS='' 'index($0, name) { for (i = 1; i < NF; i += 2) { printf("%s%s%s: %s%s", green, $i, reset, $(i + 1), (i < NF -2)? " ": "\n") } exit }' $CONFIGFILE
exit 0
else
error "Sorry, \"$name\" is not in list"
fi
else
awk -v name="$name" -v green="\033[0;32m" -v reset="\033[0m" -v RS='' '{ for (i = 1; i < NF; i += 2) { printf("%s%s%s: %s\t%s", green, $i, reset, $(i + 1), (i < NF -2)? " ": "\n") } }' $CONFIGFILE | column -t
fi
} do_connect() {
name=$1
if [[ $(do_check_names | grep --count "^$name$") != 0 ]]; then
ssh $1
exit 0
fi
} do_search_process() {
name=$2
ssc ls | grep $name
} do_edit_process() {
name=$2
if [[ $(do_check_names | grep --count "^$name$") != 0 ]]; then
echo "Now, Enter new values ($(ssc | grep -i add | awk -F"-a" '{print $2}'))"
read new_name user host identity port
do_remove_process remove $name 1>/dev/null
do_add_process add $new_name $user $host $identity $port 1>/dev/null
success "\"${name}\" successfully edited."
else
error "Sorry, \"$name\" is not in list"
fi
} do_show_usage() {
print "Add" "ssc add/-a NAME USERNAME HOSTNAME [IdentityKey] [PORT] "
print "Edit" "ssc edit/-e NAME"
print "Remove" "ssc remove/-r/rm NAME"
print "List" "ssc list/-l/ls [NAME]"
print "Search" "ssc search/-s NAME"
print "Version" "ssc version/-v"
print "Help" "ssc help/-h"
} do_show_version() {
print "Version" "Version 1.8 Stable"
print "Contribute" "Fork me at Github <https://github.com/Ara4Sh/sshconfig>"
} action=$1
case $action in
add | -a)
do_add_process $@
;;
remove | -r | rm)
do_remove_process $@
;;
list | -l | ls)
do_list_process $@
;;
search | -s)
do_search_process $@
;;
version | -v)
do_show_version
;;
edit | -e)
do_edit_process $@
;;
help | -h)
do_show_usage
;;
*)
do_connect $@
do_show_usage
echo ""
do_show_version
;;
esac exit 0

剩下的事情就比较简单了,将以上两个文件拷贝到你的工作目录下,然后写脚本调用:

sh ec2.sh start workstation
ipAddress=$(sh ec2.sh ipAddress workstation)
echo "start to config .ssh/config"
sh sshconfig remove workstation
sh sshconfig add workstation ec2-user ${ipAddress} "C:\\Users\\{yourname}\\.ssh\\{private_key_name}.pem"
echo "done"

VS Code插件

以上脚本在Windows的Git Bash和Mac测试通过,在这里介绍几个好用的插件

  • VS code切换终端的类型

    这个插件,可以让你快速打开不同的类型的终端,例如windows上的cmd, PowerShell, Git Bash
  • 远程连接Linux

    方便连接远程Linux,打开一个文件夹,像编辑本地文件一下编辑远程文件

VS Code 自动化连接非固定IP地址EC2实例的解决方案的更多相关文章

  1. vmware虚拟机下linux centos6.6只有lo,没有eth0网卡、随机分配ip地址,固定ip地址等问题

    这个问题卡了我一天多的时间,百度上搜出来的问题五花八门,反而把我给搞糊涂了.最后总算是实践成功了,记录一下配置的过程. 配置网卡和随机分配ip地址 我安装的是basic server版本,用的是NAT ...

  2. Neutron 理解(5):Neutron 是如何向 Nova 虚机分配固定IP地址的 (How Neutron Allocates Fixed IPs to Nova Instance)

    学习 Neutron 系列文章: (1)Neutron 所实现的虚拟化网络 (2)Neutron OpenvSwitch + VLAN 虚拟网络 (3)Neutron OpenvSwitch + GR ...

  3. 初步学习大数据——设置虚拟机固定ip地址

    1.打开本机的网络连接 2.右键以太网,打开属性. 3.右键VMnet8,打开属性.最多不能超过255,最少不能小于0.    0~255之间. 4.找到你要设置固定IP地址的虚拟机 ,选择上方的编辑 ...

  4. Windows 通过命令行设置固定ip地址

    Winserver1709 之后 windows系统取消了GUI界面 设置ip地址 需要使用命令行界面进行 这里简单记录一下 打开win1709的虚拟机 进入命令行控制台 输入 ipconfig 查看 ...

  5. 如何设置电脑的固定IP地址

    大家在上网时电脑的IP地址往往都是自动选择的,但在局域网内有时会方便共享文件和监控流量等操作时需要固定的IP地址.下面将简单介绍如何手设置电脑的固定IP地址. 百度经验:jingyan.baidu.c ...

  6. win10如何在局域网中设置一台电脑的固定ip地址

    在工作和生活中,经常要遇到远程访问一台电脑的情况,但是在局域网中如果不进行设置,通常一台电脑的ip是自动生成的,,没有固定,这就导致下次访问这个地址时,不能正常访问,下面就交大家如何在win10系统中 ...

  7. VMware Workstation安装CentOs7固定ip地址

    今天发现之前hypervisor配置的CentOs7连接不了了,该死的加密系统和杀毒软件又搞事情了,于是决定试下VMware虚拟机,下载安装后,发现可以连上CentOS7界面,很开心,于是决定把之前的 ...

  8. 在Linux虚拟机中添加多个固定ip地址

    1.右键点击设置2.点击添加,再点击网络适配器,最后点击完成.3.选择完成后的网络适配器,选择仅主机模式.4.用roott身份登录,用nmtui进行设置 systemctl start Network ...

  9. docker固定IP地址重启不变

    docker固定IP地址重启不变 代码地址 https://github.com/lioncui/docker-static-ip 宿主机IP为  10.6.17.12 docker IP为 10.6 ...

随机推荐

  1. Spring源码解析之BeanFactoryPostProcessor(二)

    上一章,我们介绍了在AnnotationConfigApplicationContext初始化的时候,会创建AnnotatedBeanDefinitionReader和ClassPathBeanDef ...

  2. Android Studio下的简单网页解析

    Android Studio下的简单网页解析 一.导入数据 导入前添加依赖 implementation 'org.jsoup:jsoup:1.11.3' 使用字符串导入 String html = ...

  3. 第7.14节 Python类中的实例方法详析

    第7.14节 Python类中的实例方法详析 一.    实例方法的定义 在本章前面章节已经介绍了类的实例方法,实例方法的定义有三种方式: 1.    类体中定义实例方法 第一种方式很简单,就是在类体 ...

  4. C++编程指南(6-7)

    六.函数设计 函数是C++/C程序的基本功能单元,其重要性不言而喻.函数设计的细微缺点很容易导致该函数被错用,所以光使函数的功能正确是不够的.本章重点论述函数的接口设计和内部实现的一些规则. 函数接口 ...

  5. jarvisoj babyphp

    jarvisoj babyphp 涉及知识点: (1)GitHack处理.git源码泄露 (2)php代码注入 解析: 进入题目界面. 看到题目中的用了git那么第一反应肯定是可能存在.git源码泄露 ...

  6. XDown单文件版 下载工具 支持磁力等多种链接方式下载

    原来的程序不带剪辑板探测,不支持迅雷链接等 增加功能后优化制作单文件版本. 下载类型为下图 magnet:?xt=urn:btih:836A228D932EF1C7EA1DD99D5D80B7CB0C ...

  7. buuctf-[网鼎杯 2018]Fakebook 1

    这道题,也是费了很大的劲,慢慢理解慢慢消化,今天,才开始把wp写出来 首先我们先扫描一波目录,用dirsearch扫一手,发现有robots.txt文件 dirseach自带的字典在db目录下,使用格 ...

  8. 手把手教你写DI_0_DI是什么?

    DI是什么? Dependency Injection 常常简称为:DI. 它是实现控制反转(Inversion of Control – IoC)的一个模式. fowler 大大大神 "几 ...

  9. 【笔记】「pj复习」深搜——拿部分分

    说在最前面 众所周知, NOIP pj 的第三题大部分都是 dp ,但是有可能在考场上想不到动态转移方程,所以我们就可以拿深搜骗分. 方法 深搜拿部分分 剪枝 记忆化 看数据范围 有时候发现,写完深搜 ...

  10. Social Infrastructure Information Systems Division, Hitachi Programming Contest 2020 D题题解

    将题意转换为一开始\(t = 0\),第\(i\)个操作是令\(t \leftarrow (a_i + 1) t + (a_i + b_i + 1)\).记\(A_i = a_i + 1, B_i = ...