PowerShell 学习笔记 - 2 PS Module
本章主要探讨 PowerShell 的模块化,由于 PowerShell Core 现版本下已经移植的模块较少以及存在大量强依赖于平台的功能(例如 Hyper-V 相应的管理模块),此处主要依照 Windows PowerShell 实现:
获取模块加载信息 Get-Module
启动一个 mcr.microsoft.com/powershell:centos-7
官方容器可以发现其默认的引入了三个模块,即:
-
Microsoft.PowerShell.Management
和Microsoft.PowerShell.Utility
,用于提供 PowerShell 基本语法实现 -
Script
模块用于提供 PowerShell 具体的运行环境
PS /> $PSVersionTable.OS
Linux 4.9.93-linuxkit-aufs #1 SMP Wed Jun 6 16:55:56 UTC 2018
PS /> Get-Module
ModuleType Version Name ExportedCommands
---------- ------- ---- ----------------
Manifest 6.1.0.0 Microsoft.PowerShell.Management {Add-Content, Clear-Content, Clear-Item, Clear-ItemPropert...
Manifest 6.1.0.0 Microsoft.PowerShell.Utility {Add-Member, Add-Type, Clear-Variable, Compare-Object...}
Script 2.0.0 PSReadLine {Get-PSReadLineKeyHandler, Get-PSReadLineOption, Remove-PS...
同时可以通过为 Get-Module
附加参数 -ListAvailable
以列出可用的 Module,从现版本看有 10 个:
PS /> (Get-Module -ListAvailable).Length
10
反观 Windows 10 Build 17134 上 PowerShell 所拥有的 Module,有 85 个之多:
PS C:\Users\chuny> $PSVersionTable.BuildVersion.Major
10
PS C:\Users\chuny> (Get-Module -ListAvailable).Length
85
但这个问题可以辩证的看,虽然 macOS / Linux 平台上的 PowerShell Core 只拥有少的可怜的基本模块,但得益于 GNU 计划的原生 CLI 工具,实际上并不输 Windows,仍然拿 Hyper-V 模块举例,微软通过提供 PowerShell Hyper-V Module 使能其基于 CLI 的管理功能,开源世界的竞品 QEMU/KVM 等,均通过提供相应的二进制以进行管理,因此 PowerShell Core 在此时只是纯粹的“命令行胶水”,但这不影响其“与原生功能构成平台”的能力。
以基础模块 Microsoft.PowerShell.Utility
为例,所有模块均以 .psd1
的 PowerShell 字典格式存储于文件中,而运行时会根据平台连接到对应的 .Net 实例中:
# Windows
PS C:\Users\chuny> (Get-Module -Name Microsoft.PowerShell.Utility).Path
C:\Windows\system32\WindowsPowerShell\v1.0\Modules\Microsoft.PowerShell.Utility\Microsoft.PowerShell.Utility.psd1
# Linux
PS /> (Get-Module -Name Microsoft.PowerShell.Utility).Path
/opt/microsoft/powershell/6/Modules/Microsoft.PowerShell.Utility/Microsoft.PowerShell.Utility.psd1
# 该字典指向如下递归模块
PS /opt/microsoft/powershell/6> cat /opt/microsoft/powershell/6/Modules/Microsoft.PowerShell.Utility/Microsoft.PowerShell.Utility.psd1 | grep NestedModules
NestedModules="Microsoft.PowerShell.Commands.Utility.dll","Microsoft.PowerShell.Utility.psm1"
# 庐山真面目,即是这个 DLL
PS /opt/microsoft/powershell/6> Get-Item ./Microsoft.PowerShell.Commands.Utility.dll
Directory: /opt/microsoft/powershell/6
Mode LastWriteTime Length Name
---- ------------- ------ ----
------ 9/10/18 8:30 PM 1718784 Microsoft.PowerShell.Commands.Utility.dll
加载/卸载模块 Import/Remove-Module
通过 Get-Command
找到 Microsoft.PowerShell.Core
即 PowerShell Core 对于 Module 一共提供了 4 个 cmdlet,除去用于新建模块的 Add-Module
和上节中的 getter 方法,剩下两个便是加载与卸载:
PS C:\Users\chuny> Get-Command -Noun Module | Where-Object {$_.Source.ToString() -eq "Microsoft.PowerShell.Core"}
CommandType Name Version Source
----------- ---- ------- ------
Cmdlet Get-Module 3.0.0.0 Microsoft.PowerShell.Core
Cmdlet Import-Module 3.0.0.0 Microsoft.PowerShell.Core
Cmdlet New-Module 3.0.0.0 Microsoft.PowerShell.Core
Cmdlet Remove-Module 3.0.0.0 Microsoft.PowerShell.Core
以常见的 TroubleshootingPack
即错误调试工具包模块为例(很遗憾,截至当前 PowerShell Core 还未包含统一的跨平台,且由于 Linux 的崩溃没有一个统一且良好的收集体系,用户态崩溃信息分散且一般不会触发 coredump,因此也很难给出这样的统一排错工具包):
# Windows PowerShell
PS C:\Users\chuny> (Get-Module).Name.Contains("TroubleshootingPack")
False
# 加载模块
PS C:\Users\chuny> Import-Module TroubleshootingPack
PS C:\Users\chuny> (Get-Module).Name.Contains("TroubleshootingPack")
True
# 该模块共提供了两个 cmdlet
PS C:\Users\chuny> (Get-Module -Name TroubleshootingPack).ExportedCmdlets
Key Value
--- -----
Get-TroubleshootingPack Get-TroubleshootingPack
Invoke-TroubleshootingPack Invoke-TroubleshootingPack
PS C:\Users\chuny> (Get-TroubleshootingPack -Path "C:\Windows\diagnostics\system\Apps").RootCauses
Name
----
你已使用临时配置文件登录
用户帐户控制已禁用
需要 Microsoft 帐户
临时 Internet 文件位置已更改
悬挂或崩溃的应用
卸载模块即为反操作:
PS C:\Users\chuny> Remove-Module -Name TroubleshootingPack
PS C:\Users\chuny> (Get-Module).Name.Contains("TroubleshootingPack")
False
实际上,当一个模块还未被引入,直接调用其内部的 cmdlet 时,PowerShell 将完成自动引入的过程,但在脚本制作时应严格禁止这样的默认引入,以避免可能的命名冲突,并在引用前检查目标模块是否可以被引用成功。
**粗体** _斜体_ [链接](http://example.com) `代码` - 列表 > 引用
。你还可以使用@
来通知其他用户。