如何同时捕获外部命令输出并将其打印到终端
How to simultaneously capture external command output and print it to the terminal
我可以通过管道返回:
$OUTPUT = $(flutter build ios --release --no-codesign | tail -1)
我想从构建中获取最后一行并显示进度,例如
$OUTPUT = $(flutter build ios --release --no-codesign | out | tail -1)
假设的 out
实用程序也会将输出发送到终端。
你知道怎么做吗?
我假设你的意思是 bash,因为据我所知,powershell 中没有 tail
。
下面介绍了如何查看命令的输出,同时仍将其捕获到变量中。
#!/bin/bash
# redirect the file descriptor 3 to 1 (stdout)
exec 3>&1
longRunningCmd="flutter build ios --release --no-codesign"
# use tee to copy the command's output to file descriptor 3 (stdout) while
# capturing 1 (stdout) into a variable
output=$(eval "$longRunningCmd" | tee >(cat - >&3) )
# last line of output
lastline=$(printf "%s" "$output" | tail -n 1)
echo "$lastline"
注意:在类Unix平台上,是最简单的;除了也在 Windows 上工作之外,下面的解决方案可能对在 PowerShell 中逐行处理外部程序输出感兴趣。
一个PowerShell解决方案(假设你问题中的代码是PowerShell[1]):
我不确定 flutter
是如何报告其进度的,但以下方法可能有效:
如果一切都转到 stdout:
$OUTPUT = flutter build ios --release --no-codesign | % {
Write-Host $_ # print to host (console)
$_ # send through pipeline
} | select -Last 1
注意:%
是 ForEach-Object
, and select
the one for Select-Object
的内置别名。
如果进度消息转到 stderr:
$OUTPUT = flutter build ios --release --no-codesign 2>&1 | % {
Write-Host $_.ToString() # print to host (console)
if ($_ -is [string]) { $_ } # send only stdout through pipeline
} | select -Last 1
[1] 正如变量名中的 $
印记 在赋值的 LHS 中 和 [=19 周围的空格所证明的那样=]
($OUTPUT =
),两者都不会像 bash
/ POSIX 那样的 shell 中预期地工作。
我在管道中使用写入进度。
为了保持可读管道,我写了一个函数
function Write-PipedProgress{
<#
.SYNOPSIS
Insert this function in a pipeline to display progress bar to user
.EXAMPLE
$Result = (Get-250Items |
Write-PipedProgress -PropertyName Name -Activity "Audit services" -ExpectedCount 250 |
Process-ItemFurther)
>
[cmdletBinding()]
param(
[parameter(Mandatory=$true,ValueFromPipeline=$true)]
$Data,
[string]$PropertyName=$null,
[string]$Activity,
[int]$ExpectedCount=100
)
begin {
Write-Verbose "Starting $($MyInvocation.MyCommand)"
$ItemCounter = 0
}
process {
Write-Verbose "Start processing of $($MyInvocation.MyCommand)($Data)"
try {
$ItemCounter++
# (3) mitigate unexpected additional input volume"
if ($ItemCounter -lt $ExpectedCount) {
$StatusProperty = if ($propertyName) { $Data.$PropertyName } > > else { ""}
$StatusMessage = "Processing $ItemCounter th $StatusProperty"
$statusPercent = 100 * $ItemCounter / $ExpectedCount
Write-Progress -Activity $Activity -Status $StatusMessage -> > PercentComplete $statusPercent
} else {
Write-Progress -Activity $Activity -Status "taking longer than expected" -PercentComplete 99
}
# return input data to next element in pipe
$Data
} catch {
throw
}
finally {
Write-Verbose "Complete processing of $Data in > $($MyInvocation.MyCommand)"
}
}
end {
Write-Progress -Activity $Activity -Completed
Write-Verbose "Complete $($MyInvocation.MyCommand) - processed $ItemCounter items"
}
}
希望对您有所帮助 ;-)
我相信这会起作用,至少在 osx 或 linux powershell(甚至 Linux 的 Windows 子系统)中可以使用这些命令。我用 "ls" 而不是 "flutter" 测试了它。真的有"out"命令吗?
$OUTPUT = bash -c 'flutter build ios --release --no-codesign | tee /dev/tty | tail -1'
或者,假设 tee 没有别名为 tee-object。实际上,tee-object 也可以。
$OUTPUT = flutter build ios --release --no-codesign | tee /dev/tty | tail -1
它也可以与 $( ) 一起使用,但您不需要它。在powershell中,它用于组合多个管道。
我可以通过管道返回:
$OUTPUT = $(flutter build ios --release --no-codesign | tail -1)
我想从构建中获取最后一行并显示进度,例如
$OUTPUT = $(flutter build ios --release --no-codesign | out | tail -1)
假设的 out
实用程序也会将输出发送到终端。
你知道怎么做吗?
我假设你的意思是 bash,因为据我所知,powershell 中没有 tail
。
下面介绍了如何查看命令的输出,同时仍将其捕获到变量中。
#!/bin/bash
# redirect the file descriptor 3 to 1 (stdout)
exec 3>&1
longRunningCmd="flutter build ios --release --no-codesign"
# use tee to copy the command's output to file descriptor 3 (stdout) while
# capturing 1 (stdout) into a variable
output=$(eval "$longRunningCmd" | tee >(cat - >&3) )
# last line of output
lastline=$(printf "%s" "$output" | tail -n 1)
echo "$lastline"
注意:在类Unix平台上,
一个PowerShell解决方案(假设你问题中的代码是PowerShell[1]):
我不确定 flutter
是如何报告其进度的,但以下方法可能有效:
如果一切都转到 stdout:
$OUTPUT = flutter build ios --release --no-codesign | % {
Write-Host $_ # print to host (console)
$_ # send through pipeline
} | select -Last 1
注意:%
是 ForEach-Object
, and select
the one for Select-Object
的内置别名。
如果进度消息转到 stderr:
$OUTPUT = flutter build ios --release --no-codesign 2>&1 | % {
Write-Host $_.ToString() # print to host (console)
if ($_ -is [string]) { $_ } # send only stdout through pipeline
} | select -Last 1
[1] 正如变量名中的 $
印记 在赋值的 LHS 中 和 [=19 周围的空格所证明的那样=]
($OUTPUT =
),两者都不会像 bash
/ POSIX 那样的 shell 中预期地工作。
我在管道中使用写入进度。 为了保持可读管道,我写了一个函数
function Write-PipedProgress{ <#
.SYNOPSIS Insert this function in a pipeline to display progress bar to user .EXAMPLE $Result = (Get-250Items | Write-PipedProgress -PropertyName Name -Activity "Audit services" -ExpectedCount 250 | Process-ItemFurther)
>
[cmdletBinding()] param( [parameter(Mandatory=$true,ValueFromPipeline=$true)] $Data, [string]$PropertyName=$null, [string]$Activity, [int]$ExpectedCount=100 ) begin { Write-Verbose "Starting $($MyInvocation.MyCommand)" $ItemCounter = 0 } process { Write-Verbose "Start processing of $($MyInvocation.MyCommand)($Data)" try { $ItemCounter++ # (3) mitigate unexpected additional input volume" if ($ItemCounter -lt $ExpectedCount) { $StatusProperty = if ($propertyName) { $Data.$PropertyName } > > else { ""} $StatusMessage = "Processing $ItemCounter th $StatusProperty" $statusPercent = 100 * $ItemCounter / $ExpectedCount Write-Progress -Activity $Activity -Status $StatusMessage -> > PercentComplete $statusPercent } else { Write-Progress -Activity $Activity -Status "taking longer than expected" -PercentComplete 99 } # return input data to next element in pipe $Data } catch { throw } finally { Write-Verbose "Complete processing of $Data in > $($MyInvocation.MyCommand)" } } end { Write-Progress -Activity $Activity -Completed Write-Verbose "Complete $($MyInvocation.MyCommand) - processed $ItemCounter items" }
}
希望对您有所帮助 ;-)
我相信这会起作用,至少在 osx 或 linux powershell(甚至 Linux 的 Windows 子系统)中可以使用这些命令。我用 "ls" 而不是 "flutter" 测试了它。真的有"out"命令吗?
$OUTPUT = bash -c 'flutter build ios --release --no-codesign | tee /dev/tty | tail -1'
或者,假设 tee 没有别名为 tee-object。实际上,tee-object 也可以。
$OUTPUT = flutter build ios --release --no-codesign | tee /dev/tty | tail -1
它也可以与 $( ) 一起使用,但您不需要它。在powershell中,它用于组合多个管道。