0

私は、ジョブで使用するために関数をスクリプトブロックに渡すことについてこの投稿を読んでいました:

Powershell start-job -scriptblockは、同じファイルで定義されている関数を認識できませんか?

関数を変数として渡すことでそれがどのように機能するかを理解し、簡単な例で機能します。しかし、実際のソリューションについてはどうでしょうか。これを処理するためのよりエレガントな方法はありますか?

ベンダーソフトウェアに変更を展開するために使用しているスクリプトがあります。環境をナビゲートする方法を指示するxmlを読み取り、ドライブのマップ、サービスの停止、perlインストールスクリプトの呼び出しなどのさまざまなタスクを実行します。スクリプトにパラメーターを指定して、スクリプトを同時に実行できるようにします。これにより、perlスクリプトに5分かかり(珍しいことではありません)、スクリプトの実行を待機していない11台のサーバーにロールアウトする場合に使用できます。 1時間。

完全なスクリプトは少し長いので、いくつかのスニペットを投稿します。ログ関数:

function Log
{
    Param(
    [parameter(ValueFromPipeline=$true)]
    $InputObject,
    [parameter()]
    [alias("v")]
    $verbosity = $debug    
    )       

    $messageIndex = [array]::IndexOf($verbosityArray, $verbosity)
    $verbosityIndex = [array]::IndexOf($verbosityArray, $loggingVerbosity)

    if($messageIndex -ge $VerbosityIndex)
    {
        switch($verbosity)
        {
            $debug {Write-Host $verbosity ": " $InputObject}
            $info  {Write-Host $verbosity ": " $InputObject}
            $warn  {Write-Host $verbosity ": " $InputObject -ForegroundColor yellow}
            $error {Write-Host $verbosity ": " $InputObject -ForegroundColor red}
        }        
    }
}

log関数を呼び出す別の関数は次のとおりです。

function ExecuteRollout
{
    param(
    [parameter(Mandatory=$true)]
    [alias("ses")]
    $session,
    [parameter(Mandatory=$true)]
    $command
    )

    #invoke command    
    Invoke-Command -session $session -ScriptBlock {$res = cmd /v /k `"$args[0]`"} -args $command

    #get the return code from the remote session
    $res = Invoke-Command -session $session {$res}
    Log ("Command Output: "+$res)    
    $res = [string] $res        
    $exitCode = $res.substring($res.IndexOf("ExitCode:"), 10)
    $exitCode = $exitCode.substring(9,1)     
    Log ("Exit code: "+$exitCode)

    return $exitCode
}

そして最後に私のメインからのスニペットなので、何が起こっているのかを知ることができます。$ target.Destinations.Destinationには、デプロイメントが移動するすべてのサーバーとそれらに関する関連情報が含まれます。これをよりコンパクトにするために、いくつかの変数のセットアップとロギングを削除したので、はい、定義されていない参照された変数が表示されます。

#Execute concurrently
$target.Destinations.Destination | %{
    $ScriptBlock = {

        $destination = $args[0]

        Log -v $info ("Starting remote session on: "+$destination.Server)
        $session = New-PSSession -computerName $destination.Server               

        $InitializeRemote -session $session -destination $destination

        #Gets a little tricky here, we need to keep the cmd session so it doesn't lose the sys vars set by env.bat
        #String everything together with &'s    
        $cmdString = $destDrive + ": & call "+$lesDestDir+"data\env.bat & cd "+$rolloutDir+" & perl ..\JDH-rollout-2010.pl "+$rollout+" NC,r:\les & echo ExitCode:!errorlevel!"
        Log ("cmdString: "+$cmdString)
        Log -v $info ("Please wait, executing the rollout now...")
        $exitCode = $ExecuteRollout -session $session -command $cmdString    
        Log ("ExitCode: "+$exitCode)

        #respond to return code from rollout script
        $HandleExitCode -session $session -destination $destination -exitCode $exitCode

        $CleanUpRemote -session $session -destination $destination            
    }
    Start-Job $ScriptBlock -Args $_
}

したがって、リンクのアプローチを使用すると、すべての関数を変数に変換して、スクリプトブロックに渡すことになります。現在、冗長性パラメーターが別の冗長性として明示的に渡されない限り、私のログ関数はデフォルトでDEBUGにログインします。ファンクチンを変数に変換すると、PowerShellは次の構文を好まないようです。

$Log ("Print this to the log")

だから私は今ずっとパラメータを使う必要があると思います:

$Log ("Print this to the log" -v $debug

つまり、最終的には、すべての関数を変数としてスクリプトブロックに渡し、それらを呼び出すときにいくつかのフォーマットを変更する必要があるように見えます。それほど大きな努力ではありませんが、スクリプトをハッキングする前に、もっと良い方法があるかどうかを知りたいと思います。入力と見てくれてありがとう、私はこれがかなり長い投稿であることを知っています。

4

1 に答える 1

0

変数として格納されている関数にパラメーターを渡すことについて別の投稿を開始しました。その答えもこの問題を解決します。その投稿はここで見つけることができます:

Powershell:変数に格納されている関数にパラメーターを渡す

簡単に言うと、Start-Jobのinitializescriptパラメーターを使用して、すべての関数をブロックにラップして変数に格納すると、すべての関数をフィードできます。

例:

# concurrency
$func = {
    function Logx 
    {
        param(
        [parameter(ValueFromPipeline=$true)]
        $msg
        )    
        Write-Host ("OUT:"+$msg)
    }
}

# Execution starts here
cls
$colors = @("red","blue","green")
$colors | %{
    $scriptBlock = 
    {   
        Logx $args[0]
        Start-Sleep 9        
    } 

    Write-Host "Processing: " $_
    Start-Job -InitializationScript $func -scriptblock $scriptBlock -args $_
}

Get-Job

while(Get-Job -State "Running")
{
    write-host "Running..."
    Start-Sleep 2
}

# Output
Get-Job | Receive-Job

# Cleanup jobs
Remove-Job * 
于 2012-08-04T19:06:21.610 に答える