VS Code 自动化连接非固定IP地址EC2实例的解决方案
问题描述
大家可能和我一样,平时在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实例的解决方案的更多相关文章
- vmware虚拟机下linux centos6.6只有lo,没有eth0网卡、随机分配ip地址,固定ip地址等问题
这个问题卡了我一天多的时间,百度上搜出来的问题五花八门,反而把我给搞糊涂了.最后总算是实践成功了,记录一下配置的过程. 配置网卡和随机分配ip地址 我安装的是basic server版本,用的是NAT ...
- Neutron 理解(5):Neutron 是如何向 Nova 虚机分配固定IP地址的 (How Neutron Allocates Fixed IPs to Nova Instance)
学习 Neutron 系列文章: (1)Neutron 所实现的虚拟化网络 (2)Neutron OpenvSwitch + VLAN 虚拟网络 (3)Neutron OpenvSwitch + GR ...
- 初步学习大数据——设置虚拟机固定ip地址
1.打开本机的网络连接 2.右键以太网,打开属性. 3.右键VMnet8,打开属性.最多不能超过255,最少不能小于0. 0~255之间. 4.找到你要设置固定IP地址的虚拟机 ,选择上方的编辑 ...
- Windows 通过命令行设置固定ip地址
Winserver1709 之后 windows系统取消了GUI界面 设置ip地址 需要使用命令行界面进行 这里简单记录一下 打开win1709的虚拟机 进入命令行控制台 输入 ipconfig 查看 ...
- 如何设置电脑的固定IP地址
大家在上网时电脑的IP地址往往都是自动选择的,但在局域网内有时会方便共享文件和监控流量等操作时需要固定的IP地址.下面将简单介绍如何手设置电脑的固定IP地址. 百度经验:jingyan.baidu.c ...
- win10如何在局域网中设置一台电脑的固定ip地址
在工作和生活中,经常要遇到远程访问一台电脑的情况,但是在局域网中如果不进行设置,通常一台电脑的ip是自动生成的,,没有固定,这就导致下次访问这个地址时,不能正常访问,下面就交大家如何在win10系统中 ...
- VMware Workstation安装CentOs7固定ip地址
今天发现之前hypervisor配置的CentOs7连接不了了,该死的加密系统和杀毒软件又搞事情了,于是决定试下VMware虚拟机,下载安装后,发现可以连上CentOS7界面,很开心,于是决定把之前的 ...
- 在Linux虚拟机中添加多个固定ip地址
1.右键点击设置2.点击添加,再点击网络适配器,最后点击完成.3.选择完成后的网络适配器,选择仅主机模式.4.用roott身份登录,用nmtui进行设置 systemctl start Network ...
- docker固定IP地址重启不变
docker固定IP地址重启不变 代码地址 https://github.com/lioncui/docker-static-ip 宿主机IP为 10.6.17.12 docker IP为 10.6 ...
随机推荐
- Spring源码解析之BeanFactoryPostProcessor(二)
上一章,我们介绍了在AnnotationConfigApplicationContext初始化的时候,会创建AnnotatedBeanDefinitionReader和ClassPathBeanDef ...
- Android Studio下的简单网页解析
Android Studio下的简单网页解析 一.导入数据 导入前添加依赖 implementation 'org.jsoup:jsoup:1.11.3' 使用字符串导入 String html = ...
- 第7.14节 Python类中的实例方法详析
第7.14节 Python类中的实例方法详析 一. 实例方法的定义 在本章前面章节已经介绍了类的实例方法,实例方法的定义有三种方式: 1. 类体中定义实例方法 第一种方式很简单,就是在类体 ...
- C++编程指南(6-7)
六.函数设计 函数是C++/C程序的基本功能单元,其重要性不言而喻.函数设计的细微缺点很容易导致该函数被错用,所以光使函数的功能正确是不够的.本章重点论述函数的接口设计和内部实现的一些规则. 函数接口 ...
- jarvisoj babyphp
jarvisoj babyphp 涉及知识点: (1)GitHack处理.git源码泄露 (2)php代码注入 解析: 进入题目界面. 看到题目中的用了git那么第一反应肯定是可能存在.git源码泄露 ...
- XDown单文件版 下载工具 支持磁力等多种链接方式下载
原来的程序不带剪辑板探测,不支持迅雷链接等 增加功能后优化制作单文件版本. 下载类型为下图 magnet:?xt=urn:btih:836A228D932EF1C7EA1DD99D5D80B7CB0C ...
- buuctf-[网鼎杯 2018]Fakebook 1
这道题,也是费了很大的劲,慢慢理解慢慢消化,今天,才开始把wp写出来 首先我们先扫描一波目录,用dirsearch扫一手,发现有robots.txt文件 dirseach自带的字典在db目录下,使用格 ...
- 手把手教你写DI_0_DI是什么?
DI是什么? Dependency Injection 常常简称为:DI. 它是实现控制反转(Inversion of Control – IoC)的一个模式. fowler 大大大神 "几 ...
- 【笔记】「pj复习」深搜——拿部分分
说在最前面 众所周知, NOIP pj 的第三题大部分都是 dp ,但是有可能在考场上想不到动态转移方程,所以我们就可以拿深搜骗分. 方法 深搜拿部分分 剪枝 记忆化 看数据范围 有时候发现,写完深搜 ...
- 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 = ...