PowerShell 学习笔记 - 3 使用 cmdlet
本章主要探讨 PowerShell 中 cmdlet 的使用方法,单独拿出这一部分正是为没有 UNIX Shell 经验的同学设计的,例如必须参数与非必需参数以及筛选技巧等。
cmdlet 命令行参数
以 Get-Process
为例,于 PowerShell Core Docker 容器中运行会得到如下的结果:
PS /> Get-Process
NPM(K) PM(M) WS(M) CPU(s) Id SI ProcessName
------ ----- ----- ------ -- -- -----------
0 0.00 99.55 1.61 1 1 pwsh
同时对比 ps
命令的输出结果,发现他们均可以得到对着同一个进程的描述:
PS /> ps aux |grep -v ps
USER PID %CPU %MEM VSZ RSS TTY STAT START TIME COMMAND
root 1 0.1 4.9 3204676 101356 pts/0 SLsl+ Sep18 0:01 pwsh
Linux 系统附加的 ps
是一个功能输入过于复杂的程序反例,很大程度上违反了 UNIX 设计哲学中的 小即是美,以其可以接受的命令行参数为例:
This version of ps accepts several kinds of options:
1 UNIX options, which may be grouped and must be preceded by a dash.
2 BSD options, which may be grouped and must not be used with a dash.
3 GNU long options, which are preceded by two dashes.
它直接支持 UNIX / BSD / GNU
三种风格的参数,且其帮助手册 man ps
对其语法的描述为:
SYNOPSIS
ps [options]
因为支持的参数形式实在太多,很难写的详细。这样做的初衷因为描述一个进程的维度太多,而 UNIX 管道传递的是字符串,ps
才提供大量正交的功能用以描述进程的方方面面,反观 PowerShell 中的面向对象理念,获取的进程对象可以通过管道传递给下一个 cmdlet 用以操作:
# Get-Process 返回结果为一个 System.ComponentModel.Component 类型的对象
PS /> (Get-Process).GetType()
IsPublic IsSerial Name BaseType
-------- -------- ---- --------
True False Process System.ComponentModel.Component
# Get-Process 返回的对象拥有 93 个属性
PS /> (Get-Process -Id 1 -IncludeUserName | Get-Member).Length
93
因此 Get-Process
中的语法部分也相当简单(WIndows PowerShell 上面要复杂的多),只进行 getter 函数的功能:
SYNTAX
Get-Process [[-Name] <string[]>] [-Module] [-FileVersionInfo] [<CommonParameters>]
Get-Process [[-Name] <string[]>] -IncludeUserName [<CommonParameters>]
Get-Process -Id <int[]> [-Module] [-FileVersionInfo] [<CommonParameters>]
Get-Process -Id <int[]> -IncludeUserName [<CommonParameters>]
Get-Process -InputObject <Process[]> -IncludeUserName [<CommonParameters>]
Get-Process -InputObject <Process[]> [-Module] [-FileVersionInfo] [<CommonParameters>]
该版本下默认给出了6种用法,这样的标准语法描述与 UNIX Shell 是相同的,即:
- 未直接包被 - 用户可选择加上该参数,这常会触发必须参数或非必须参数
-
[]
- 非必需参数 -
<>
- 必须参数
以其中一条为例:
# Get-Process -Id <int[]> -IncludeUserName [<CommonParameters>]
# -Id 为用户可选,后必须加 Id 构成的数组
# -IncludeUserName 为用户可选
# [<CommonParameters>] 代表常规参数
# -id 后不附加参数提示 Specify a parameter of type 'System.Int32[]' and try again. 即缺少参数
PS /> Get-Process -Id
Get-Process : Missing an argument for parameter 'Id'. Specify a parameter of type 'System.Int32[]' and try again.
At line:1 char:13
+ Get-Process -Id
+ ~~~
+ CategoryInfo : InvalidArgument: (:) [Get-Process], ParameterBindingException
+ FullyQualifiedErrorId : MissingArgument,Microsoft.PowerShell.Commands.GetProcessCommand
# 附加参数即可
PS /> Get-Process -Id 1
NPM(K) PM(M) WS(M) CPU(s) Id SI ProcessName
------ ----- ----- ------ -- -- -----------
0 0.00 99.84 2.24 1 1 pwsh
# -IncludeUserName 是非必选的
PS /> Get-Process -Id 1 -IncludeUserName
WS(M) CPU(s) Id UserName ProcessName
----- ------ -- -------- -----------
99.85 2.26 1 root pwsh
Select-Object
与格式化输出
上文已经提到 PowerShell 管道传递的是对象,那么如何基于对象去生成输出,则需要借助管道与 Format-*
cmdlet 族,仍以 Get-Process
为例,显示全部属性即为借助 Format-List
将通过管道传递的进程对象展开为 List:
# 结果较长截取前几项
PS /> Get-Process -Id 1 | Format-List *
Name : pwsh
Id : 1
PriorityClass : Normal
FileVersion :
HandleCount : 119
WorkingSet : 107376640
PagedMemorySize : 0
PrivateMemorySize : 0
...
进一步的筛选属性等则可以通过 Select-Object / select
完成,例如从对象中选取某些字段生成新的对象:
# 选取部分属性
PS /> Get-Process | select -Property PM,CPU
PM CPU
-- ---
0 6.11
# 通过 Select-Object 将对象依属性筛选
PS /> Get-Process | select -Property PM,CPU | Get-Member
TypeName: Selected.System.Diagnostics.Process
Name MemberType Definition
---- ---------- ----------
Equals Method bool Equals(System.Object obj)
GetHashCode Method int GetHashCode()
GetType Method type GetType()
ToString Method string ToString()
CPU NoteProperty System.Double CPU=6.1
PM NoteProperty long PM=0
同时,select
还支持模拟 Linux 下的 head / last
的作用:
# 生成列,类似于 seq 1 10 的效果
PS /> 1..10
1
2
3
4
5
6
7
8
9
10
# Head
PS /> 1..10 | select -First 2
1
2
# Tail
PS /> 1..10 | select -Last 2
9
10
结合 Sort-Object
等,可进一步的完成基本的文本排序筛选功能:
# 生成一个包含 10 个随机数的数组
PS /> $array = foreach ($n in 1..10)
>> {
>> Get-Random
>> }
# head / tail
PS /> $array | select -First 3
850010005
1643404153
1052124830
PS /> $array | select -Last 3
1845560963
1964683853
153356516
# sort
PS /> $array |Sort-Object | select -Last 3
1845560963
1934390288
1964683853
# 按属性排序
PS /> Get-Module -ListAvailable | select -Property Version, Name| Sort-Object -Property Version
Version Name
------- ----
0.0 PSDesiredStateConfiguration
1.1.0.0 Microsoft.PowerShell.Archive
1.1.2 ThreadJob
1.1.7.2 PackageManagement
1.6.7 PowerShellGet
2.0.0 PSReadLine
6.1.0.0 Microsoft.PowerShell.Host
6.1.0.0 Microsoft.PowerShell.Management
6.1.0.0 Microsoft.PowerShell.Security
6.1.0.0 Microsoft.PowerShell.Utility
关于用于生成格式化输出的 Format-*
cmdlet 家族,请参考 Get-Help
中的相关内容,并不需要特别的背记,随用随查就可以了。