从powershell函数内部流式传输外部命令的输出



考虑以下命令:

7z.exe a -t7z folder.7z folder

我有以下两个精简的powershell脚本

文件1:common.ps1

function Archive-Folder ($src, $dest_path, $archive_name) {
$script_dir = split-path $script:MyInvocation.MyCommand.Path
if ((test-path $src) -eq $false) {
write-error "$src is not a valid source directory"
#return
return $false
}
if ((test-path $dest_path) -eq $false) {
write-error "$dest_path is not a valid destination directory"
#return
return $false
}
if ([string]::IsNullOrWhiteSpace($archive_name) -eq $true) {
write-error "$archive_name is not a valid archive name"
#return
return $false
}
write-verbose "archiving the folder"
$archive_command = "$script_dir7z.exe a -t7z $dest_path$archive_name $src"
$exe = "$script_dir7z.exe"
$arguments = @('a', '-t7z', "$dest_path$archive_name", "$src")
iex $archive_command
# this doesn't stream the output. it prints it all at once.
# & $exe $arguments | write-verbose
return $true
}

文件2:script.ps1

$script_dir = split-path $script:MyInvocation.MyCommand.Path
. "$script_dircommon.ps1"
$VerbosePreference = "Continue"
$src = 'C:somesource'
$backup_path = 'C:somedestination'
$date_format = 'yyyy_MM_dd_HHmm'
$date = get-date
$date_str = $date.tostring($date_format)
$date_ticks = $date.ticks
$archive_name = "backup-$date_str-$date_ticks.7z"
# this prints the output streamed. The output ends with `True`
archive-folder $src $backup_path $archive_name 
# the following however doesn't output anything. in order to separate the command output from my function output, 
# i was printing the command output using write-verbose
$isSuccess = archive-folder $src $backup_path $archive_name
if ($isSuccess -eq $true) {
#proceed with the rest of the code
}

来自@Christian&zdan,我能够将问题隔离到捕获返回值。与archive-folder类似,我还有其他函数可以执行一些命令行工具。我在想,这些函数中的每一个都可以返回true或false,这取决于该函数是否使用正确的操作调用,以及命令行工具是否正确执行。

但是,如果我捕获了archive-folder函数的返回值,那么命令的输出就不会打印到控制台。此外,我的返回值不包括真值或假值。它由命令的整个输出组成。

我解决这个问题的第一次尝试是将命令执行语句写为iex $archive_command | write-verbose,但这并没有对输出进行流式处理。

我想我可以在成功的情况下检查命令行工具的副作用(比如存档文件的存在),以确定我的函数是否成功执行,但不确定我是否能够为我最终创建的所有函数执行这一操作。

有没有一种方法可以返回值并流式传输命令行工具的输出?

编辑2

关于为什么我要将代码划分为两个独立的文件/函数,我的实际使用场景如下

script.ps1将协调此流程。备份数据库(mongodb为数据库的每个集合生成文件)。归档数据库备份。将档案上传到S3。这些步骤中的每一个都将由common.ps1中的一个单独函数来完成。script.ps1将只包含粘合代码。发布所有这些可能会使问题变得复杂,我觉得不需要理解面临的问题

编辑1

如果正在压缩的文件夹有5个文件,7zip将首先输出版权。然后它将输出文本Scanning。然后它将输出一条线路Creating archive at some location。然后它将处理每个文件,逐个输出每个文件的进度。通过这种方式,我们可以不断获得有关操作进度的反馈。

如果我执行powershell函数,那么在操作期间我看不到任何输出,然后一次看到所有输出。我没有收到7zip的反馈。我想模拟7zip作为独立exe运行时显示的行为。

这对我有效:

& 7z.exe a -t7z -bsp1 $archive_name $src 2>&1 | Out-Host

-bsp1交换机将progress information流重定向到stdout流。这是7z的一个特点。另请查看-bb开关。

CCD_ 14将错误流重定向到CCD_。这是PowerShell的一项功能。

-bs(为输出/错误/进度行设置输出流)开关语法

语法

-bs{o|e|p}{0|1|2}

{id}|流类型。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。o|标准输出消息e|错误消息p |进度信息
{N}|流目的地。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。0|禁用流1|重定向到stdout流2|重定向到stderr流

在我看来,你应该能够做到:

&7z.exe a -t7z $archive_name $src | write-verbose

除非我遗漏了什么。

为什么不这样做?如果您需要

function archive-folder ($src, $archive_name) {   
$origcolor = [console]::ForegroundColor
[console]::ForegroundColor = "yellow"
"archiving $src"
$command = "7z.exe a -t7z $archive_name $src"
iex $command    
[console]::ForegroundColor = $origcolor    
}

我琐碎的调用函数:

Function k
{
dir c:psita
Write-Host "Starting 7zippping from K function"
archive-folder -archive_name c:pspippo.7z c:psita
Write-Host "7zipping from function k ended"
}

以及我在powershell控制台中看到的内容(黄色为archive-folder的输出)

k

Directory: C:psita

Mode           LastWriteTime       Length Name
----           -------------       ------ ----
-a---    08/06/2011    19:26     5,502 MB ita.txt
-a---    28/05/1994    16:59   165,624 KB ITALIANO.A
-a---    28/05/1994    16:54    53,903 KB ITALIANO.B
-a---    28/05/1994    17:00   165,541 KB ITALIANO.C
-a---    08/06/2011    11:06    98,609 KB ITALIANO.D
-a---    28/05/1994    17:00    72,077 KB ITALIANO.E
-a---    28/05/1994    16:54    80,813 KB ITALIANO.F
-a---    28/05/1994    16:55    78,312 KB ITALIANO.G
-a---    28/05/1994    16:55     2,412 KB ITALIANO.H
-a---    08/06/2011    11:07   298,609 KB ITALIANO.I
-a---    28/05/1994    16:55     1,033 KB ITALIANO.J
-a---    28/05/1994    16:55     1,777 KB ITALIANO.K
-a---    28/05/1994    17:01    71,553 KB ITALIANO.L
-a---    08/06/2011    10:59   162,084 KB ITALIANO.M
-a---    28/05/1994    16:56    47,123 KB ITALIANO.N
-a---    28/05/1994    16:56    72,973 KB ITALIANO.O
-a---    08/06/2011    19:37   264,109 KB ITALIANO.P
-a---    28/05/1994    16:56    10,512 KB ITALIANO.Q
-a---    08/06/2011    19:38   327,348 KB ITALIANO.R
-a---    08/06/2011    19:40   566,512 KB ITALIANO.S
-a---    08/06/2011    10:57   184,719 KB ITALIANO.T
-a---    28/05/1994    16:57    19,378 KB ITALIANO.U
-a---    28/05/1994    16:57    61,552 KB ITALIANO.V
-a---    28/05/1994    16:57     1,334 KB ITALIANO.W
-a---    28/05/1994    16:57     1,368 KB ITALIANO.X
-a---    28/05/1994    16:57       533 B  ITALIANO.Y
-a---    28/05/1994    17:01     7,054 KB ITALIANO.Z
Starting 7zippping from K funztion
archiving c:psita
7-Zip 4.65  Copyright (c) 1999-2009 Igor Pavlov  2009-02-03
Scanning
Updating archive c:pspippo.7z
Compressing  ITAITALIANO.H
Compressing  ITAITALIANO.C
Compressing  ITAITALIANO.F
Compressing  ITAita.txt
Compressing  ITAITALIANO.O
Compressing  ITAITALIANO.A
Compressing  ITAITALIANO.B
Compressing  ITAITALIANO.D
Compressing  ITAITALIANO.E
Compressing  ITAITALIANO.G
Compressing  ITAITALIANO.I
Compressing  ITAITALIANO.J
Compressing  ITAITALIANO.K
Compressing  ITAITALIANO.L
Compressing  ITAITALIANO.M
Compressing  ITAITALIANO.N
Compressing  ITAITALIANO.P
Compressing  ITAITALIANO.Q
Compressing  ITAITALIANO.R
Compressing  ITAITALIANO.S
Compressing  ITAITALIANO.T
Compressing  ITAITALIANO.U
Compressing  ITAITALIANO.V
Compressing  ITAITALIANO.W
Compressing  ITAITALIANO.X
Compressing  ITAITALIANO.Y
Compressing  ITAITALIANO.Z
Everything is Ok
7zipping from function k ended

相关内容

最新更新