从Windows terminal里面的输出内容中截取trim IP 地址,再更新到.ssh/config文件里面

一、为什么要截取IP 地址(出发点)

bash 复制代码
PS C:\Users\yyy> & "D:\Program Files\google_cloude_cli\google-cloud-sdk\bin\gcloud.cmd" cloud-shell ssh
Automatic authentication with GCP CLI tools in Cloud Shell is disabled. To enable, please rerun command with --authorize-session flag.
Welcome to Cloud Shell! Type "help" to get started, or type "gemini" to try prompting with Gemini CLI.
Your Cloud Platform project in this session is set to vscode2gcloudshell.
Use gcloud config set project [PROJECT_ID] to change to a different project.
yyy@cloudshell:~ (vscode2gcloudshell)$ exit
logout
Connection to 34.10.33.28 closed

现在我能通过

bash 复制代码
& "D:\Program Files\google_cloude_cli\google-cloud-sdk\bin\gcloud.cmd" cloud-shell ssh

命令连接Google cloud shell,但是如果空闲20分钟,这个ip会变,我只能每次复制这个ip修改.ssh文件夹的config文件,然后我才能用vscode免配置(直接使用config里面的ssh host 信息)连接Google cloud shell进行开发,请问我怎么能在使用

bash 复制代码
& "D:\Program Files\google_cloude_cli\google-cloud-sdk\bin\gcloud.cmd" cloud-shell ssh

命令连接后,再输入exit,可以看到这个ip,然后自动把这个ip更新到.ssh文件下面的config文件呢

二、脚本实现

这是一个非常典型的痛点。

Google Cloud Shell 的 IP 是动态分配的,且闲置后会回收,导致本地 SSH 配置经常失效。

要实现"连接 -> 退出 -> 自动抓取 IP -> 更新 SSH Config",

最简单的办法是写一个 PowerShell 脚本 来封装这个流程。

目标自动化脚本会执行以下步骤:

  1. 打开 gcloud 连接(这会唤醒 Cloud Shell 实例)。
  2. 当你输入 exit 退出后,脚本自动获取当前活跃的连接信息。
  3. 使用正则表达式提取最新的 IP 地址。
  4. 自动替换 C:\Users\yyyy\.ssh\config 文件中的 IP。

解决方案:编写 PowerShell 自动化脚本

第一步:准备 SSH Config 文件

确保你的 C:\Users\yyyy\.ssh\config 文件中有一个专门用于 Google Cloud Shell 的 Host 配置,并且有一个占位符 IP。

文件内容示例:

ssh 复制代码
Host gcloud
    HostName 1.2.3.4
    User yyyy
    Port 6000
    IdentityFile ~/.ssh/google_compute_engine
    # 注意:HostName 这一行会被脚本自动修改,Host 的名字 "gcloud" 下面脚本要用到
第二步:创建脚本

在你的电脑上创建一个文件,例如 gcloud-connect.ps1,将以下代码复制进去:

powershell 复制代码
# 配置区域
$GcloudPath = "D:\Program Files\google_cloude_cli\google-cloud-sdk\bin\gcloud.cmd"
$SshConfigPath = "$env:USERPROFILE\.ssh\config"
$HostEntryName = "cloudshell" # Host 名称可以修改

# 1. 启动交互式连接
Write-Host "正在连接 Google Cloud Shell... (输入 exit 退出后将自动更新 IP)" -ForegroundColor Cyan
# 添加 --authorize-session 以解决报错中提到的认证警告
& $GcloudPath cloud-shell ssh --authorize-session

# 2. 连接结束后,获取最新的连接信息
Write-Host "`n连接已关闭,正在获取最新 IP 地址..." -ForegroundColor Yellow

# 使用 (| Out-String) 确保输出被视为单个字符串,而不是数组
$DryRunOutput = (& $GcloudPath cloud-shell ssh --dry-run 2>&1) | Out-String
# 数组 -match 正则:返回匹配的那一行内容,不填充 $matches。
# 字符串 -match 正则:返回 True/False,填充 $matches。
# Out-String 让PowerShell 把所有输出当作一个长字符串处理,会填充
# 强制将 gcloud 的输出转换为单个字符串对象,确保 -match 能正常工作并填充 $matches。
# 


# 3. 提取 IP 地址
# 匹配格式通常为 user@IP 或直接 IP,增加容错
if ($DryRunOutput -match '(\d{1,3}\.\d{1,3}\.\d{1,3}\.\d{1,3})') {
    $NewIP = $matches[1]
    
    # 确保提取到了有效的 IP
    if ([string]::IsNullOrWhiteSpace($NewIP)) {
        Write-Error "错误:提取到的 IP 为空,跳过更新配置文件。"
        exit
    }

    Write-Host "检测到新 IP: $NewIP" -ForegroundColor Green

    # 4. 更新 SSH Config 文件
    if (Test-Path $SshConfigPath) {
        $Content = Get-Content $SshConfigPath
        $InHostBlock = $false
        $Updated = $false
        
        $NewContent = $Content | ForEach-Object {
            $Line = $_
            # 检测是否进入了目标 Host 块
            if ($Line -match "^Host\s+$HostEntryName$") {
                $InHostBlock = $true
            } elseif ($Line -match "^Host\s+") {
                $InHostBlock = $false
            }

            # 如果在目标块内,且是 HostName 行,则替换
            # 正则放宽,匹配 HostName 后可能没有参数的情况(修复你当前被写坏的文件)
            # 这里的正则匹配能处理可能的端口号干扰。
            if ($InHostBlock -and $Line -match "^\s*HostName\b") {
                $Updated = $true
                "    HostName $NewIP" # 输出新行
            } else {
                $Line # 输出原行
            }
        }

        if ($Updated) {
            $NewContent | Set-Content $SshConfigPath
            Write-Host "成功更新 $SshConfigPath 中的 HostName!" -ForegroundColor Cyan
            Write-Host "现在你可以直接在 VS Code 中连接 '$HostEntryName' 了。" -ForegroundColor Green
        } else {
            Write-Error "未在 config 文件中找到 Host 为 '$HostEntryName' 的 HostName 字段。"
        }
    } else {
        Write-Error "找不到 SSH Config 文件: $SshConfigPath"
    }
} else {
    Write-Error "无法解析 IP 地址,请检查 gcloud 输出。"
    Write-Host "调试信息 (Gcloud Output):"
    Write-Host $DryRunOutput
}
第三步:如何使用
  1. 打开 PowerShell。
  2. 运行这个脚本:.\gcloud-connect.ps1
  3. 它会像往常一样进入 Cloud Shell。
  4. 此时Cloud Shell 虚拟机被激活了。
  5. 输入 exit 退出。
  6. 脚本会提示 检测到新 IP: 34.x.x.x 并提示 成功更新...
  7. 打开 VS Code,直接连接 SSH Host gcloud 即可。

三、英语注释版本

bash 复制代码
# Configuration Section
$GcloudPath = "D:\Program Files\google_cloude_cli\google-cloud-sdk\bin\gcloud.cmd"
$SshConfigPath = "$env:USERPROFILE\.ssh\config"
$HostEntryName = "cloudshell" # Note: Changed to 'cloudshell' based on your error logs

# 1. Start interactive connection
Write-Host "Connecting to Google Cloud Shell... (Type 'exit' to quit, and the IP will update automatically)" -ForegroundColor Cyan
# Added --authorize-session to fix the authentication warning seen in your logs
& $GcloudPath cloud-shell ssh --authorize-session

# 2. After connection closes, retrieve latest connection info
Write-Host "`nConnection closed. Retrieving the latest IP address..." -ForegroundColor Yellow

# [Fix 1] Use (| Out-String) to ensure output is treated as a single string, not an array.
# This prevents the "Cannot index into a null array" error.
$DryRunOutput = (& $GcloudPath cloud-shell ssh --dry-run 2>&1) | Out-String

# 3. Extract IP address
# Matches format like user@IP or just the IP directly
if ($DryRunOutput -match '(\d{1,3}\.\d{1,3}\.\d{1,3}\.\d{1,3})') {
    $NewIP = $matches[1]
    
    # [Fix 2] Ensure a valid IP was extracted before writing to file
    if ([string]::IsNullOrWhiteSpace($NewIP)) {
        Write-Error "Error: Extracted IP is empty. Skipping config update."
        exit
    }

    Write-Host "New IP detected: $NewIP" -ForegroundColor Green

    # 4. Update SSH Config file
    if (Test-Path $SshConfigPath) {
        $Content = Get-Content $SshConfigPath
        $InHostBlock = $false
        $Updated = $false
        
        $NewContent = $Content | ForEach-Object {
            $Line = $_
            # Check if we entered the target Host block
            if ($Line -match "^Host\s+$HostEntryName$") {
                $InHostBlock = $true
            } elseif ($Line -match "^Host\s+") {
                $InHostBlock = $false
            }

            # If inside the target block and it is a HostName line, replace it
            # [Fix 3] Relaxed regex to match HostName even if empty (fixes your currently broken config file)
            if ($InHostBlock -and $Line -match "^\s*HostName\b") {
                $Updated = $true
                "    HostName $NewIP" # Output new line
            } else {
                $Line # Output original line
            }
        }

        if ($Updated) {
            $NewContent | Set-Content $SshConfigPath
            Write-Host "Successfully updated HostName in $SshConfigPath!" -ForegroundColor Cyan
            Write-Host "You can now connect to '$HostEntryName' directly in VS Code." -ForegroundColor Green
        } else {
            Write-Error "HostName field for Host '$HostEntryName' not found in the config file."
        }
    } else {
        Write-Error "SSH Config file not found: $SshConfigPath"
    }
} else {
    Write-Error "Unable to parse IP address. Please check gcloud output."
    Write-Host "Debug Info (Gcloud Output):"
    Write-Host $DryRunOutput
}
相关推荐
MrSYJ1 小时前
TCP协议理解
后端·tcp/ip
Web3探索者4 天前
可视化服务器管理和传统命令行区别是什么?新手教程:Linux 运维到底该用图形界面还是 SSH 命令行?
linux·ssh
开发者联盟league11 天前
安装pnpm
ssh
qq_3692243311 天前
Windows全系通用!ntdll.dll文件丢失、报错、闪退问题的完整排查与修复教程
windows·dll·dll修复·dll丢失·dll错误
treesforest11 天前
AI安全系统如何识别异常访问?IP风险识别正在成为关键能力
网络·人工智能·tcp/ip·安全·web安全
2601_9618752411 天前
决战申论100题2026|最新|范文
linux·容器·centos·debian·ssh·fabric·vagrant
阿米亚波11 天前
【Windows】QEMU 启动 openEuler aarch64/arm64 架构系统 + 离线软件源
linux·windows·经验分享·笔记·架构·arm
江华森11 天前
TCP/IP 协议栈实战 — 7 个实验详解
网络·tcp/ip·智能路由器
酉鬼女又兒11 天前
零基础入门计算机网络运输层:端到端通信核心作用、端口号分类规则、复用分用工作机制及UDP与TCP协议全方位对比详解
网络·网络协议·tcp/ip·计算机网络·考研·udp·php
dog25011 天前
不要再继续优化 TCP
网络协议·tcp/ip·php