powershell invoke-command 更新具有多行内容的文件的内容

powershell invoke-command update contents of a file with multiple lines of content

我需要在多个服务器上的一堆配置文件中更新服务器名称。我有一个快速脚本可以执行此操作,但不想单独登录每个服务器并将脚本本地移动到它 运行 它。所以我正在使用调用命令。一切都在获取文件的内容并更新它,但是当我尝试将新内容写回文件时,我在 Set-Content 上收到 PositionalParameterNotFound 错误。我想是因为它是多线的?

这是遍历文件并尝试将它们写回的代码块:

ForEach($file in $Files){
    $content = Invoke-command -computerName $computerName -ScriptBlock {get-Content $args[0] -raw} -argumentlist $($file.FullName)
    $content = $content -replace $serverRegEx, $newServer
    Invoke-command -computerName $computerName -ScriptBlock {Set-Content -path $args[0] -value "$($args[1])"} -argumentList $($file.FullName) $content
}

如何将此多行内容传回远程命令参数?

我认为您不小心将数组转换为带有“$($args[1])”的字符串。试试这个。

Invoke-Command -ScriptBlock {
    ForEach($file in $using:Files){
        $content = get-Content $file.FullName
        $content = $content %{$_ -replace $serverRegEx,$newServer}
        Set-Content -path $file.FullName -value $content
    }
}

这是一个范围问题。

您不能在没有指定的情况下在远程会话中使用局部变量。这需要 PowerShellv3+ 及更高版本。

示例:

Invoke-Command -ComputerName Server01 -ScriptBlock {
   Write-Output The value of variable a is: $using:a
   Write-Output The value of variable b is: $using:b
}


Get-Help about_remote_variables -Full

About Remote Variables

LONG DESCRIPTION

You can use variables in commands that you run on remote computers. Simply assign a value to the variable and then use the variable in place of the value.

By default, the variables in remote commands are assumed to be defined in the session in which the command runs. You can also use variables that are defined in the local session, but you must identify them as local variables in the command.

USING LOCAL VARIABLES

You can also use local variables in remote commands, but you must indicate that the variable is defined in the local session.

Beginning in Windows PowerShell 3.0, you can use the Using scope modifier to identify a local variable in a remote command.

Invoke-command argumentList 参数接受一个数组,在您第二次使用 Invoke-command 时,您只是将一个参数 ($($file.FullName)) 传递给 argumentList. $content 变量作为单独的参数传递给 Invoke-command,而不是您的脚本块。

通过将您的 2 个参数作为数组传递来解决此问题:

Invoke-command -computerName $computerName -ScriptBlock {Set-Content -path $args[0] -value "$($args[1])"} -argumentList @($($file.FullName),$content)

所以这里的问题真的很简单... -ArgumentList 接受对象数组,但您没有将其作为数组传递。这是您拥有的:

Invoke-command -computerName $computerName -ScriptBlock {Set-Content -path $args[0] -value "$($args[1])"} -argumentList $($file.FullName) $content

据我所知,您对参数的意图如下:

-computerName = $computerName
-ScriptBlock = {Set-Content -path $args[0] -value "$($args[1])"}
-argumentList = $($file.FullName), $content

问题是 $($file.FullName)$content 之间没有逗号,因此它不会将它们视为对象数组,而是将 $($file.FullName) 视为-argumentList 的值,然后将 $content 视为一个单独的对象,它试图将其评估为位置参数,但无法确定它可能是什么位置参数。解决方法是在两项之间加一个逗号:

Invoke-command -computerName $computerName -ScriptBlock {Set-Content -path $args[0] -value "$($args[1])"} -argumentList $($file.FullName),$content