从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
}
相关推荐
leo_2322 小时前
IP--SMP(软件制作平台)语言基础知识之六十四
服务器·开发语言·tcp/ip·企业信息化·smp(软件制作平台)·应用系统·eom(企业经营模型)
说私域2 小时前
技术赋能直播运营:开源AI智能名片商城小程序助力个人IP构建与高效运营
人工智能·tcp/ip·小程序·流量运营·私域运营
czhc11400756633 小时前
通信217
服务器·网络·tcp/ip
郝学胜-神的一滴5 小时前
深入理解TCP连接的优雅关闭:半关闭状态与四次挥手的艺术
linux·服务器·开发语言·网络·tcp/ip·程序人生
fjh199713 小时前
记一次奇怪的ssh公钥登录失败的情况
运维·ssh
yaoxin52112316 小时前
324. Java Stream API - 实现 Collector 接口:自定义你的流式收集器
java·windows·python
非凡ghost17 小时前
小X分身APP(手机分身类工具)
android·windows·学习·智能手机·软件需求
Bruce_Liuxiaowei18 小时前
渗透测试中的提权漏洞:从低权限到系统控制的全解析
网络·windows·安全
kaizq19 小时前
Windows下基于Python构造Dify可视应用环境[非Dock]
windows·python·dify·大语言模型llm·人工智能ai·智能体agent