Dan*_*iel 5 asp.net powershell remoting multithreading iis-7.5
我目前正在尝试使用PowerShell构建一个线程清理脚本,该脚本是从IIS启动的.我使用powershell远程处理创建了一个线程"由所有者杀死进程",从与清理脚本相同的服务器列表运行,这没有问题.
$jobs = @()
foreach ($comp in $comps) {
$jobs += start-job -FilePath ("CleanupJob.ps1") -ArgumentList $comp, $username
Write-Host "Started Job on: $comp"
}
foreach($job in $jobs)
{
$job | wait-job | out-null
receive-job $job.ID
}
Remove-Job -State Completed
Run Code Online (Sandbox Code Playgroud)
当我从powershell控制台运行我的脚本时,整个过程运行完美,主线程启动28个新进程,启动与每个服务器的远程连接,并等待所有作业完成.完成后,我得到输出,主机线程存在.全部按计划运行.
当我从我的asp.net应用程序运行它时不是这样,我为我的28个服务器中的每个服务器获得"开始工作:$ comp",但只有前14个服务器的结果,然后主机线程就在那里.(直到我用火杀死它,我的输出返回到asp.net网页)
当我从asp.net页面运行它时,我无法看到脚本中发生了什么.我可以看到cpu/ram使用率下降到与从PSconsole运行它时相同的水平,但我的主线程从不关闭.所以我确实认为脚本按照假设工作,但我的网页挂起,直到主线程关闭(它从来没有,如上所述).
这就是我调用脚本的方式(不是漂亮的.net <3 powershell方式:)
public string RunProgramme(string scriptpath, string arguments)
{
ProcessStartInfo startInfo = new ProcessStartInfo();
startInfo.FileName = @"powershell.exe";
startInfo.Arguments = "& \'"+scriptpath+"\' "+ arguments;
//return startInfo.Arguments;
startInfo.RedirectStandardOutput = true;
startInfo.RedirectStandardError = true;
startInfo.UseShellExecute = false;
startInfo.CreateNoWindow = true;
Process process = new Process();
process.StartInfo = startInfo;
process.Start();
string output = process.StandardOutput.ReadToEnd();
string errors = process.StandardError.ReadToEnd();
return output;
}
Run Code Online (Sandbox Code Playgroud)
神秘感加深了,将这一行添加到我的线程工作中
Invoke-Command -Session $session -ScriptBlock {param($path) net send mymachine $path} -Args $msg
Run Code Online (Sandbox Code Playgroud)
当我从IIS运行我的脚本时,我收到来自每台机器的消息.正如我的ram用法显示的那样,所有作业都在运行,但输出没有正确返回,我的主机线程就在那里......等待...
作为一个说明,你有一些不必要的东西正在发生.
foreach ($comp in $comps) {
start-job -FilePath ("CleanupJob.ps1") -ArgumentList $comp, $username
Write-Verbose "Started Job on: $comp"
}
Get-Job | Wait-Job | Out-Null
Remove-Job -State Completed
Run Code Online (Sandbox Code Playgroud)
PowerShell已经构建了一份工作清单; 在$ jobs变量中没有必要这样做,也不需要枚举它们来进行等待.
当然,您可以在代码中使用$ jobs来做其他事情 - 但只是想确保其他人看到这个替代方案.
我找到了解决方案。这是调用造成的死锁
string output = process.StandardOutput.ReadToEnd();
string errors = process.StandardError.ReadToEnd();
Run Code Online (Sandbox Code Playgroud)
紧随其后。相反,我遵循了http://msdn.microsoft.com/en-us/library/system.diagnostics.processstartinfo.redirectstandarderror.aspx#Y95并改为这样做:
public string RunProgramme(string scriptpath, string arguments)
{
ProcessStartInfo startInfo = new ProcessStartInfo();
startInfo.FileName = @"powershell.exe";
startInfo.Arguments = "& \'"+scriptpath+"\' "+ arguments;
startInfo.ErrorDialog = false;
startInfo.RedirectStandardOutput = true;
startInfo.RedirectStandardError = true;
startInfo.UseShellExecute = false;
startInfo.CreateNoWindow = true;
Process process = new Process();
process.StartInfo = startInfo;
process.Start();
process.BeginErrorReadLine();
//Use BeginErrorReadLine on one of the streams to avoid the deadlock
//(i didnt need my error stream, but I did need to filter the errors from my output, so i did this)
string output = process.StandardOutput.ReadToEnd();
process.WaitForExit(1000 * 60);
return output;
}
Run Code Online (Sandbox Code Playgroud)
不再挂了:)
| 归档时间: |
|
| 查看次数: |
11531 次 |
| 最近记录: |