PowerShell中Start-Job调用ssh时Receive-Job报错问题求助
解决PowerShell作业中执行ssh报错的问题
问题原因
PowerShell的作业(Job)环境会默认将外部程序(比如ssh)的stderr输出转化为ErrorRecord错误记录,而直接在控制台运行时不会自动这么处理。不管是ssh连接失败的错误信息,还是bash脚本中set -x输出的调试信息(默认输出到stderr),都会被作业判定为错误,最终导致Receive-Job返回报错。
解决方案
方案1:重定向stderr到stdout(最简单)
把ssh的所有输出(包括stderr)统一作为正常输出返回,作业就不会抛出错误:
$job = Start-Job -ScriptBlock {& "ssh" user@host cmd 2>&1} Receive-Job -Job $job -Wait
2>&1是标准的shell重定向语法,将stderr(文件描述符2)的内容重定向到stdout(文件描述符1),作业会把这些内容当成普通输出处理。
方案2:区分stdout/stderr并捕获结果
如果需要分别获取正常输出和错误信息,同时避免作业报错,可以在脚本块里自定义处理逻辑:
$job = Start-Job -ScriptBlock { # 禁止自动抛出错误记录 $ErrorActionPreference = 'SilentlyContinue' # 捕获所有输出(包含stdout字符串和stderr错误记录) $allOutput = & "ssh" user@host cmd 2>&1 # 分离stdout和stderr $stdout = $allOutput | Where-Object { $_ -is [string] } $stderr = $allOutput | Where-Object { $_ -is [Management.Automation.ErrorRecord] } # 返回自定义对象包含所有信息 [PSCustomObject]@{ StdOut = $stdout StdErr = $stderr ExitCode = $LASTEXITCODE # 获取ssh的退出码 } } # 接收作业结果 $result = Receive-Job -Job $job -Wait # 按需查看结果 $result.StdOut $result.StdErr $result.ExitCode
方案3:用Start-Process精细控制输出
如果需要更底层的进程控制,可以用Start-Process重定向输出到文件,再读取内容:
$job = Start-Job -ScriptBlock { # 定义临时文件路径 $stdoutFile = Join-Path $env:TEMP "ssh_stdout.txt" $stderrFile = Join-Path $env:TEMP "ssh_stderr.txt" # 启动ssh进程并重定向输出 $proc = Start-Process -FilePath "ssh" -ArgumentList "user@host", "cmd" ` -NoNewWindow -PassThru ` -RedirectStandardOutput $stdoutFile ` -RedirectStandardError $stderrFile $proc.WaitForExit() # 读取输出并返回 [PSCustomObject]@{ StdOut = Get-Content $stdoutFile -Raw StdErr = Get-Content $stderrFile -Raw ExitCode = $proc.ExitCode } # 清理临时文件 Remove-Item $stdoutFile, $stderrFile -Force } $result = Receive-Job -Job $job -Wait
内容的提问来源于stack exchange,提问作者choosyg
相关产品推荐
相关产品推荐

