powershell - 管道流到其他进程
问题描述
我想下载一个 20GB 的转储,替换字符串并将其通过管道传输到 mysql.exe,同时它仍在 Powershell 中下载。但我在管道流中遇到问题。
如果我的文件已经下载,我可以在将文件中的字符串替换为 StdOut 的同时进行流式传输:
Get-Content 'dump.sql' | %{ $_.replace("production_db", "staging_db") }
或者,如果我在流式传输并将字符串替换到 StdOut 时也下载文件,我可以这样做:
$url = 'http://MyServer.ext/dump.sql'
& {
$myHttpWebRequest = [System.Net.WebRequest]::Create($url)
$myHttpWebRequest.Headers.Add("Authorization", "Basic " + [System.Convert]::ToBase64String([System.Text.Encoding]::ASCII.GetBytes("MyUsername:MyPassword")))
try {
$res = $myHttpWebRequest.GetResponse()
}
catch [System.Net.WebException] {
$res = $_.Exception.Response
}
if ([int] $res.StatusCode -ne 200) {
'Error: ' + [int]$res.StatusCode + " " + $res.StatusCode
} else {
$receiveStream = $res.GetResponseStream()
$encode = [System.Text.Encoding]::GetEncoding("utf-8")
$readStream = [System.IO.StreamReader]::new($receiveStream, $encode)
while (-not $readStream.EndOfStream) {
$readStream.ReadLine().replace("production_db", "staging_db")
}
$res.Close()
$readStream.Close()
}
}
但在这两种情况下,我都无法将其作为流传输到 mysql.exe。它接缝整个流首先加载到内存中,然后再传递给 mysql.exe 进程,当我追加时:
| & 'C:\Program Files\MySQL\MySQL Server 5.7\bin\mysql.exe' -u MyUsername -pMyPassword -h 127.0.0.1
我如何设法将流通过管道传输到 Powershell 中的另一个进程?
解决方案
我们知道 mysql.exe 将采用标准输入,因为我们可以运行mysql.exe < myfile.sql
并且它运行良好。我找到了这个关于将文本行发送到进程的标准输入的奇妙答案,它似乎对我有用。我正在使用 CMD shell 进行测试,因为我手边没有 mysql:
# Setup: example commands to feed via stream to process
'echo "hello"
echo "world"
echo "bye"
exit' > 'C:\temp\file.bat'
# create streamreader from file
$readStream = [System.IO.Streamreader]::new('C:\temp\file.bat')
$encode = [System.Text.Encoding]::GetEncoding("utf-8")
对你来说,只需更新你的替换和 exe 名称:
# Create a process for the job
$psi = New-Object System.Diagnostics.ProcessStartInfo;
$psi.FileName = "cmd.exe"; #process file
$psi.UseShellExecute = $false; #start the process from it's own executable file
$psi.RedirectStandardInput = $true; #enable the process to read from standard input
$psi.RedirectStandardOutput = $true #send standard output to object
$p = [System.Diagnostics.Process]::Start($psi);
# Send each line of the file to the process as standard input:
while (-not $readStream.EndOfStream) {
$p.StandardInput.WriteLine(
($readStream.ReadLine().replace("l", "L"))
)
}
$readStream.Close()
# Make sure you don't accidentally close mysql before it's done processing.
# For example, add WriteLine('exit') after the While{}, then use Wait-Process.
# get the output of the process, should also wait for the process to finish
$p.StandardOutput.ReadToEnd()
$p.Close()
在我的测试中,它正在工作,在读取命令时替换它们,并将它们发送到进程,并显示输出:
Microsoft Windows [Version 10.0.19043.1110]
(c) Microsoft Corporation. All rights reserved.
C:\>echo "heLLo"
"heLLo"
C:\>echo "worLd"
"worLd"
C:\>echo "bye"
"bye"
C:\>exit
我认为您应该能够挂接到 $p.StandardOutput 并随时阅读它,但是当我尝试它会导致进程挂起?也许只是使用 mysql 日志记录。
推荐阅读
- jquery - 在下拉菜单中单击时上升选中的单选按钮
- php - 为什么 Lumen 采用数组到字符串的转换?
- visual-studio - 在 Visual Studio 中将所有类添加到 Intellisense
- batch-file - 如何让计算机在人而不是数字之间随机选择并且只显示一次?
- c# - AutoMapper.Collections,EFCore - 使用短暂的 DbContext
- modelica - 使用 Dymola 编译器的 OneModelica 出错
- python-3.x - 如何使用 selenium/python 访问 HTML 文本?
- vue.js - Vuetify 导航抽屉开始关闭,然后一秒钟后打开
- mechanicalturk - 允许在 Mturk 的人群图像分类器上选择多个类
- android - 如何在 Koin Android 中设置不同的测试模块(除了产品)?