从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
}
相关推荐
水饺编程1 小时前
第5章,[Win32 章节] :Polygon 函数和多边形填充模式
c语言·c++·windows·visual studio
梓沂1 小时前
SSH 公钥认证配置指南:从生成密钥到配置 SFTP 服务器
ssh
百事牛科技1 小时前
文档不想再加密了?Word打开密码移除的两种方法
windows·word
软件资深者4 小时前
千千静听典藏修复版 使用教程:经典本地音乐播放器回归,歌词同步、皮肤皮肤自由换,音乐播放器怀旧新手 5 分钟上手(2026)
windows
牛油果子哥q4 小时前
C++ Socket精讲:TCP/UDP套接字、客户端服务端实现、字节序、粘包拆包、简单HTTP服务、网络踩坑与面试全解
网络·c++·tcp/ip
captain3764 小时前
文件与IO(2)
java·开发语言·windows·java-ee
A hao4 小时前
户外LED广告牌需要什么防护等级IP级别?
大数据·网络·图像处理·人工智能·网络协议·tcp/ip·广告
zhougl9966 小时前
Netcat完整教程
tcp/ip
星栖与芯6 小时前
# STM32MP157+LiteOS-M GCC极简工程:启动源码适配+Windows Make终极避坑
windows·stm32·单片机
工业一体机老司机6 小时前
Python实现工业一体机Modbus-TCP通信-从协议解析到多设备轮询实战
开发语言·python·tcp/ip