linux - 如何创建运行命令的函数?
问题描述
所以我想做的是重新创建一个与我在 Bash 中使用的类似的函数,但在 Powershell 中:
yell() { echo "$0: $*" >&2; }
die() { yell "$*"; exit 111; }
try() { "$@" || die "FAILED: $*"; }
我目前最感兴趣的部分是这里的 try() 函数。本质上它的作用是允许我用这个函数包装一个命令并让它管理退出代码。效果是这样的:
try doSomething -args
如果doSomething
以非零值退出,它会将命令输出到 stderr 并停止脚本执行。
我意识到 Powershell 有一个可用于中止脚本的错误操作,但它似乎只适用于命令行开关。我需要一些可以在整个脚本中使用的东西。我还希望避免大量冗长的 try/catch 逻辑使脚本变得混乱,因此需要像 try/yell/die 这样优雅的东西。这样,我可以单独在这个函数中编写处理,并使用它来调用我想要处理的任何内容。
我发现$MyInvocation
并认为这可能是进入的方式,但我似乎无法找到从函数中实际执行它的方法。例如:
function run() {
$MyInvocation # ?? what do??
}
run doSomething -args
我想我可以自己弄清楚其余的,我只是不太清楚如何编写这个包装函数。有任何想法吗?
更新
所以我做了一些俗气的事情,我对命令进行了子串化,并对Invoke-Expression
剩下的内容做了一个,它似乎有效。感觉超级hacky,所以我仍然对想法持开放态度:
function attempt() {
$thisCommand = $MyInvocation.Line.Trim()
Write-Output $thisCommand
Invoke-Expression $thisCommand.Substring(8)
if($LASTEXITCODE -ne 0) {
throw "Command failed $thisCommand"
exit 111
}
}
attempt doSomething -args
解决方案
如果您希望函数运行任意命令并在该命令失败时抛出错误,您可以执行以下操作:
function Test-Command {
try {
$cmd, $params = $args
$params = @($params)
$global:LastExitCode = 0
$output = & $cmd @params 2>&1
if ($global:LastExitCode -ne 0) {
throw $output
}
$output
} catch {
throw $_
}
}
分解:
$cmd, $params = $args
获取自动变量 $args
(传递给函数的参数数组)并将其第一个元素分配给变量$cmd
,其余元素分配给变量$params
。
$params = @($params)
确保$params
包含一个数组(下一步需要),即使变量为空或仅包含一个值。
& $cmd @params
使用call 操作符 调用命令,&
同时喷出参数。不要使用Invoke-Expression
. _
重定向运算符 将2>&1
错误输出与正常输出合并,以便在变量 中捕获两个输出流$output
。
如果$cmd
是PowerShell cmdlet错误将引发异常,该异常会被try
语句捕获。try
然后将跳过块中的其余代码。但是请注意,并非所有由 PowerShell cmdlet 引发的错误都会自动终止错误(例如,请参阅脚本专家博客上的“PowerShell 中的错误处理简介” )。要将非终止错误转换为终止错误,您需要设置$ErrorActionPreference = 'Stop'
(并在完成后将其重置为其原始值)。
如果$cmd
是外部命令错误不会抛出异常,但自动变量$LastExitCode
会更新为命令的退出代码。返回非零退出代码的命令将触发if
条件并导致引发自定义异常,使用命令输出作为异常消息。然后该异常也被该try
语句捕获。块中的其余代码try
再次被跳过。
$global:LastExitCode = 0
$LastExitCode
在每次运行之前重置变量。这是必要的,因为只有外部命令会返回退出代码,而 PowerShell cmdlet 不会。由于$LastExitCode
保留了当前会话中最后一次运行的外部命令的退出代码,因此不重置变量会影响在外部命令之后运行的 PowerShell cmdlet 的状态检测。
try
仅当命令既不引发异常也不返回非零退出代码时,才会到达块中的最后一行,它回显捕获的命令输出。
任何捕获的异常都在catch
块中处理,它只是将异常传递给函数的调用者。当然,您也可以输出错误并退出,而不是抛出。
推荐阅读
- mysql - SQL 密集索引和备用索引
- c# - 带有 DnSpy 的问题类 C# System.Net.Http
- python - Selenium 未加载 TikTok 页面
- javascript - JavaScript 函数输出的问题不会持续存在
- sql - SQL Server 中允许您将存储过程存储在表中并在从 select 语句中检索它后调用它的机制?
- sql-server - 触发更新我单击更新的行上的列
- javascript - 对 JavaScript 继承/原型感到困惑
- matlab - 每次少遍历一个数组
- javascript - 保存用户数据谷歌浏览器扩展
- c# - 如何使用 API 将 base64 图像保存到另一个项目