私はもともとこのスクリプトのロジックを解決するのに役立つこの質問を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