Windows Server Core 管理与 PowerShell 笔记(九)———— PowerShell 面向对象脚本语言

2019-04-07 966 Words Windows Powershell

Windows Server Core 管理与 PowerShell 笔记(九)———— PowerShell 面向对象脚本语言

前面的几篇文章都是使用 PowerShell 作为主要交互脚本。在这些命令的使用过程中,已经初步体验到了面向对象的脚本语言于传统的基于文本的脚本语言的区别。这篇文章中将综合介绍 PowerShell 的一些知识和面对对象的部分。

一、 变量、环境变量

1.1 基本用法

变量全部以 $ 开头,用等号赋值。没有特殊的声明语句。例如:

PS C:\Windows\system32> $a = 1
PS C:\Windows\system32> $b = "Hello,World"
PS C:\Windows\system32> $a
1
PS C:\Windows\system32> $b
Hello,World

所有的变量全部存储在 Variable: 驱动器中。因此我们可以使用于导航文件目录一样的命令来管理变量。比如:

PS Variable:\> Test-Path Variable:a # 查找变量是否存在
True
PS Variable:\> Remove-Item Variable:b # 删除变量

1.2 PowerShell 自动化变量

下面这些变量在命令运行的过程中自动赋值:

  • \$\$ 上一个命令最后一个参数
  • $^ 上一个命令第一个参数
  • $? 上一个命令执行结果
  • $Error 错误数组
  • $Home 家目录
  • $Host 当前主机对象
  • $PID 当前进程ID
  • $Profile 当前配置文件位置

等等

1.3 环境变量

所有的环境变量都由 $env:name 构成,比如:

PS C:\> $env:OS
Windows_NT
PS C:\> $env:PATH
C:\Windows\system32;C:\Windows;C:\Windows\System32\Wbem;C:\Windows\System32\WindowsPowerShell\v1.0\;C:\Windows\System32\OpenSSH\;C:\Users\ertuil\AppData\Local\Microsoft\WindowsApps
PS C:\> $env:a = 123
PS C:\> $env:a
123

所有的变量全部存储在 Env: 驱动器中。因此我们可以使用于导航文件目录一样的命令来管理变量。比如:

PS C:\Windows\system32> Remove-Item env:a # 删除环境变量 a

值得注意的是,这些环境变量都只在当前 PowerShell 上下文中修改,如果需要永久修改,需要使用 .net 的接口:

PS> [environment]::SetEnvironmentvariable("Path", ";c:\powershellscript", "User")
PS> [environment]::GetEnvironmentvariable("Path", "User")

二、别名(alias)

PowerShell 使用别名机制来继承 CMD 和 Shell 的命令。比如 wget 是 Invoke-WebRequest 的别名。这些别名可以降低我们的学习成本。

PS C:\Windows\system32> Get-Alias ls # 查询某个别名

CommandType     Name                                               Version    Source
-----------     ----                                               -------    ------
Alias           ls -> Get-ChildItem

PS C:\> Set-Alias -Name list -Value get-childitem # 新建别名或者修改别名
PS C:\> New-Alias -Name "List" Get-ChildItem # 新建别名

所有的别名都在 Alias:虚拟驱动器中。进入这个驱动器之后,也可以用文件操作来修改和查看所有的别名。

三、PowerShell 数组、哈希表和对象

3.1 数组

PowerShell 可以建立数组和哈希表,当命令执行结果返回多个对象时,也会以数组的形式返回结果。

PS C:\Windows\system32> $num = 1,2,3 # 创建数组
PS C:\Windows\system32> $a1 = 1..5 # 1 到 5 创建数组
PS C:\Windows\system32> $a2 = "Hello","World",1 # 不一定同一类型
PS C:\Windows\system32> $a3 = @() # 空数组
PS C:\Windows\system32> $as -is [array] # 判断类型
False
PS C:\Windows\system32> $a2.Count # Count 属性用来获取数组长度
3

PS C:\Windows\system32> $a2[1] # 获取某一个元素
World
PS C:\Windows\system32> $a2[0,2] # 获取多个元素
Hello
1
PS C:\Windows\system32> $a2 += 2 # 添加元素
PS C:\Windows\system32> $a4 = $a2.Clone() # 数组是引用类型,深拷贝需要使用 Clone 函数

3.2 哈希表

哈希表类似 Python 的字典,操作也非常类似。

PS C:\Windows\system32> $h1 = @{a = 1;b = 2; c = "hi"} # 创建哈希表
PS C:\Windows\system32> $h1

Name                           Value
----                           -----
c                              hi
b                              2
a                              1

PS C:\Windows\system32> $h2 = @{} # 建立空表
PS C:\Windows\system32> $h1.a = 2 # 修改元素
PS C:\Windows\system32> $h1.Remove("b") # 删除键值对

3.3 对象

对象是 PowerShell 的核心实现。下面给出了简单介绍:

PS C:\Windows\system32> $o1 = New-Object object # 建立对象

PS C:\Windows\system32> Add-Member -InputObject $o1 -Name a -Value "1" -MemberType NoteProperty # 添加属性

PS C:\Windows\system32> Add-Member -InputObject $o1 -Name b -Value {"123"} -MemberType ScriptMethod # 添加方法

PS C:\Windows\system32> $o1.b() # 调用方法
123

PS C:\Windows\system32> Get-Member -InputObject $o1 # 获取属性

   TypeName:System.Object

Name        MemberType   Definition
----        ----------   ----------
Equals      Method       bool Equals(System.Object obj)
GetHashCode Method       int GetHashCode()
GetType     Method       type GetType()
ToString    Method       string ToString()
a           NoteProperty string a=1
b           ScriptMethod System.Object b();

每一个对象默认都有四个方法:

  • Equal 判断对象是否相等
  • GetHashCode 获取对象哈希值
  • GetType 获取对象类型
  • ToString 转化为字符串

四、PowerShell 常用处理函数

PowerShell 的管道(“|”)用于将前一个命令输出的对象,输入到下一个命令中。以此为基础产生了通用的但是多样化的数据处理流程。与 Linux 基于文本的 Shell 中的 awk 、sed、grep、sort 等类似,这里的操作函数全都是操作对象。以此构建了对象流。

4.1 Out-Host 和 Read-Host

Out-Host 用于将对象转换成字符串,并打印出来。默认最后一个命令输出的对象将会自动套接这个函数,并输出到控制台。于此类似的还有:

  • Out-Default 默认方式输出(默认是 Out-Host)
  • Out-File 输出到文件
  • Out-Null 丢弃输出
  • Out-Printer 输出到打印机
  • Out-String 输出字符串
  • Out-GridView 发送到单独窗口的交互表中

此外,还可以使用 Export-Csv 到处成 CSV 文件。而 Import-Csv用于导入一个 CSV 并转化为对象。 ConvertTo-CsvConvertFrom-Csv 用于 CSV 与对象之间互相转换。 ConverTo-Html 则可以到处成 Html 文件。

Read-Host 用于读取键盘输入,-AsSecureString 参数用于按照密码的方式读取。

4.2 格式化对象

有四个函数 Format-List, Format-Table, Format-Wide, Format-Custom。用于将对象格式化成数组、表格、宽列表和自定义。一般前两个较为常用,表格显示的较为整齐,而列表显示的信息更多,下面的例子给出了区别:

PS C:\Windows\system32> Get-EventLog -List |Format-Table # 格式化成表格

  Max(K) Retain OverflowAction        Entries Log
  ------ ------ --------------        ------- ---
  20,480      0 OverwriteAsNeeded         483 Application
  20,480      0 OverwriteAsNeeded           0 HardwareEvents
     512      7 OverwriteOlder              0 Internet Explorer
  20,480      0 OverwriteAsNeeded           0 Key Management Service
     512      7 OverwriteOlder                Parameters
  20,480      0 OverwriteAsNeeded       2,133 Security
     512      7 OverwriteOlder                State
  20,480      0 OverwriteAsNeeded       2,537 System
  15,360      0 OverwriteAsNeeded           0 Windows PowerShell

PS C:\Windows\system32> Get-EventLog -List |Format-List # 格式化成列表


Log                  : Application
EnableRaisingEvents  : False
MaximumKilobytes     : 20480
MinimumRetentionDays : 0
OverflowAction       : OverwriteAsNeeded

Log                  : HardwareEvents
EnableRaisingEvents  : False
MaximumKilobytes     : 20480
MinimumRetentionDays : 0
OverflowAction       : OverwriteAsNeeded

Log                  : Internet Explorer
EnableRaisingEvents  : False
MaximumKilobytes     : 512
MinimumRetentionDays : 7
OverflowAction       : OverwriteOlder

...

这些 Format 函数后面可以加上列的名字,表示只显示这些列的属性,比如:

PS C:\Windows\system32> Get-EventLog -List |Format-Table Log # 只显示 Log 这一列

Log
---
Application
HardwareEvents
Internet Explorer
Key Management Service
Parameters
Security
State
System
Windows PowerShell

4.3 分组、排序、测量和比较

命令 Group-Object(alias: group) 用于将命令分组。其后可以接一个用于分组的属性名称或一个表达式,例如:

PS C:\Windows\system32> Get-Service | Group-Object Status # 按 Status 分组

Count Name                      Group
----- ----                      -----
  136 Stopped                   {AJRouter, ALG, AppIDSvc, AppMgmt...}
   72 Running                   {Appinfo, BFE, BrokerInfrastructure, camsvc...}

PS C:\Windows\system32> Get-Process | Group-Object { $_.WS -ge 1mb} # 按照 WS 是否大于 1mb 分组

Count Name                      Group
----- ----                      -----
   91 True                      {System.Diagnostics.Process (ChsIME), System.Diagnostics.Process (conhost), System.D...
    3 False                     {System.Diagnostics.Process (Idle), System.Diagnostics.Process (spaceman), System.Di...

Sort-Object 用来排序,后面接用于排序的属性名,参数 -Descending 表示降序排列。比如:

PS C:\Windows\system32> Get-Process |Sort-Object CPU -Descending # 按照 CPU 使用降序排列

Handles  NPM(K)    PM(K)      WS(K)     CPU(s)     Id  SI ProcessName
-------  ------    -----      -----     ------     --  -- -----------
   1887       0      192        116     221.64      4   0 System
    658      40   160180     229496      51.58    376   1 dwm
    375      30    10152      43944      32.63   2244   1 conhost
    587      59   136484      84956      30.75   1872   0 MsMpEng
    653      37   174004     193408      21.97   1100   1 powershell
    382      22     9444      23120      20.98   3024   0 vmtoolsd
...

命令 Measure-Object 用于测量一个属性的最小值(Minimum)、最大值(Maximum)、平均值(Average)、求和(Sum)等。比如:

PS C:\Windows\system32> Get-Process | Measure-Object CPU -Average -Minimum -Maximum -Sum

Count    : 94
Average  : 5.57247340425532
Sum      : 523.8125
Maximum  : 221.78125
Minimum  : 0.015625
Property : CPU

命令 Compare-Object 用于比较两个对象(类似 diff)。这里不再给出例子。

4.4 筛选

Select-Object 用于筛选对象。有如下一些属性可以灵活搭配:

  • -Property 筛选有这些属性的对象
  • -Last n 最后的 n 个
  • -First n 开头的 n 个
  • -Unique 唯一的
  • -Index a,b 位于 a,b 之间的
  • -Skip n 跳过 n 个

Where-Object 后面接表达式,利用表达式进行筛选,比如:


PS C:\Windows\system32> Get-Process | Where-Object {$_.CPU -gt 20} # 筛选出大于 20s 的。

Handles  NPM(K)    PM(K)      WS(K)     CPU(s)     Id  SI ProcessName
-------  ------    -----      -----     ------     --  -- -----------
    371      30    10592      42512      35.11   2244   1 conhost
    650      40   159268     227660      53.58    376   1 dwm
    593      59   136772      86732      31.47   1872   0 MsMpEng
    771      37   154796     174928      24.31   1100   1 powershell
   1890       0      192        116     222.11      4   0 System
    382      22     9440      23116      21.39   3024   0 vmtoolsd

命令 Get-Unique 用于将对象不重复的输出。

PS C:\Windows\system32> $a1 = 1,1,1,2,2,2,3
PS C:\Windows\system32> $a1 |Get-Unique | ft # 输出不重复元素
1
2
3

4.5 ForEach-Object

ForEach-Object 方法将会遍历所有的对象,然后按照参数对每一个对象进行操作。这个命令非常类似于 awk 脚本,它有:

  • -Begin 后接开始脚本
  • -End 结束脚本
  • -Process 处理脚本
  • -RemainingScripts 保留脚本

例子:

PS C:\>$Events = Get-EventLog -LogName System -Newest 1000 
PS C:\>$events | ForEach-Object -Begin {Get-Date} -Process {Out-File -Filepath Events.txt -Append -InputObject $_.Message} -End {Get-Date}

这个命令是非常通用的命令,可以完成对对象的绝大部分操作。

五、总结

这部分只大致介绍了 PowerShell 在实际使用中常用到的部分知识,对于真正面对对象部分、流程控制和细节部分都没有涉及。更多具体知识点可以参见: https://www.pstips.net/powershell-online-tutorials

至此,我们已经介绍了 PowerShell 管理 Windows 的绝大部分基础知识。下面将会将重心转向提供网络服务的方向。主要包括 Hyper-V 虚拟机、Containers 容器化、DNS 服务器搭建、IIS 的 web 和 ftp 服务器搭建、Dhcp 服务器搭建、Active Directory 域控等。