【问题标题】:How do I conditionally execute a resource in Powershell DSC based on a previous resource executing?如何根据先前执行的资源有条件地执行 Powershell DSC 中的资源?
【发布时间】:2014-09-29 18:12:29
【问题描述】:

假设我有两个这样的块:

Configuration TestConfig
{
    Node ('localhost') {
        File foo {
            DestinationPath = 'C:\foo.txt'
            Contents = 'Bar'
        }
        Script dothing {
            SetScript = {'Baz' | set-content C:\foo.txt}
            TestScript = {return $false}
            GetScript = {
                return @{
                    GetScript = ''
                    SetScript = ''
                    TestScript = ''
                    Credential = $Credential
                    Result = (Invoke-Expression -Command $TestScript)
                }
            }
            DependsOn = '[File]foo'
        }
    }
}

我构建了一个执行类似操作的测试,但似乎无论 File 资源的测试输出如何,Service 资源都会被执行 - 也就是说,如果它实际上对文件做了任何事情。

VERBOSE: [MACHINENAME]: LCM:  [ Start  Set      ]
VERBOSE: [MACHINENAME]: LCM:  [ Start  Resource ]  [[File]foo]
VERBOSE: [MACHINENAME]: LCM:  [ Start  Test     ]  [[File]foo]
VERBOSE: [MACHINENAME]:                            [[File]foo] The destination object was found and no action is required.
VERBOSE: [MACHINENAME]: LCM:  [ End    Test     ]  [[File]foo]  in 0.0040 seconds.
VERBOSE: [MACHINENAME]: LCM:  [ Skip   Set      ]  [[File]foo]
VERBOSE: [MACHINENAME]: LCM:  [ End    Resource ]  [[File]foo]
VERBOSE: [MACHINENAME]: LCM:  [ Start  Resource ]  [[Script]dothing]
VERBOSE: [MACHINENAME]: LCM:  [ Start  Test     ]  [[Script]dothing]
VERBOSE: [MACHINENAME]: LCM:  [ End    Test     ]  [[Script]dothing]  in 0.0050 seconds.
VERBOSE: [MACHINENAME]: LCM:  [ Start  Set      ]  [[Script]dothing]
VERBOSE: [MACHINENAME]: LCM:  [ End    Set      ]  [[Script]dothing]  in 0.0060 seconds.
VERBOSE: [MACHINENAME]: LCM:  [ End    Resource ]  [[Script]dothing]
VERBOSE: [MACHINENAME]: LCM:  [ End    Set      ]
VERBOSE: [MACHINENAME]: LCM:  [ End    Set      ]    in  0.0390 seconds.

抛开人为的例子不谈,我怎样才能让脚本资源只有在文件资源实际执行某些操作时才执行?

我的用例是检查远程位置的文件是否已更改,如果是,请将其复制到本地计算机,然后重新启动服务。如果文件没有更改,我显然不想重新启动服务,但我看不到一个好的幂等方法,因为正在使用哈希测试文件 - 我必须拥有我的服务重新启动步骤执行相同的文件哈希检查。

【问题讨论】:

    标签: powershell dsc


    【解决方案1】:

    我认为 DSC 中没有任何原生内置功能可以让一个资源检测“Set-TargetResource”函数是否在同一配置运行中针对不同资源实际执行。

    但是,以下脚本资源可以满足您的需求,但它们使用全局脚本级变量进行通信,因此如果您在单个 DSC 中配置多个服务,它们就会中断。 ConfigureService 脚本资源更新本地配置文件并设置一个标志,RestartService 资源读取该标志以检查是否进行了更改。它有点脏,但它可以工作。

    Script ConfigureService {
        GetScript  = { return $null; }
        TestScript = {
            # compare remote and local file contents and return 
            # $true if they match, or $false if they're different
            $source = "D:\temp\dsctest\source.txt";
            $target = "D:\temp\dsctest\target.txt";
            $isMatch = [System.IO.File]::ReadAllText($target) -eq [System.IO.File]::ReadAllText($source);
            # set a flag for the RestartService resource to read
            $script:serviceChanged = -not $isMatch;
            write-verbose "isMatch = $isMatch";
            return $isMatch;
        }
        SetScript  = {
            # overwrite the local file
            $source = "D:\temp\dsctest\source.txt";
            $target = "D:\temp\dsctest\target.txt";
            $content = [System.IO.File]::ReadAllText($source);
            write-verbose "overwriting config";
            [System.IO.File]::WriteAllText($target, $content);
        }
    }
    
    Script RestartService {
        DependsOn  = "[Script]ConfigureService"
        GetScript  = { return $null; }
        TestScript = {
            write-verbose "serviceChanged = $($script:serviceChanged)";
            return -not $script:serviceChanged;
        }
        SetScript  = {
            # restart the service
            write-verbose "restarting service";
        }
    }
    

    或者,只需将其全部整合到一个资源中。如果您想将其重新用于多个服务,您可以将其移动到成熟的 ServiceConfiguration 自定义资源中。

    Script ConfigureService {
        GetScript  = { return $null; }
        TestScript = {
            # compare remote and local file contents and return 
            # $true if they match, or $false if they're different
            $source = "D:\temp\dsctest\source.txt";
            $target = "D:\temp\dsctest\target.txt";
            $isMatch = [System.IO.File]::ReadAllText($target) -eq [System.IO.File]::ReadAllText($source);
            write-verbose "isMatch = $isMatch";
            return $isMatch;
        }
        SetScript  = {
            # overwrite the local file
            $source = "D:\temp\dsctest\source.txt";
            $target = "D:\temp\dsctest\target.txt";
            $content = [System.IO.File]::ReadAllText($source);
            write-verbose "overwriting config";
            [System.IO.File]::WriteAllText($target, $content);
            # restart the service
            write-verbose "restarting service";
        }
    }
    

    【讨论】:

    • 同意;没有本地方法可以基于另一个资源有条件地执行资源。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2021-01-02
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多