我知道这个主题有很多主题,但是我找不到解决问题的方法,因此我可以真正使用指南(也许我遗漏了一些东西)。
我有一个自定义功能,可将内容写入日志文件:
function Write-Log
{
[CmdletBinding()]
Param
(
[Parameter(Mandatory=$true,
ValueFromPipelineByPropertyName=$true)]
[ValidateNotNullOrEmpty()]
[Alias("LogContent")]
[string]$Message,
[Parameter(Mandatory=$false)]
[Alias('LogPath')]
[string]$Path='C:\Scripts\default.log',
[Parameter(Mandatory=$false)]
[ValidateSet("Error","Warn","Info")]
[string]$Level="Info",
[Parameter(Mandatory=$false)]
[switch]$NoClobber
)
Begin
{
# Set VerbosePreference to Continue so that verbose messages are displayed.
$VerbosePreference = 'Continue'
}
Process
{
# If the file already exists and NoClobber was specified, do not write to the log.
if ((Test-Path $Path) -AND $NoClobber) {
Write-Error "Log file $Path already exists, and you specified NoClobber. Either delete the file or specify a different name."
Return
}
# If attempting to write to a log file in a folder/path that doesn't exist create the file including the path.
elseif (!(Test-Path $Path)) {
Write-Verbose "Creating $Path."
$NewLogFile = New-Item $Path -Force -ItemType File
}
else {
# Nothing to see here yet.
}
# Format Date for our Log File
$FormattedDate = Get-Date -Format "yyyy-MM-dd HH:mm:ss"
# Write message to error, warning, or verbose pipeline and specify $LevelText
switch ($Level) {
'Error' {
Write-Error $Message
$LevelText = 'ERROR:'
}
'Warn' {
Write-Warning $Message
$LevelText = 'WARNING:'
}
'Info' {
# If you want to write INFO messages to console, uncomment line below.
#Write-Verbose $Message
$LevelText = 'INFO:'
}
}
# Write log entry to $Path
"$FormattedDate (PID: $PID) $LevelText $Message" | Out-File -FilePath $Path -Append
}
End
{
}
}
我想做的是用invoke-command
远程运行一些命令,我想(本地)记录在远程计算机上完成的一些活动。远程调用的命令的一个示例是:
$DriveLetter = Invoke-Command -ComputerName computer2 -ScriptBlock {
try {
Write-Log "Trying to mount the profile on the remote server..." -Level Info -Path $log_path
$path_to_mount = $args[0] + "\" + $args[1]
$DriveLetter = ((Mount-VHD -Path $path_to_mount -ErrorAction Stop -PassThru| Get-Disk | Get-Partition | Get-Volume).DriveLetter)+":"
Write-Log "Profile mounted to $DriveLetter" -Level Info -Path $log_path
return $DriveLetter
}
catch [Microsoft.HyperV.PowerShell.VirtualizationException] {
Write-Host "Profile is mounted." -ForegroundColor Red
Write-Log "Profile is mounted." -Level Error -Path $log_path
} -ConfigurationName ConnectUPD -ArgumentList $sourceDir,$upd_file -ErrorAction Stop
上面的示例只是(从computer3)挂载(在computer2上)一个文件并返回其驱动器号(在script1所在的计算机上)。如果我注释掉write-log
行,则代码将完美运行。
我尝试应用了许多在线提供的解决方案(例如this,该解决方案可以正常工作,但前提是脚本块仅包含函数。如果脚本块包含更多内容,例如我的情况)工作)。 我最想得到的是让远程计算机记录操作,但记录到C驱动器上的新远程文件中,而不是脚本运行的本地文件中。
我真的需要一些有关此问题的帮助和指导。它踢了我的屁股:(
谢谢。
答案 0 :(得分:0)
要做您想做的事情,我将把日志功能从本地作用域点源到远程,进行处理,在远程计算机上生成日志文件,然后再返回到现有的会话,然后在本地下拉文件。
这是我刚想到的一个特别示例(SO的语法突出显示不喜欢块注释,因此请原谅不足)
# Function creation, screw foo, I use banana
function banana()
{
# to let you know that the function is working
Write-Host "From function"
# creates a file to copy
New-Item -Path "C:\temp\remotefunctest.txt" -Force
}
# This creates an object that is a representation of the function in string form
# this is what we'll dot source from within the invoke's scope
$myFunction = "function banana {${function:banana}}"
# list of your machines
# for simplicity I just built a string array, you can use whatever method you deem best
[string[]]$listOfComputerNames = @("machine1","machine2")
# Empty session array instantiation
[System.Management.Automation.Runspaces.PSSession[]]$sessions = @()
# iterate through machine names and creates sessions, adding them to the sessions array
foreach($name in $listOfComputerNames)
{
$sessions += New-PSSession -ComputerName $name # add -Credential if needed
}
# Will invoke your commands against the persistent sessions,
# instantiating the function, and running said function,
# which creates the file for you
Invoke-Command -Session $sessions -ScriptBlock {
# This will create a new ScriptBlock object,
# then use dot sourcing to run that scriptblock inside the current scope.
# It's the exact same functionality as copy-pasting the entire function
# into the invoke command
. $([scriptblock]::Create($using:myFunction))
# this is calling the function
banana
Write-Host "From invoke"
}
# This will iterate through the $sessions array,
# copy the designated file via Copy-Item's
# fancy schmancy -FromSession parameter,
# then place that file in a folder that is
# named after the name of the remote machine.
foreach($session in $sessions)
{
# With the -FromSession ParameterSet,
# -Path is the file path on the REMOTE machine to copy the file FROM
# -Destination is the file path on the LOCAL machine to copy the file TO
Copy-Item -FromSession $session -Path "C:\temp\remotefunctest.txt" -Destination "C:\temp\session-copy-test\$($session.ComputerName)\"
}
# Clean up the sessions
Remove-PSSession $sessions