繁体   English   中英

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

[英]How do I create function that runs a command?

因此,我想做的是重新创建一个与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并对剩下的内容进行了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展开参数时使用调用运算符 &调用命令。 不要使用Invoke-Expression

重定向运算符 2>&1将错误输出与常规输出合并,以便将两个输出流都捕获到变量$output

如果$cmdPowerShell cmdlet,则错误将引发异常,该异常由try语句捕获。 然后将跳过try块中的其余代码。 但是请注意,并非PowerShell cmdlet引发的所有错误都会自动终止错误(例如,请参见Scripting Guy博客上的“ PowerShell中的错误处理简介” )。 要将非终止错误转换为终止错误,您需要设置$ErrorActionPreference = 'Stop' (完成后将其重置为原始值)。

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

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

仅在命令既不引发异常也不返回非零退出代码的情况下,才到达try块的最后一行,该行回显捕获的命令输出。

任何捕获的异常都在catch块中处理,该块仅将异常传递给函数的调用者。 当然,除了抛出错误,您还可以输出错误并退出。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM