원래이 질문을 받았습니다 : Powershell script for checking AD replication 내 스크립트의 논리를 해결하는 데 도움이되었습니다. 이후 추가 정보와 수표를 스크립트에 추가했으며 최종 결과는 다음과 같습니다.Powershell 스크립트가 로컬 컴퓨터에서 실행되지 않을 때 잘못된 결과를 출력합니다.
function ExitWithCode {
<#
.SYNOPSIS
Specifies custom exit code.
.DESCRIPTION
The ExitWithCode function allows you to pass in a custom exit code
throughout your script by calling the function.
.PARAMETER
Use the -exitcode parameter followed by an integer to specify the error
code
.EXAMPLE
Calling ExitWithCode -exitcode 2 will stop the powershell.exe process
and report an exit code of 2 to the system.
#>
param
(
$exitcode
)
$host.SetShouldExit($exitcode)
exit
}
function Write-Log {
<#
.SYNOPSIS
Write-Log writes a message to a logfile
.DESCRIPTION
The Write-Log function is designed to add logging capability to other
scripts. In addition to writing output and/or verbose you can write to
a log file for later debugging.
#>
[CmdletBinding()]
Param
(
[Parameter(Mandatory = $true,ValueFromPipelineByPropertyName = $true)]
[ValidateNotNullOrEmpty()]
[Alias('LogContent')]
[string]$Message,
[Parameter(Mandatory = $false)]
[ValidateSet("Error", "Info", "Status")]
[string]$Level = "Info",
[Parameter(Mandatory = $false)]
[Alias('LogPath')]
[string]$Path = ('C:\dataloop\ADHealthCheck\ADHealthCheck' + '_' + "$(Get-Date -Format MM-dd-yyyy)" + '.log'),
[Parameter(Mandatory = $false)]
[string]$logFolderPath = 'c:\dataloop\ADHealthCheck\'
)
BEGIN {
[string]$FormattedDate = Get-Date -Format "dd-MM-yyyy HH:mm"
#Test to see if the 'c:\dataloop\ADHealthCheck\' directory exist. If it does not, than create it.
If (-NOT (Test-Path $logFolderPath)) {
Write-Verbose "Creating the folder, $logFolderPath"
New-Item $logFolderPath -Force -ItemType directory
}
#Test to see if the file 'c:\dataloop\ADHeatlhCheck\ADHealthCheck_{current_date}.log' exist. If it does not, than create it.
If (-NOT (Test-Path $path)) {
Write-Verbose "Creating $Path"
[System.IO.FileInfo]$LogFile = New-Item $Path -Force -ItemType file
}
}
PROCESS {
[string]$LogLine = "$FormattedDate - $Level - $message"
$LogLine | Out-File -FilePath $Path -Append
Switch ($Level) {
"Info" {Write-Verbose $LogLine}
"Status" {Write-Output $LogLine}
"Error" {Write-Error $LogLine}
}
}
END {}
}
function Get-ADHealthCheck {
[CmdletBinding()]
param()
BEGIN {
Write-Log "Beginning the AD Health Check..."
}
PROCESS {
#Obtain a list of all the domain controllers and sort them by name in ascedening order
$DCs = Get-ADDomainController -Filter * |sort name
Write-Log "$($DCs.Count) Domain Controllers found" -level Info
#Create an empty array to store object properties later
$results = @()
ForEach ($DC in $DCs) {
Write-Log "Getting replication metadata for $($DC.HostName)" -level Status
#Grab replication metadata for each domain controller. Reports metadata for both inbound and outbound partners
$ReplStatuses = Get-ADReplicationPartnerMetadata -target $DC.HostName -PartnerType Both -ErrorAction SilentlyContinue
If ($ReplStatuses) {
#Reports the number of replication links found for each successful query
Write-Log "$($ReplStatuses.Count) replication links found for $($DC.HostName)" -level Info
ForEach ($ReplStatus in $ReplStatuses) {
#Retrieves the hostname of each partner by splitting the 'Partner' key
$Partner = $ReplStatus.Partner.Split(",")[1].Replace("CN=","")
#create a custom object and set custom properties
$results += [pscustomobject] @{
'Source DC' = $DC.Hostname.ToUpper()
'Partner DC' = (Get-ADComputer $Partner).DNSHostName.ToUpper()
'Direction' = $ReplStatus.PartnerType
'Type' = $ReplStatus.IntersiteTransportType
'Last Attempt' = $ReplStatus.LastReplicationAttempt
'Last Success' = $ReplStatus.LastReplicationSuccess
'Last Result' = $ReplStatus.LastReplicationResult
}
}
}
Else {
#creates a custom object to store information about any domain controller where replication data could not be retrieved
Write-Log "Unable to get replication status for $($DC.HostName)" -level Error
$results += [pscustomobject] @{
'Source DC' = $DC.Hostname.ToUpper()
'Partner DC' = "N/A"
'Direction' = "N/A"
'Type' = "N/A"
'Last Attempt' = "N/A"
'Last Success' = "N/A"
'Last Result' = "N/A"
}
}
}
#Start checking for outdated log files to purge
Write-Log "Cleaning out outdated Log files..."
#Define the log path
$logPath = 'c:\dataloop\ADHealthCheck\'
#Do the actual check based on the log path defined above
$checkLogPath = Get-ChildItem -Path $logPath -Recurse
#Performs check against the log path and returns any files where the last modified date is greater than 14 days
$retentionPeriod = $checkLogPath | Where {$_.LastWriteTime -lt (Get-Date).AddDays(-14)}
foreach ($file in $retentionPeriod) {
if ($retentionPeriod) {
Write-Log "Deleting file $file since it is older than 14 days" -Level Info
#Sets the current working directory to the log path
Set-Location $logPath
#Deletes any files where the modified date is greater than 14 days
Remove-Item $file -Force
}
else {
Write-Log "There were no files older than two weeks. Nothing to delete at this time" -Level Info
}
}
#Check to see if any of the results contain failure
$failedChecks = $results | Where-object{$_.'Last Result' -ne 0}
#Evaluate $failedChecks as a boolean. If there are no failed checks Else can be assumed that everything is fine.
If ($failedChecks) {
Write-Log "These domain controllers have replication errors. Please review them..." -Level Error
$error = $failedChecks | select 'Source DC','Partner DC','Direction' | ft -AutoSize | Out-String
Write-Log $error -Level Error
ExitWithCode -exitcode 2
}
Else {
Write-Log "There were no replication issues found" -Level Info
ExitWithCode -exitcode 0
}
}
}
Get-ADHealthCheck
스크립트에 문제가없는 것으로 보입니다. 테스트 할 서버에서 로컬로 실행하면 모든 것이 작동합니다. 올바른 디렉토리에 올바른 이름의 올바른 로그 파일을 작성합니다. 로그 메시지를 확인하고 모두 체크 아웃합니다.
문제점은 Dataloop/Outlyer에 대한 플러그인으로 스크립트를 포팅하여 특정 서버에서 실행하도록 설정했을 때 스크립트 자체가 Dataloop에 올바른 상태를 출력하지만 스크립트를 실행하는 서버에 원격으로 연결하면 문제가 발생합니다. 내 로그 파일을 검사하면 명령이 성공적으로 실행 되었더라도 모든 오류 메시지가 기록됩니다.
스크립트가 실행되어 로컬에서 올바르게보고되지만 에이전트에 의해 트리거 될 때 모든 잘못된 정보를 기록하는 사람이 이처럼 보입니까? 나는 Dataloop의 지원에 대해서도 알아 보았으나 여기서도 확인해 보았습니다.
서버에서 권한을 부여 할 수 있습니까? 어떤 사용자 컨텍스트가 실패 할 때 실행중인 스크립트입니까? – Bassie
실행 정책을 언급하고 있는지 확실하지 않지만 dataloop의 KB 기사에 따르면 powershell.exe -executionpolicy bypass-file을 사용하여 스크립트를 실행해야하는 powershell 플러그인에 대해 제안합니다. 또한 차이점을 보이지 않는 -noprofile 및 -noninteractive 스위치를 추가하려고 시도했습니다. 서버 중 하나의 현재 실행 정책은 제한되지 않도록 설정됩니다. –
어쩌면 오류 세부 정보가 로그에 기록되는지 게시 할 수 있습니다. 유용한 단서를 제공 할 수 있습니다. – Bassie