&2; } die() { yell "$*"; ex-6ren">
gpt4 book ai didi

linux - 如何创建运行命令的函数?

转载 作者:太空宇宙 更新时间:2023-11-04 10:04:07 26 4
gpt4 key购买 nike

所以我想做的是重新创建一个与我在 Bash 中使用的类似的函数,但在 Powershell 中:

yell() { echo "$0: $*" >&2; }
die() { yell "$*"; exit 111; }
try() { "$@" || die "FAILED: $*"; }

目前我最感兴趣的部分是这里的 try() 函数。本质上,它的作用是让我用这个函数包装一个命令,并让它管理退出代码。效果是这样的:

try doSomething -args

如果 doSomething 以非零值退出,它会将命令输出到 stderr 并停止脚本执行。

我知道 Powershell 有一个错误操作可以用来中止脚本,但它似乎只适用于 commandlet。我需要一些我可以在整个脚本中使用的东西。我还希望避免大量冗长的 try/catch 逻辑弄乱脚本,因此需要像 try/yell/die 这样优雅的东西。这样,我就可以单独在这个函数中编写处理,然后用它来调用任何我想处理的东西。

我找到了 $MyInvocation 并认为这可能是进入的方式,但我似乎找不到从函数内部实际执行它的方法。例如:

function run() {
$MyInvocation # ?? what do??
}

run doSomething -args

我想我可以自己弄清楚剩下的部分,我只是不太清楚如何编写这个包装函数。有什么想法吗?

更新

所以我做了一些俗气的事情,我对命令进行了子字符串化,并对剩下的内容做了一个 Invoke-Expression,它似乎可以工作。感觉 super 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 采用 automatic variable $args(传递给函数的参数数组)并将其第一个元素分配给变量 $cmd,其余元素分配给变量 $params.

$params = @($params) 确保 $params 包含一个数组(下一步需要),即使变量为空或仅包含一个数组单值。

& $cmd @params 使用 call operator 调用命令& 同时 splatting参数。 Do NOT use Invoke-Expression .

redirection operator 2>&1 将错误输出与正常输出合并,因此两个输出流都被捕获到变量 $output 中。

如果 $cmd 是一个 PowerShell cmdlet 错误将引发异常,该异常会被 try 捕获陈述。 try block 中的其余代码将被跳过。但是请注意,并非 PowerShell cmdlet 抛出的所有错误都是自动终止错误(例如,参见脚本专家博客上的 "An Introduction to Error Handling in PowerShell")。要将非终止错误转换为终止错误,您需要设置 $ErrorActionPreference = 'Stop'(并在完成后将其重置为原始值)。

如果$cmd 是一个外部命令 错误不会抛出异常,但是自动变量$LastExitCode使用命令的退出代码更新。返回非零退出代码的命令将触发 if 条件并导致抛出自定义异常,使用命令输出作为异常消息。然后该异常也被 try 语句捕获。 try block 中的其余代码再次被跳过。

$global:LastExitCode = 0 在每次运行前重置变量 $LastExitCode。这是必要的,因为只有外部命令返回退出代码,而 PowerShell cmdlet 则不会。由于 $LastExitCode 保留了当前 session 中上次运行的外部命令的退出代码,因此不重置该变量会混淆在外部命令后运行的 PowerShell cmdlet 的状态检测。

只有当命令既不抛出异常也不返回非零退出代码时,才会到达 try block 中的最后一行,它回显捕获的命令输出。

任何捕获的异常都在 catch block 中处理,它只是将异常传递给函数的调用者。当然,您也可以输出错误并退出,而不是抛出。

关于linux - 如何创建运行命令的函数?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/53837910/

26 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com