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