ICode9

精准搜索请尝试: 精确搜索
首页 > 其他分享> 文章详细

VS Code 自动化连接非固定IP地址EC2实例的解决方案

2020-12-02 14:34:06  阅读:160  来源: 互联网

标签:do Code NAME -- VS EC2 ssh name


问题描述

大家可能和我一样,平时在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 adds-in

标签:do,Code,NAME,--,VS,EC2,ssh,name
来源: https://www.cnblogs.com/neo-bingliang/p/14073634.html

本站声明: 1. iCode9 技术分享网(下文简称本站)提供的所有内容,仅供技术学习、探讨和分享;
2. 关于本站的所有留言、评论、转载及引用,纯属内容发起人的个人观点,与本站观点和立场无关;
3. 关于本站的所有言论和文字,纯属内容发起人的个人观点,与本站观点和立场无关;
4. 本站文章均是网友提供,不完全保证技术分享内容的完整性、准确性、时效性、风险性和版权归属;如您发现该文章侵犯了您的权益,可联系我们第一时间进行删除;
5. 本站为非盈利性的个人网站,所有内容不会用来进行牟利,也不会利用任何形式的广告来间接获益,纯粹是为了广大技术爱好者提供技术内容和技术思想的分享性交流网站。

专注分享技术,共同学习,共同进步。侵权联系[81616952@qq.com]

Copyright (C)ICode9.com, All Rights Reserved.

ICode9版权所有