-1

我正在尝试构建一个 powershell 脚本,该脚本从多个系统收集系统正常运行时间信息,然后通过电子邮件发送。我想格式化电子邮件,以便以合理的方式对其进行结构化,然后添加有关系统的更多信息。

今天我有这个脚本,它收集有关系统列表的正常运行时间信息,然后将这些信息以数组的形式传递给 SendMail 函数,该函数将数组包含在电子邮件中。但是当前的输出是这样的。

正常运行时间列表:重新启动 02/19/2013 04:04:52 MyServer01 计算机正常运行时间:23 天 9 小时 重新启动 02/15/2013 04:17:40 MyServer02 计算机正常运行时间:27 天 9 小时

我希望输出或电子邮件文本更像:

系统 | 重启日期/时间 | 正常运行时间
MyServer01 02/17/2013 04:04:52 25 天 9 小时
MyServer02 02/17/2013 04:04:52 25 天 9 小时

如何格式化电子邮件中的文本,或者在将数组传递给电子邮件函数之前是否必须这样做。

脚本本身:

`

function SendMail([string]$arg1){

     #SMTP server name
     $smtpServer = "mysmtp"

     #Creating a Mail object
     $msg = new-object Net.Mail.MailMessage

     #Creating SMTP server object
     $smtp = new-object Net.Mail.SmtpClient($smtpServer)

     #Email structure 
     $msg.From = "my@overtherainbow.ddd"
     $msg.ReplyTo = "noreply@overtherainbow.ddd"
     $msg.To.Add("my@overtherainbow.ddd")
     $msg.subject = "System uptime"
     $msg.body = ("List og servers and uptime:" + $arg1 )

     #Sending email 
     $smtp.Send($msg)}


function CheckUptime($listofservers){
    $k =@()
    foreach($s in $listofservers){
        $Booted = Get-WmiObject -Class Win32_OperatingSystem -Computer $s
        $Calc = [DateTime]::Now - $Booted.ConvertToDateTime($Booted.LastBootUpTime)
        $k +=       "   Restarted " + 
        $Booted.ConvertToDateTime($Booted.LastBootUpTime) +
        " " + $s + " " +
        "    Computer Uptime:   " + 
        $Calc.days + " " +
        "days and", $Calc.hours + " hours"
        }
        return $k
}



#Defining list og servers
$listofservers = "MyServer01", "MyServer02"

#Calling function
$message = CheckUptime($serverlist)
SendMail($message)

`

4

2 回答 2

2

首先,当您的样本甚至不是工作样本时,它几乎不需要付出任何努力。可变错别字等

作为一种解决方案,为什么不为每个服务器创建包含数据的自定义对象并将其作为数组输出?就像是:

PS > function CheckUptime($listofservers){
    $res = @()

    foreach($s in $listofservers){
        $boot = Get-WmiObject win32_operatingsystem -ComputerName $s | % { $_.ConvertToDateTime($_.LastBootUpTime) }
        $uptime = [DateTime]::Now - $boot
        $res += New-Object psobject -Property @{
            Server = (Get-Culture).TextInfo.ToTitleCase($s)
            BootTime = $boot
            Uptime = "{0} days and {1} hours" -f $uptime.Days, $uptime.Hours
        }
    }

    #Output
    $res
}

$myservers = "localhost", "localhost"

$str = "List of servers and uptime:`r`n"

$str += CheckUptime $myservers | Out-String

PS > $str
List of servers and uptime:

Server                            Uptime                           BootTime
------                            ------                           --------
Localhost                         8 days and 6 hours               06.03.2013 09:33:37
Localhost                         8 days and 6 hours               06.03.2013 09:33:37 
于 2013-03-14T14:24:57.727 回答
2

用于Format-Table根据需要格式化数据,并将其通过管道Out-String转换为包含格式化数据的单个字符串。

然后将其附加到您的电子邮件内容中。

这依赖于数据收集,将构建单个字符串替换为构建自定义对象,每个不同列都有单独的字段。

例如(不完整,但应该给你的想法)

$serverData = $serverList | Foreach-Object { GetServerData $_ } | 
   Format-Table Name, 
                @(l='Boot Time'; e={$_.BootTime.ToLocalTime()}},
                @(l='Uptime'; e={FormatUptime([DateTime]::UtcNow - $_.BootTime}} |
   Out-String

$emailBody += $serverData

其中引用的函数已经定义,大致如下:

function GetServerData {
  params([string]$name)

  $os = Get-WmiObject -Class Win32_OperatingSystem -Computer $name
  $bootTimeLocal = $os.ConvertToDateTime($os.LastBootUpTime)

  new-object PSObject -property @{
    Name = $name;
    # Keep everything in UTC to avoid confusion in calcs,
    # TODO FIX: Use the remote machine's timezone for this....
    BootTime = $bootTimeLocal.ToUniversalTime()
  }
}

function FormatUptime {
  params([TimeSpan]$time)

  ...
}

概括:

  • 使用Format-*cmdlet 进行格式化,如果不立即传递给输出(默认Out-Default附加到每个管道的末尾,Out-*没有Out-String.
  • 尽可能长时间地保持数据类型的本机类型。除非必须,否则不要转换为人类可读的形式。因此信息不会丢失。
  • 利用自定义对象和属性(尤其是 NoteProperties)来创建您自己的对象“类型”以将相关信息保存在一起。
于 2013-03-14T14:34:02.703 回答