VScode SSH 免密连接 一键脚本

VScode SSH 免密连接 一键脚本

前言

使用VScode的SSH插件连接一个新的服务器时,由于VScode不支持保存密码,所以一般的免密操作步骤如下:
1)生成一对密钥
2)把公钥拷贝到服务器(Linux)的authorized_keys
3)在主机(Windows)的.ssh/config 中设置 IdentityFile 后面接私钥绝对路径
上述步骤每次全部来一遍也是很繁琐的,完全可以整合一个脚本,然后一键式傻瓜操作。

一键配置VScode SSH免密连接脚本

@echo off setlocalset"SELF=%~f0"powershell.exe-NoProfile-ExecutionPolicyBypass-EncodedCommandJABwAD0AJABlAG4AdgA6AFMARQBMAEYAOwAgACQAbABpAG4AZQBzAD0ARwBlAHQALQBDAG8AbgB0AGUAbgB0ACAALQBMAGkAdABlAHIAYQBsAFAAYQB0AGgAIAAkAHAAIAAtAEUAbgBjAG8AZABpAG4AZwAgAEQAZQBmAGEAdQBsAHQAOwAgACQAbQBhAHIAawA9AFsAQQByAHIAYQB5AF0AOgA6AEkAbgBkAGUAeABPAGYAKAAkAGwAaQBuAGUAcwAsACcAIwAgAFAATwBXAEUAUgBTAEgARQBMAEwAJwApADsAIABpAGYAKAAkAG0AYQByAGsAIAAtAGwAdAAgADAAKQB7AHQAaAByAG8AdwAgACcAQgBBAFQAIABmAGkAbABlACAAaQBzACAAYgByAG8AawBlAG4ALgAnAH0AOwAgACQAYwBvAGQAZQA9ACQAbABpAG4AZQBzAFsAKAAkAG0AYQByAGsAKwAxACkALgAuACgAJABsAGkAbgBlAHMALgBMAGUAbgBnAHQAaAAtADEAKQBdACAALQBqAG8AaQBuACAAWwBFAG4AdgBpAHIAbwBuAG0AZQBuAHQAXQA6ADoATgBlAHcATABpAG4AZQA7ACAASQBuAHYAbwBrAGUALQBFAHgAcAByAGUAcwBzAGkAbwBuACAAJABjAG8AZABlAA==echo. pauseexit/b# POWERSHELL$ErrorActionPreference='Stop'functionAsk($text,$default=''){if($default){$v=Read-Host"$text[$default]"if([string]::IsNullOrWhiteSpace($v)){return$default}return$v.Trim()}do{$v=Read-Host$text}while([string]::IsNullOrWhiteSpace($v))return$v.Trim()}functionHas-HostConfig($configText,$hostValue){if([string]::IsNullOrWhiteSpace($configText)){return$false}$pattern="(?m)^\s*Host\s+$([regex]::Escape($hostValue))\s*$"return[regex]::IsMatch($configText,$pattern)}functionTest-HostValue($hostValue){if($hostValue-match'^\d+$'){throw"Invalid IP or host:$hostValue"}if($hostValue-match'^[\d.]+$'){$addr=$nullif(-not[Net.IPAddress]::TryParse($hostValue,[ref]$addr)){throw"Invalid IP:$hostValue"}}}functionSet-HostConfigBlock($configPath,$hostValue,$configBlock){$lines=@(Get-Content-LiteralPath$configPath-ErrorActionSilentlyContinue)$hostPattern="^\s*Host\s+$([regex]::Escape($hostValue))\s*$"$start=-1for($i=0;$i-lt$lines.Count;$i++){if($lines[$i]-match$hostPattern){$start=$ibreak}}if($start-lt0){Add-Content-LiteralPath$configPath-Value$configBlock-EncodingASCIIreturn}$end=$lines.Countfor($i=$start+1;$i-lt$lines.Count;$i++){if($lines[$i]-match'^\s*Host\s+\S+'){$end=$ibreak}}$newLines=@()if($start-gt0){$newLines+=$lines[0..($start-1)]}$newLines+=($configBlock-split"\r?\n")if($end-lt$lines.Count){$newLines+=$lines[$end..($lines.Count -1)]}Set-Content-LiteralPath$configPath-Value$newLines-EncodingASCII}try{$ip=Ask'IP'Test-HostValue$ip$user=Ask'User'$port=[int](Ask'Port''22')$keyName=Ask'Key name''id_rsa'if($keyName-match'[\\/]'-or$keyName-in'.','..'){throw'Key name must be a file name, not a path.'}$hostAlias=Ask'Host alias''my-server'$sshDir=Join-Path$HOME'.ssh'$key=Join-Path$sshDir$keyName$pub="$key.pub"if(!(Test-Path$sshDir)){New-Item-ItemTypeDirectory-Path$sshDir|Out-Null}$config=Join-Path$sshDir'config'$identityFile=($key-replace'\\','/')$configBlock=@" Host$hostAliasHostName$ipUser$userPort$portIdentityFile$identityFileIdentitiesOnly yes HostKeyAlgorithms +ssh-rsa,ssh-dss PubkeyAcceptedKeyTypes +ssh-rsa,ssh-dss PubkeyAcceptedAlgorithms +ssh-rsa,ssh-dss "@if(!(Test-Path$config)){New-Item-ItemTypeFile-Path$config|Out-Null}$configText=Get-Content-LiteralPath$config-Raw-ErrorActionSilentlyContinue$originalConfigText=$configTextif(-not(Has-HostConfig$configText$hostAlias)){if([string]::IsNullOrWhiteSpace($configText)){Set-Content-LiteralPath$config-Value$configBlock-EncodingASCII}else{Add-Content-LiteralPath$config-Value$configBlock-EncodingASCII}Write-Host"SSH config added: Host$hostAlias"-ForegroundColorGreen}else{Set-HostConfigBlock$config$hostAlias$configBlockWrite-Host"SSH config updated: Host$hostAlias"-ForegroundColorGreen}$configText=Get-Content-LiteralPath$config-Raw-ErrorActionSilentlyContinueif(-not(Has-HostConfig$configText$hostAlias)){throw"SSH config was not written correctly: Host$hostAliasnot found in$config"}$parsedConfig=&ssh.exe-G-F$config$hostAlias2>&1if($LASTEXITCODE-ne0){throw"ssh cannot read config:$parsedConfig"}if(-not($parsedConfig-match"(?m)^hostname\s+$([regex]::Escape($ip))\s*$")){throw"ssh config is not applied correctly: Host$hostAliasdid not resolve to$ip"}$keyGenerated=$falseif(!(Test-Path$pub)){Write-Host"Creating SSH key:$key"-ForegroundColorCyan ssh-keygen.exe-trsa-b4096-N'""'-f$key|Out-Null$keyGenerated=$true}$cmd='umask 077; mkdir -p ~/.ssh; touch ~/.ssh/authorized_keys; TMP=~/ssh_pubkey_$$; cat > $TMP; grep -qxFf $TMP ~/.ssh/authorized_keys || { echo >> ~/.ssh/authorized_keys; cat $TMP >> ~/.ssh/authorized_keys; }; chmod 700 ~/.ssh; chmod 600 ~/.ssh/authorized_keys; grep -qxFf $TMP ~/.ssh/authorized_keys && echo PUBLIC_KEY_INSTALLED; rm -f $TMP'Write-Host''Write-Host'Now enter the server password if ssh asks for it.'-ForegroundColorYellow Write-Host"Connecting with SSH config:$hostAlias..."-ForegroundColorCyan$knownHosts=Join-Path$HOME'.ssh\known_hosts'$hadKnownHosts=Test-Path$knownHostsif($hadKnownHosts){$originalKnownHosts=Get-Content-LiteralPath$knownHosts-Raw-ErrorActionSilentlyContinue}&cmd.exe /ctype"$pub"|&ssh.exe-F$config-oConnectTimeout=5-oPubkeyAuthentication=no-oPreferredAuthentications=password,keyboard-interactive$hostAlias$cmdif($LASTEXITCODE-ne0){# Cleanup: restore config to original state if password auth failsif([string]::IsNullOrWhiteSpace($originalConfigText)){Remove-Item-LiteralPath$config-Force-ErrorActionSilentlyContinue Write-Host'Config file removed (was empty before this run).'-ForegroundColorYellow}else{Set-Content-LiteralPath$config-Value$originalConfigText-EncodingASCII Write-Host'Config restored to original state.'-ForegroundColorYellow}if($keyGenerated){Remove-Item-LiteralPath$key,$pub-Force-ErrorActionSilentlyContinue Write-Host'Generated key files removed.'-ForegroundColorYellow}if($hadKnownHosts){Set-Content-LiteralPath$knownHosts-Value$originalKnownHosts-EncodingASCII Write-Host'known_hosts restored to original state.'-ForegroundColorYellow}else{Remove-Item-LiteralPath$knownHosts-Force-ErrorActionSilentlyContinue Write-Host'known_hosts file removed.'-ForegroundColorYellow}throw"ssh password authentication failed with exit code$LASTEXITCODE"}Write-Host''Write-Host'Testing key login ...'-ForegroundColorCyan&ssh.exe-F$config-oBatchMode=yes-oConnectTimeout=5$hostAlias"echo KEY_LOGIN_OK"if($LASTEXITCODE-ne0){throw"public key was installed, but key login still failed"}Write-Host''Write-Host'Done. Use this command next time:'-ForegroundColorGreen Write-Host"ssh$hostAlias"Write-Host'or:'Write-Host"ssh -i`"$key`"-p$port$user@$ip" } catch { Write-Host '' Write-Host "Failed:$($_.Exception.Message)"-ForegroundColorRed}

把上述代码保存为.bat文件双击启动,依次键入IP,用户名,密钥名,主机别名,密码
出现PUBLIC_KEY_INSTALLED和 KEY_LOGIN_OK即代表成功。

最后可以使用ssh [主机别名]测试免密配置是否成功。