如何为 PowerShell 函数设置超时?
How to set timeout to a PowerShell function?
我有一个脚本正在获取呼叫中心许多机器的磁盘 space 信息。但是,有时此功能需要的时间太长。我需要为该功能创建一个超时,但一直无法做到。我尝试使用 start-job 但老实说,我并不完全理解它,所以我没有得到想要的结果。
try {
$timeoutSeconds = 30
$code = {
param($currentPCname, $activeDriveTypes)
// Function which takes computer name as input and outputs the ComputerName,DeviceID, Size, Freespace and DriveType (3 = local)
function get-FDS {
[cmdLetBinding()]
Param([string]$hostName)
Get-WmiObject Win32_LogicalDisk -ComputerName $hostName |
Where-object {$_.DriveType -in $activeDriveTypes} |
select-Object @{Name="ComputerName";Expression={$hostName}}, @{Name="Date";Expression={Get-Date}}, DeviceID, Size, Freespace, DriveType
}
get-FDS($currentPCname) -errorAction stop
}
$processTime = measure-command {
$j = Start-Job -ScriptBlock $code -Arg $currentPCname, $activeDriveTypes
if (Wait-Job $j -Timeout $timeoutSeconds) { $tempData = Receive-Job $j }
$jobState = $j.state
Remove-Job -force $j
}
if ($jobState -ne 'Completed') {
$pcTurnedOn = $false
$errorMessage = "ERROR talking to $currentPCname : Query timed-out"
$query = "CALL sp_fds_insert_log(" + $currentRunID + ", '" + $errorMessage + "', '" + $scriptName + "');"
$cmd = new-object mysql.data.mysqlclient.mysqlcommand($query, $conn)
$cmd.executenonquery()
}
} catch {
$pcTurnedOn = $false
$errorMessage = "ERROR talking to $currentPCname : $_"
$query = "CALL sp_fds_insert_log(" + $currentRunID + ", '" + $errorMessage + "', '" + $scriptName + "');"
$cmd = new-object mysql.data.mysqlclient.mysqlcommand($query, $conn)
$cmd.executenonquery()
}
上面代码的要点是,如果下面的行调用了 $code 段
$processTime = measure-command {
$j = Start-Job -ScriptBlock $code -Arg $currentPCname, $activeDriveTypes
if (Wait-Job $j -Timeout $timeoutSeconds) { $tempData = Receive-Job $j }
$jobState = $j.state
Remove-Job -force $j
}
超过 30 秒即 $timeoutSeconds,将调用最后一个 IF 语句,如果上面的行由于某种原因不起作用,将调用 catch 语句,如果它在不到 30 秒内起作用,什么都不会被调用。
如果作业在超时之前完成,Wait-Job
将 return 作业本身 - 如果超过超时,它不会 return 任何东西:
$timeout = 2
$job = Start-Job { Start-Sleep -Seconds 3 }
$done = $job |Wait-Job -TimeOut $timeout
if($done){
# It returned within the timeout
}
else {
# Nothing was returned, job timed out
}
我有一个脚本正在获取呼叫中心许多机器的磁盘 space 信息。但是,有时此功能需要的时间太长。我需要为该功能创建一个超时,但一直无法做到。我尝试使用 start-job 但老实说,我并不完全理解它,所以我没有得到想要的结果。
try {
$timeoutSeconds = 30
$code = {
param($currentPCname, $activeDriveTypes)
// Function which takes computer name as input and outputs the ComputerName,DeviceID, Size, Freespace and DriveType (3 = local)
function get-FDS {
[cmdLetBinding()]
Param([string]$hostName)
Get-WmiObject Win32_LogicalDisk -ComputerName $hostName |
Where-object {$_.DriveType -in $activeDriveTypes} |
select-Object @{Name="ComputerName";Expression={$hostName}}, @{Name="Date";Expression={Get-Date}}, DeviceID, Size, Freespace, DriveType
}
get-FDS($currentPCname) -errorAction stop
}
$processTime = measure-command {
$j = Start-Job -ScriptBlock $code -Arg $currentPCname, $activeDriveTypes
if (Wait-Job $j -Timeout $timeoutSeconds) { $tempData = Receive-Job $j }
$jobState = $j.state
Remove-Job -force $j
}
if ($jobState -ne 'Completed') {
$pcTurnedOn = $false
$errorMessage = "ERROR talking to $currentPCname : Query timed-out"
$query = "CALL sp_fds_insert_log(" + $currentRunID + ", '" + $errorMessage + "', '" + $scriptName + "');"
$cmd = new-object mysql.data.mysqlclient.mysqlcommand($query, $conn)
$cmd.executenonquery()
}
} catch {
$pcTurnedOn = $false
$errorMessage = "ERROR talking to $currentPCname : $_"
$query = "CALL sp_fds_insert_log(" + $currentRunID + ", '" + $errorMessage + "', '" + $scriptName + "');"
$cmd = new-object mysql.data.mysqlclient.mysqlcommand($query, $conn)
$cmd.executenonquery()
}
上面代码的要点是,如果下面的行调用了 $code 段
$processTime = measure-command {
$j = Start-Job -ScriptBlock $code -Arg $currentPCname, $activeDriveTypes
if (Wait-Job $j -Timeout $timeoutSeconds) { $tempData = Receive-Job $j }
$jobState = $j.state
Remove-Job -force $j
}
超过 30 秒即 $timeoutSeconds,将调用最后一个 IF 语句,如果上面的行由于某种原因不起作用,将调用 catch 语句,如果它在不到 30 秒内起作用,什么都不会被调用。
如果作业在超时之前完成,Wait-Job
将 return 作业本身 - 如果超过超时,它不会 return 任何东西:
$timeout = 2
$job = Start-Job { Start-Sleep -Seconds 3 }
$done = $job |Wait-Job -TimeOut $timeout
if($done){
# It returned within the timeout
}
else {
# Nothing was returned, job timed out
}