Я сделал скрипт для проверки статуса ИБП, регистрации его и отправки уведомлений по электронной почте. Скрипт работает нормально, если он запускается вручную, но при выполнении через планировщик задач он не отправляет электронную почту. Хотя он делает все остальное (например, правильно записывает в файл), поэтому я не понимаю, что происходит.

Любой намек и / или объяснение? Большое спасибо!

Вот сценарий:

<#
.SYNOPSIS
Skript pro test stavu napájení (AC, nebo UPS)
.DESCRIPTION
Zjistí stav napájení, a pokud to není AC, ale baterie, pole notifikační e-mail. Stejně tak ho pole, pokud ádná baterie připojena není.
.PARAMETER none
no parameters
.EXAMPLE
no example needed
.NOTES
crysman (copyleft) 2016
# changelog:
# ...         next version - don't forget to update the $scriptVersion variable!
# 2016-03-10  přidány barvy výstupů, help, upraveny exit codes a návratové hodnoty, upraven hostname
# 2016-03-09  opraveno logování, vč. loggingu nefunkčních mailnotifikací
# 2016-03-08  initial release
#>
$scriptVersion = '2016-03-10'
$scriptName = $MyInvocation.mycommand.name
$timestamp = [datetime]::now.tostring("yyyy-MM-dd_HH-mm")
$hostName = [system.environment]::MachineName.ToLower()


#funkce pro posílání notifikačních mailů
#v.1.2
function sendEmail($Subject, $Body){
  $EmailTo = "it@XXXYOURFAVOURITEDOMAIN.cz"
  $EmailFrom = "$global:hostName@XXXYOURFAVOURITEDOMAIN.cz"
  $SMTPServer = "smtp.XXXYOURFAVOURITEDOMAIN.cz"
  $SMTPClient = New-Object Net.Mail.SmtpClient($SMTPServer, 587)
  $SMTPClient.EnableSsl = $true
  $SMTPClient.Credentials = New-Object System.Net.NetworkCredential("notifications@XXXYOURFAVOURITEDOMAIN.cz", "XXXYOURFAVOURITEPASSWORD");
  $Body = "$Body `n-----`nscript $global:scriptName v.$global:scriptVersion on host $global:hostName`ntimestamp: $global:timestamp"
  #Write-Host $EmailTo $EmailFrom $Subject $Body
  try {
    $SMTPClient.Send([string]$EmailFrom,[string]$EmailTo,[string]$Subject,[string]$Body)
  }
  catch {
    $msg = "$global:timestamp WARNING: notification e-mail has NOT been sent, please check SMTP credentials"
    Write-Host "ERR: " $Error[0].ToString() -ForegroundColor Red
    #následující řádek nefunguje - proč? :( - do souboru se zapisuje, ale na screen ne!
      #Write-Output $msg | Tee -Append -FilePath $global:errorLog
    Write-Host $msg -ForegroundColor Red
    Write-Output $msg | Out-File -Append $global:errorLog
    return $false
  }
  finally {
    $SMTPClient.Dispose()  
  }
  Write-Host "notification e-mail has been sent succesfully" -ForegroundColor Gray
  return $true
}

$scriptDir = "D:\scripts"
$log = "$scriptDir\checkPowerUPS-error.log"
$errorLog = $log


# kategorie stavů baterie viz https://msdn.microsoft.com/en-us/library/aa394074(v=vs.85).aspx
$bStats= @{"1"="battery is discharging";"2"="On AC";"3"="Fully Charged";"4"="Low";"5"="Critical";"6"="Charging";"7"="Charging and High";"8"="Charging and Low";"9"="Charging and Critical";"10"="Undefined";"11"="Partially Charged";} 

# aktuální stav:
$powerStat=Get-WmiObject -class Win32_Battery -ComputerName localhost
$bStat=$powerStat.BatteryStatus
$bStatText=$bStats["$bStat"]
$bStatRemaining=$powerStat.EstimatedRunTime

#zapíeme do EventLogu, popř. poleme mail
#nachystat EventLog
$eLog = $scriptName #pouijeme název skriptu
if (! $eLog) {
  Write-Output "$timestamp něco je patně s powershellem (?)" | tee -Append -FilePath $log
  exit 99  
}
$eLogExists = get-EventLog -LogName Application -Source "$eLog"
if (! $eLogExists){
  echo "WARNING: jetě neexistuje eventlog, vytvářím..."
  new-EventLog -LogName Application -Source "$eLog"
}
#zalogovat a notifikovat
if (!($powerStat) -or $bStat -eq 1 -or $bStat -eq 4 -or $bStat -eq 5) { 
  if(!$powerStat){
    #(nemáme UPS)
    $Subject = "IMPORTANT: Power without UPS on $hostName"
    $Body = "this host seems NOT to be connected to any battery/UPS"
  } else {
    #(UPS máme, ale nějaký non-AC status)
    $Subject = "IMPORTANT: Power failure on $hostName"
    $Body = "battery status is $bStat ($bStatText), estimated remaining battery time: $bStatRemaining min"
  }
  #vypsat na screen a zalogovat:
  Write-Output "$timestamp $Body" | Out-File -Append $log
  Write-Host "$timestamp $Body" -ForegroundColor Red
  Write-EventLog -LogName Application -Source "$eLog" -EntryType Warning -EventId 11 -Message "$eLog skončil neúspěně - $Body"
  #poslat maila:
  $mailsent = sendEmail $Subject $Body
  if ($mailsent) {$exitcode=1} else {$exitcode=2}
} else {
  $exitcode = 0
  Write-Host "OK, $hostName is on AC (status $bStat)`nscript $scriptName v.$scriptVersion" -ForegroundColor Green
}
exit $exitcode

Вот задача:

<Task xmlns="http://schemas.microsoft.com/windows/2004/02/mit/task" version="1.2">
<RegistrationInfo>
<Date>2016-03-07T16:53:24.9000439</Date>
<Author>SERVER-XXX\myadminaccount</Author>
</RegistrationInfo>
<Triggers>
<CalendarTrigger>
<Repetition>
<Interval>PT1M</Interval>
<StopAtDurationEnd>false</StopAtDurationEnd>
</Repetition>
<StartBoundary>2016-03-07T00:00:00</StartBoundary>
<Enabled>true</Enabled>
<ScheduleByDay>
<DaysInterval>1</DaysInterval>
</ScheduleByDay>
</CalendarTrigger>
</Triggers>
<Principals>
<Principal id="Author">
<UserId>SERVER-XXX\myadminaccount</UserId>
<LogonType>Password</LogonType>
<RunLevel>HighestAvailable</RunLevel>
</Principal>
</Principals>
<Settings>
<MultipleInstancesPolicy>StopExisting</MultipleInstancesPolicy>
<DisallowStartIfOnBatteries>false</DisallowStartIfOnBatteries>
<StopIfGoingOnBatteries>true</StopIfGoingOnBatteries>
<AllowHardTerminate>true</AllowHardTerminate>
<StartWhenAvailable>true</StartWhenAvailable>
<RunOnlyIfNetworkAvailable>false</RunOnlyIfNetworkAvailable>
<IdleSettings>
<StopOnIdleEnd>true</StopOnIdleEnd>
<RestartOnIdle>false</RestartOnIdle>
</IdleSettings>
<AllowStartOnDemand>true</AllowStartOnDemand>
<Enabled>true</Enabled>
<Hidden>false</Hidden>
<RunOnlyIfIdle>false</RunOnlyIfIdle>
<WakeToRun>false</WakeToRun>
<ExecutionTimeLimit>PT1H</ExecutionTimeLimit>
<Priority>7</Priority>
</Settings>
<Actions Context="Author">
<Exec>
<Command>powershell</Command>
<Arguments>
-NonInteractive -Noprofile -Command "&{D:\scripts\checkPowerUPS.ps1}"
</Arguments>
</Exec>
</Actions>
</Task>

Операционная система: Windows Server 2012 R2

PS: я просмотрел и Technet, и различные сайты Stack Exchange, чтобы решить эту проблему, но не повезло:/ Так что пробую здесь ...

1 ответ1

1

После часов отладки я понял.

Эта проблема:

использование -Command "..." в планировщике заданий.

Решение:

Вместо этого используйте аргумент -File "..." . В данном конкретном случае это будет:

<Exec>
<Command>powershell</Command>
<Arguments>
-NonInteractive -Noprofile -File "D:\scripts\checkPowerUPS.ps1"
</Arguments>
</Exec>

Подробности:

При использовании -Command "&{D:\testScript.ps1}" глобальные переменные, объявленные в сценарии, недоступны, то есть, например, это не будет работать:

$myVar = "ham"
function myF(){
  Write-Output $global:myVar
}
myF

Я не нашел ответ на мой баг решенных-вопрос: « В чем разница между -Command и -File PowerShell аргументом?" Вызывая powershell /? мне все равно не поможет, потому что он ничего не говорит о глобальных и / или любых "полуглобальных" переменных. Более того, он утверждает, что используя -Command:

...Выполняет указанные команды (и любые параметры), как если бы они были введены в командной строке Windows PowerShell ...

Это не так, потому что запуск нового окна PowerShell и выполнение строк, которые я поместил в приведенном выше примере кода с помощью $ myVar, будет работать, тогда как выполнение примера с -Command ... будет.

Я надеюсь, что это поможет вам.

Всё ещё ищете ответ? Посмотрите другие вопросы с метками .