使用自定义函数从invoke命令进行日志记录



我知道这个主题有很多主题,但我找不到解决问题的方法,所以我真的可以使用指导(也许我错过了什么(。

我有一个自定义功能可以将东西写入日志文件:

function Write-Log 
{  
[CmdletBinding()] 
Param 
( 
[Parameter(Mandatory=$true, 
ValueFromPipelineByPropertyName=$true)] 
[ValidateNotNullOrEmpty()] 
[Alias("LogContent")] 
[string]$Message, 
[Parameter(Mandatory=$false)] 
[Alias('LogPath')] 
[string]$Path='C:Scriptsdefault.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

上面的例子只是简单地装载(在计算机2上(一个文件(来自计算机3(并返回其驱动器号(计算机1是脚本运行的地方(。如果我注释掉write-log行,代码就会完美地运行。

我试着应用了很多在线提供的解决方案(比如这个,效果很好,但前提是脚本块只包含函数。如果脚本块有更多的东西,比如我的情况,它就不起作用了(。我得到的最远的方法是让远程计算机将操作记录到C驱动器上的一个新的远程文件,而不是脚本运行的本地文件。

在这个问题上,我真的需要一些帮助和指导。它踢我屁股:(

提前谢谢。

要做你想做的事情,我会将日志函数从本地范围点源到远程,做一些事情,在远程机器上生成日志文件,然后返回到现有会话,并在本地下拉文件。

这是我刚刚想出的一个特别的例子(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:tempremotefunctest.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:tempremotefunctest.txt" -Destination "C:tempsession-copy-test$($session.ComputerName)"

}
# Clean up the sessions
Remove-PSSession $sessions

最新更新