Powershell:在生产中调试/良好的异常处理
在生产环境中分析powershell cmdlet的最佳方法是什么?假设您编写了一个执行以下操作的脚本-Powershell:在生产中调试/良好的异常处理,powershell,powershell-2.0,Powershell,Powershell 2.0,在生产环境中分析powershell cmdlet的最佳方法是什么?假设您编写了一个执行以下操作的脚本- 写入注册表值的lof 注册COM DLL 创建IIS应用程序池 启动Windows服务 &…在这两者之间出现了一些问题,那么最好的做法是什么来通知用户以便跟踪和调试根问题 假设由于某种原因,用户凭据无法创建AppPool 我想在那个时候停止处理,再加上我想回滚 我以前做过的事 详细模式+日志记录是在每一步收集每个细节的优雅方式吗 我编写了一个Write Log函数,发布在poshcode()
详细模式+日志记录是在每一步收集每个细节的优雅方式吗 我编写了一个
Write Log
函数,发布在poshcode()上,用于生产级PowerShell程序。或者,您可以使用Start Transcript
,它将控制台上显示的几乎所有内容记录到一个文件中。关于Start Transcript
-
Out主机
,如ping.exe localhost | Out主机
$host
添加主机检查$\uuu
可用。它将包含所有关于发生的错误、消息、行号和列号等的信息
我还将$ErrorActionPreference
设置为Stop
,这样所有cmdlet都会抛出终止错误,脚本将不会继续。看起来是这样的:
$ErrorActionPreference = "Stop"
try {
# Write lof of registry values
New-Item -Path HKCU:\Software\MyTest -ItemType Directory
New-ItemProperty -Path HKCU:\Software\MyTest -Name MyTestValue -Value Test
# Register COM Dlls
regsrv32 my.dll
if ($LASTEXITCODE -ne 0) { throw "Failed to register my.dll" }
# Make IIS AppPools
IIS:\>New-WebAppPool NewAppPool
# Start Windows Services
Start-Service -Name MyService
} catch {
Write-Log ("Script failed. The error was: '{0}'." -f $_)
}
} catch {
# Undo the registry transaction.
# Unregister the DLL.
# Delete the App pool if it exists.
# Stop the windows service.
}
后退并不容易。。。唯一容易回滚的是注册表操作,因为注册表支持事务(假设Vista或更高版本)。您只需创建一个事务(如数据库)并在发生错误时回滚即可。您提到的其余操作需要特定的代码才能回滚。您可以将回滚代码添加到catch块,如下所示:
$ErrorActionPreference = "Stop"
try {
# Write lof of registry values
New-Item -Path HKCU:\Software\MyTest -ItemType Directory
New-ItemProperty -Path HKCU:\Software\MyTest -Name MyTestValue -Value Test
# Register COM Dlls
regsrv32 my.dll
if ($LASTEXITCODE -ne 0) { throw "Failed to register my.dll" }
# Make IIS AppPools
IIS:\>New-WebAppPool NewAppPool
# Start Windows Services
Start-Service -Name MyService
} catch {
Write-Log ("Script failed. The error was: '{0}'." -f $_)
}
} catch {
# Undo the registry transaction.
# Unregister the DLL.
# Delete the App pool if it exists.
# Stop the windows service.
}
我编写了一个
Write Log
函数,发布在poshcode()上,用于生产级PowerShell程序。或者,您可以使用Start Transcript
,它将控制台上显示的几乎所有内容记录到一个文件中。关于Start Transcript
-
Out主机
,如ping.exe localhost | Out主机
$host
添加主机检查$\uuu
可用。它将包含所有关于发生的错误、消息、行号和列号等的信息
我还将$ErrorActionPreference
设置为Stop
,这样所有cmdlet都会抛出终止错误,脚本将不会继续。看起来是这样的:
$ErrorActionPreference = "Stop"
try {
# Write lof of registry values
New-Item -Path HKCU:\Software\MyTest -ItemType Directory
New-ItemProperty -Path HKCU:\Software\MyTest -Name MyTestValue -Value Test
# Register COM Dlls
regsrv32 my.dll
if ($LASTEXITCODE -ne 0) { throw "Failed to register my.dll" }
# Make IIS AppPools
IIS:\>New-WebAppPool NewAppPool
# Start Windows Services
Start-Service -Name MyService
} catch {
Write-Log ("Script failed. The error was: '{0}'." -f $_)
}
} catch {
# Undo the registry transaction.
# Unregister the DLL.
# Delete the App pool if it exists.
# Stop the windows service.
}
后退并不容易。。。唯一容易回滚的是注册表操作,因为注册表支持事务(假设Vista或更高版本)。您只需创建一个事务(如数据库)并在发生错误时回滚即可。您提到的其余操作需要特定的代码才能回滚。您可以将回滚代码添加到catch块,如下所示:
$ErrorActionPreference = "Stop"
try {
# Write lof of registry values
New-Item -Path HKCU:\Software\MyTest -ItemType Directory
New-ItemProperty -Path HKCU:\Software\MyTest -Name MyTestValue -Value Test
# Register COM Dlls
regsrv32 my.dll
if ($LASTEXITCODE -ne 0) { throw "Failed to register my.dll" }
# Make IIS AppPools
IIS:\>New-WebAppPool NewAppPool
# Start Windows Services
Start-Service -Name MyService
} catch {
Write-Log ("Script failed. The error was: '{0}'." -f $_)
}
} catch {
# Undo the registry transaction.
# Unregister the DLL.
# Delete the App pool if it exists.
# Stop the windows service.
}
对于直接注册表操作,您可以使用PowerShell的事务支持,在脚本总体成功后提交更改,或撤消事务以回滚注册表更改,例如:
try {
$ErrorActionPreference = 'Stop' # convert all errors to terminating errors
Start-Transaction
Set-ItemProperty Acme -Name Count -Value 99 -UseTransaction
Remove-ItemProperty Acme -Name InstallDir -UseTransaction
New-Item Acme2 -UseTransaction
New-ItemProperty Acme2 -Name Count -Value 2 -UseTransaction
New-ItemProperty Acme2 -Name InstallDir -Value 'C:\Program Files\Acme2' -UseTx
... do other stuff ...
Complete-Transaction
}
catch {
Undo-Transaction
... Log failure ...
}
对于直接注册表操作,您可以使用PowerShell的事务支持,在脚本总体成功后提交更改,或撤消事务以回滚注册表更改,例如:
try {
$ErrorActionPreference = 'Stop' # convert all errors to terminating errors
Start-Transaction
Set-ItemProperty Acme -Name Count -Value 99 -UseTransaction
Remove-ItemProperty Acme -Name InstallDir -UseTransaction
New-Item Acme2 -UseTransaction
New-ItemProperty Acme2 -Name Count -Value 2 -UseTransaction
New-ItemProperty Acme2 -Name InstallDir -Value 'C:\Program Files\Acme2' -UseTx
... do other stuff ...
Complete-Transaction
}
catch {
Undo-Transaction
... Log failure ...
}
有一件事-我有35个不同的嵌套模块。并且,通过导入模块调用加载所有模块,然后依次调用与特定操作相关的特定函数。那么,我还是应该将try/catch放在模块中的每个函数中,还是应该将所有调用序列封装在一个tr/catch@AngshumanAgarwal我通常遵循的模式是在模块函数中使用try/catch。如果它们出了问题,我只会抛出一条异常消息。它将在调用方的catch块中捕获,您可以重新抛出,因此当它在main中结束时,您将有一个伪stacktrace进行评估。Was使用Write Log函数。你不认为这个函数应该这样修改吗?-[Parameter()][Switch]$NoConsoleOut=$true,@AngshumanAgarwal我的目标之一是同时记录和显示信息,这样用户就可以知道程序运行时的状态。一件事——我有35个不同的嵌套模块。并且,通过导入模块调用加载所有模块,然后依次调用与特定操作相关的特定函数。那么,我还是应该将try/catch放在模块中的每个函数中,还是应该将所有调用序列封装在一个tr/catch@AngshumanAgarwal我通常遵循的模式是在模块函数中使用try/catch。如果它们出了问题,我只会抛出一条异常消息。它将在调用方的catch块中捕获,您可以重新抛出,因此当它在main中结束时,您将有一个伪stacktrace进行评估。Was使用Write Log函数。你不认为这个函数应该这样修改吗?-[Parameter()][Switch]$NoConsoleOut=$true,@AngshumanAgarwal我的目标之一就是记录一个