[译] PowerShell Core 6.0 的新增特性

1,724 阅读9分钟

PowerShell Core 6.0 的新增特性

原文 What's New in PowerShell Core 6.0

PowerShell Core 6.0 是开源的,支持跨平台(Windows / macOS 和 Linux)的新版本,其构建目标即为支持异构环境及混合云。

译者注:异构环境 - 由于 PowerShell 最早被设计为运行在 Windows NT / .Net 平台,这里的异构指 *NIX 平台

从 .Net Framework 迁移到 .Net Core

PowerShell Core 使用 .Net Core 2.0 作为其运行时平台,.Net Core 2.0 使 PowerShell 可以被运行于多个平台(Windows / macOS 和 Linux)之上。PowerShell Core 同时向外暴露由 .Net Core 2.0 提供的 API 集合,用于 cmdlet 及脚本中。

Windows PowerShell 使用 .Net Framework 托管 PowerShell 引擎,因此其向外暴露由 .Net Framework 提供的 API 集合。

.NET Core 与 .NET Framework 间 API 的区别被定义为 .Net 标准 中的一部分

For more information on how this affects module/script compatibility between PowerShell Core and Windows PowerShell, see Backwards compatibility with Windows PowerShell.

更多关于此对 PowerShell Core / Windows PowerShell 模块或脚本的兼容性影响可参考 Windows PowerShell 向前兼容性

对 macOS 与 Linux 的支持性

PowerShell 现提供对如下 Linux / macOS 发行版的官方支持,支持范围包含:

  • Windows 7, 8.1, and 10
  • Windows Server 2008 R2, 2012 R2, 2016
  • Windows Server Semi-Annual Channel
  • Ubuntu 14.04, 16.04, and 17.04
  • Debian 8.7+, and 9
  • CentOS 7
  • Red Hat Enterprise Linux 7
  • OpenSUSE 42.2
  • Fedora 25, 26
  • macOS 10.12+

我们的社区同时也提供对如下平台的 PowerShell 发行包,但它们并非被官方支持:

  • Arch Linux
  • Kali Linux
  • AppImage(可用于多个 Linux 平台)

同时我们提供一些实验性的(非正式支持的)发行版用于下列平台:

  • Windows on ARM32/ARM64
  • Raspbian (Stretch)

A number of changes were made to in PowerShell Core 6.0 to make it work better on non-Windows systems. Some of these are breaking changes, which also affect Windows. Others are only present or applicable in non-Windows installations of PowerShell Core.

PowerShell Core 6.0 包含了大量针对非 Windows 平台的修正,其中的部分是断裂性影响,甚至将同时影响 Windows 平台,其余的只出现或被启用在非 Windows 平台的 PowerShell Core 上。

  • 提供对 UNIX 平台的原生命令通配符支持。
  • more 功能采用 Linux 的默认分页器策略,即 less。这代表用户可以在原生二进制/命令间使用通配符(例如,ls *.txt)。
  • 当处理原生命令参数时,行尾的反斜杠符号将被默认忽略。
  • 由于脚本签名功能现在还不能在非 Windows 平台上使用,在非 Windows 平台上 PowerShell 的 -ExecutionPolicy 开关被默认忽略。
  • 修复 ConsoleHost 以使能 UNIX 平台的 NoEcho 功能。
  • 修复 Get-help 以支持 UNIX 平台上非大小写敏感的模式匹配。
  • powershell 于安装包中添加帮助页(man-page)。

日志

于 macOS 中,PowerShell 使用原生的 os_log API 以记录日志于 Apple 统一日志系统中。于 Linux 中,PowerShell 使用 Syslog 这个通用的日志解决方案。

文件系统

一系列更新已被运用于 macOS 与 Linux 平台以支持传统意义上于 Windows 平台上不支持的文件名内字符:

  • 对 cmdlet 输入的路径现已斜杠无感化(slash-agnostic)。即 /\ 均可被用做路径分割符

  • XDG 基本路径规范现已被采纳并被默认开启

    译者注:XDG 基本路径规范 - 即 XDG Base Directory Specification,用于规范操作系统与上层应用对路径名的处理规范

    • Linux / macOS 平台配置文件存在于 ~/.config/powershell/profile.ps1
    • 历史文件存在于 ~/.local/share/powershell/PSReadline/ConsoleHost_history.txt
    • 用户模块路径存在于 ~/.local/share/powershell/Modules
  • 于 UNIX 平台支持包含冒号的文件 / 文件夹名

  • 支持包含逗号的脚本名或路径(感谢 @TimCurwick!)

  • 路径跳转相关的 cmdlet 中支持 -LiteralPath 参数,该参数被声明时,通配扩展将被禁用

  • 升级 Get-ChildItem 使得其工作模式更类似于 UNIX 平台的 ls -R 及 Windows 平台的 DIR /S 命令。Get-ChildItem 现返回递归搜索中遇到的符号链接且不搜索该符号链接对应的路径。

大小写敏感性

Linux 及 macOS 倾向于大小写敏感而 Windows 平台倾向于大小写不敏感,总的来说,PowerShell 使大小写不敏感的。

举例来说,macOS 与 Linux 平台上的环境变量是大小写敏感的,因此 PSModulePath 这样的环境变量已经被预先置为了固定的大小写组合形式。Import-Module 在通过文件路径决定模块名称时,是大小写不敏感的

支持共存(side-by-side)安装

PowerShell Core 的安装 / 配置及执行都与 Windows PowerShell 相隔离。PowerShell Core 存在便携式 ZIP 包,通过该包,用户可以于磁盘上部署任意套 PowerShell Core 并将他们作为其他应用的依赖。共存(side-by-side)安装方案使得对新 PowerShell 版本的测试及存量脚本的迁移更加容易。同时,该方案也可用于对运行于某特定版本的脚本做兼容性配置。

注:默认的,Windows 平台基于 MSI 的安装包将对系统现注册 PowerShell 实例进行替换升级。

powershell(.exe) 重命名为 pwsh(.exe)

PowerShell Core 的执行二进制文件由 powershell(.exe) 更名为 pwsh(.exe)。这一改变使用户可以确定性的运行共存(side-by-side)安装模式下的 PowerShell Core。而且 pwsh 更短也更好记。

其他从 powershell(.exe) 重命名为 pwsh(.exe) 后的改变:

  • 更改第一个位置参数由 -Command-File。这一改变修复了 PowerShell 脚本中的 #! 的使用于非 Windows 平台定向至非 PowerShell shell 的可能性。这也意味着用户可以直接运行脚本,而不用指明 -File 参数,如 pwsh foo.ps1 / pwsh fooScript。同时这也意味着,用户希望运行某命令时必须声明 -Command / -c 入口,如 pwsh.exe -Command Get-Command
  • PowerShell Core 接受 -i/ -Interactive 为开关标识的交互式 shell 模式。这使得 PowerShell 可以在 Unix 平台上被作为默认 shell。
  • pwsh.exe 中移除了 -importsystemmodules / -psconsoleFile 参数
  • 更改了 pwsh -version 以及 pwsh.exe 的内置帮助,以与其他原生工具保持一致。(感谢 @iSazonov!)
  • -File / -Command 错误参数报错信息及退出码与 Unix 标准保持一致
  • 于 Windows 平台增加 -WindowStyle 参数。相似的,非 Windows 平台基于包的 PowerShell 安装将升级已经安装的实例。

于 Windows PowerShell 的向前兼容性

PowerShell 的设计目标之一即为尽量保持与 Windows PowerShell 的向前兼容性。PowerShell Core 使用 .Net Standard 2.0 版本与其他现存 .Net 版本保持汇编兼容性。许多 PowerShell 模块依赖这些 .Net 汇编(有时是 DLL),因此 .Net 标准使得这些模块也可以在 PowerShell Core 上工作。PowerShell Core 也包含自发现功能用以探测知名路径,比如全局汇编缓存(Global Assembly Cache)路径等,以寻找 .NET Framework DLL 依赖。

更多 .NET Standard 相关内容可以通过 .NET Blog 或此 YouTube 视频,或通过该托管于 GitHub 上的 FAQ 了解。

PowerShell Core 为确保其内置模块(如 Microsoft.PowerShell.ManagementMicrosoft.PowerShell.Utility 等)与 Windows PowerShell 保持一致已付出巨大努力。在很多情况下,在社区的协助下,我们已经为这些 cmdlet 添加了新能力以及 Bug 修复。在某些情况下,由于部分 .Net 层次上的依赖缺失,受影响的功能是不可用的或已经被移除。

大部分作为 Windows 组件分发的模块(例如 DnsClient / Hyper-V / NetTCPIP / Storage 等)及其他微软产品,例如 Azure 与 Office 等尚未明确的被移植到 .Net Core 中。PowerShell 团队正在与这些产品的相关团队一同验证并移植这些现存模块至 PowerShell Core With .NET Standard and CDXML,大部分现存的 Windows PowerShell 模块看上去确实可以在 PowerShell Core 中正确使用,但这仍然需要官方验证,因此他们现今也未被完全支持。

通过安装 WindowsPSModulePath 模块,用户也可以通过将 Windows PowerShell PSModulePath 填充至 PowerShell Core PSModulePath 的方式,使用这些模块。

首先,从 PowerShell Gallery 安装 WindowsPSModulePath 模块:

# Add `-Scope CurrentUser` if you're installing as non-admin
Install-Module WindowsPSModulePath -Force

其后,运行 Add-WindowsPSModulePath cmdlet 将 Windows PowerShell 的 PSModulePath 加入到 PowerShell Core 中:

# Add this line to your profile if you always want Windows PowerShell PSModulePath
Add-WindowsPSModulePath

Docker 支持

PowerShell Core 为所有其支持的主流平台(包含多个 Linux 发行版,Windows Server Core 与 Nano Server 等)添加了 Docker 容器镜像。

获取完整列表,请尝试访问 microsoft/powershell on Docker Hub,更详细信息,请查看 GitHub 上的 Docker 相关信息。

基于 SSH 的 PowerShell 远程访问

PowerShell Remoting Protocol(PSRP)除运行于传统的 WinRM 外,现可以工作于 Secure Shell Protocol(SSH)之上。

这代表用户可以通过 Enter-PSSession / New-PSSession 建立基于 SSH 的会话。所有用户需要做的,仅仅是将 PowerShell 注册为基于 OpenSSH 的 SSH Server 的一个子系统,之后便可通过 PSSession 语义层使用传统的 SSH 认证(如密码或私钥等)。

更多关于配置并使用 SSH 基础的远程连接的信息,请参考 PowerShell Remoting over SSH

默认编码格式除 New-ModuleManifest 外设置为没有字节序标识的 UTF-8 编码

在过往版本中,Windows PowerShell cmdlet 例如 Get-Content / Set-Content 使用不同的编码规范,比如 ASCII 及 UTF-16。默认编码上的不同将在混合使用未统一编码格式的 cmdlet 时产生问题。

非 Windows 平台传统上使用没有字节序标识(BOM)的 UTF-8 编码格式作为文本的默认编码格式。更多的 Windows 程序和工具正在从 UTF-16 向没有字节序标识的 UTF-8 编码格式迁移。PowerShell Core 改变了默认的编码格式以适应更广泛的平台。

这代表所有可使用 -Encoding 参数的内置 cmdlet 将默认取值为 UTF8NoBOM。以下的 cmdlet 将被该改动所影响:

  • Add-Content
  • Export-Clixml
  • Export-Csv
  • Export-PSSession
  • Format-Hex
  • Get-Content
  • Import-Csv
  • Out-File
  • Select-String
  • Send-MailMessage
  • Set-Content

这些 cmdlet 也同时获得了升级,因此 -Encoding 参数全局上将采纳 System.Text.Encoding

$OutputEncoding 的默认值也被转变为 UTF-8。

最为最佳实践,用户应当于脚本中明确的通过 -Encoding 参数设置编码类型,以在各个平台上取得可预期的确定性结果。

New-ModuleManifest cmdlet 不具备 -Encoding 参数。通过 New-ModuleManifest 创建的模块配置文件(.psd1)的编码类型由环境决定:如果 PowerShell Core 运行于 Linux 环境中时,那么采用没有字节序标识(BOM)的 UTF-8 编码;否则采用有字节序标识(BOM)的 UTF-16 编码。

支持将流水线通过 & 符号放置于后台

放置 & 符号于一条流水线的尾部将使得该流水线被作为一个 PowerShell Job 运行。当一个流水线被放置于后台时,将返回一个 Job 对象。当一条流水线作为 Job 运行时,所有的标准 *-Job cmdlet 可以被用于管理 Job。变量(忽略进程相关变量)将自动被拷贝到 Job 中,因此 Copy-Item $foo $bar & 可以工作。同时,Job 被运行于当前目录而不是用户的家目录。更多关于 PowerShell Job 的信息请参考 about jobs

语义版本

  • SemanticVersion 兼容 SemVer 2.0。(感谢 @iSazonov!)
  • 改变 New-ModuleManifest 默认的 ModuleVersion0.0.1 以对齐 SemVer 版本。(感谢 @LDSpits!)
  • System.Management.Automation.SemanticVersion 增加 semver 类型加速器
  • 支持比较 SemanticVersion 实例与 Version 实例,当后者仅包含 Major / Minor 两个值时

语言升级

  • 实现 Unicode 转义字符解析,因此用户可以使用 Unicode 字符用于参数、字符串或变量名中。(感谢 @rkeithhill!)
  • 为 ESC 增加新的转义字符
  • 支持将枚举转为字符串。(感谢 @KirkMunro!)
  • 修复转换只包含单个元素的数组至通用集合中出现的问题。
  • .. 运算符增加字符范围重载,因此 'a'..'z' 返回从 az 的字符。(感谢 @IISResetMe!)
  • 修复变量赋值可能复写只读变量的问题
  • 当动态执行脚本中的 cmdlet 时,将本地自动变量作用于转换至 'DottedScopes'
  • 分离运算符支持选择单行、多行选项。(感谢 @iSazonov!)

引擎更新

  • $PSVersionTable 加入四个新属性:
    • PSEdition:于 PowerShell 平台返回 Core,Windows PowerShell 平台返回 Desktop
    • GitCommitId:返回该 PowerShell 版本构建所采取的 git commit id
    • OS:标识操作系统类型,即 [System.Runtime.InteropServices.RuntimeInformation]::OSDescription 的字符串值
    • Platform:标识平台类型,即 [System.Environment]::OSVersion.Platform 的字符串值,于 Windows 平台为 Win32NT,于 macOS / Linux 为 Unix
  • $PSVersionTable 中移除 BuildVersion 属性,该属性强依赖于 Windows 版本,现在可以使用 GitCommitId 以获得精确的 PowerShell Core 构建版本。(感谢 @iSazonov!)
  • $PSVersionTable 中移除 ClrVersion 属性,该属性与 .Net Core 无关,且其保留于 .Net Core 中仅仅作为历史遗留原因且在 PowerShell Core 中不可用
  • 增加三个自动变量以检查 PowerShell 是否运行于某确定的操作系统之上:$IsWindows / $IsMacOs / $IsLinux
  • 增加 GitCommitId 至 PowerShell Core 提示条。现在不再需要通过 $PSVersionTable 获取,而在启动时可以直接得到版本信息。(感谢 @iSazonov!)
  • $PSHome 路径下新增名为 powershell.config.json 的 JSON 格式的配置文件以存储首次运行时的某些配置,如 ExecutionPolicy
  • 当运行 Windows EXE 程序时不阻塞管道
  • 支持枚举 COM 集合

Cmdlet 更新

新 cmdlet

  • Microsoft.PowerShell.Utility 增加 Get-Uptime
  • 增加 Remove-Alias 命令。(感谢 @PowershellNinja!)
  • 增加 Remove-Service 命令用于管理模块。(感谢 @joandrsn!)

Web 相关 cmdlet

  • 为 web 相关 cmdlet 增加证书验证功能。(感谢 @markekraus!)
  • 为 web 相关 cmdlet 增加内容头处理功能。(感谢 @markekraus!)
  • 为 web 相关 cmdlet 增加多链接头部处理支持。(感谢 @markekraus!)
  • 为 web 相关 cmdlet 增加连接头部分页功能。
    • 对于 Invoke-WebRequest,当网络回应包含链接头部,其将建立一个基于字典的 RelationLink 属性以表示 URL 以及 rel 字段间的关系,并确保各个链接均为绝对地址以简化开发。
    • 对于 Invoke-RestMethod,当网络回应包含链接头部,其将暴露一个 -FollowRelLink 开关去自动跟踪下一个 rel 链接直至达到最终的地址或跳次数达到可预设的 ·-MaximumFollowRelLink
  • 为 web 相关 cmdlet 增加 -CustomMethod 参数支持,以支持包含非标准动词的 cmdlet。(感谢 @Lee303!)
  • 为 web 相关 cmdlet 增加 SslProtocol 支持。(感谢 @markekraus!)
  • 为 web 相关 cmdlet 增加多部分包支持。(感谢 @markekraus!)
  • 为 web 相关 cmdlet 增加 -NoProxy 参数支持以使得他们可以忽略系统代理。(感谢 @TheFlyingCorpse!)
  • Web 相关 cmdlet UA 将包含操作系统平台部分。(感谢 @LDSpits!)
  • 为 web 相关 cmdlet 增加 -SkipHeaderValidation 开关,以支持不验证头部值下添加自定义头部
  • Web 相关 cmdlet 可以在需要的情况下不验证服务器 HTTPS 证书
  • 为 web 相关 cmdlet 增加验证参数。(感谢 @markekraus!)
    • 增加 -Authentication 参数,提供三种选项:Basic / OAuth / Bearer
    • 增加 -Token 参数,用于获取 OAuth / Bearer 模式下的令牌。
    • 增加 -AllowUnencryptedAuthentication 参数,用于短路任何非 HTTPS 协议下传输模式的验证功能
  • Invoke-RestMethod 增加 -ResponseHeadersVariable 参数以使能头部数据捕获。(感谢 @markekraus!)
  • 修复 web 相关 cmdlet 以识别非 Success 返回值的 HTTP Response 为异常。
  • 将 web cmdlet UserAgentWindowsPowerShell 移动至 PowerShell。(感谢 @markekraus!)
  • Invoke-RestMethod 增加明确的 ContentType 检测功能。
  • 修复 web 相关 cmdlet 的 -SkipHeaderValidation 参数使其可以兼容含非标准 UA 的 HTTP 包头。(感谢 @markekraus!)

JSON 相关 cmdlet

  • ConvertFrom-Json 增加 -AsHashtable 参数,使其返回值为一个 Hashtable 而不是默认类型。(感谢 @bergmeister!)
  • 美化 ConvertTo-Json 输出。(感谢 @kittholland!)
  • ConvertTo-Json 添加 Jobject 序列化支持。
  • 修复 ConvertFrom-Json 以使其可以反序列化字符串数组形成 JSON 格式的字符串。本项更新修复某些情况下新行符可能意外终止 JSON 解释的问题。
  • 移除 System.Array 中的 AliasProperty "Count" 声明,以去除某些 ConvertFrom-Json 结果中额外产生的 Count 属性。(感谢 @PetSerAl!)

CSV 相关 cmdlet

  • Import-CsvConvertFrom-Csv 增加 PSTypeName 支持。(感谢 @markekraus!)
  • Import-Csv 可支持 CR / LF / CRLF 作为行分隔符。(感谢 @iSazonov!)
  • Export-CsvConvertTo-Csv 增加默认值 -NoTypeInformation。(感谢 @markekraus!)

服务相关 cmdlet

  • Get-Service cmdlet 返回的 ServiceController 对象添加属性:UserName / Description / DelayedAutoStart / BinaryPathName / StartupType。(感谢 @joandrsn!)
  • Set-Service 增加证书设置功能。(感谢 @joandrsn!)

其他 cmdlet

  • Get-ChildItem 增加参数 -FollowSymlink 使其可以提供支持循环引用检测的按需链接遍历功能。
  • 升级 Add-Type 以支持 CSharpVersion7。(感谢 @iSazonov!)
  • 移除 Microsoft.PowerShell.LocalAccounts 模块,由于其使用了已经不支持了的 API,当找到更好的解决方案时会被恢复。
  • 移除 Microsoft.PowerShell.Diagnostics 中的 *-Counter cmdlet,由于其使用了已经不支持了的 API,当找到更好的解决方案时会被恢复。
  • 支持 Invoke-Item -Path <folder>
  • Split-Path cmdlet 提供 -Extension-LeafBase 开关,使用户可以切分路径中的文件扩展名和剩余部分。(感谢 @powercode!)
  • Sort-Object 增加 -Top-Bottom 参数,使其支持对首尾的 N 个项目进行排序
  • 通过向 System.Diagnostics.Process 中增加 CodeProperty "Parent" 以暴露进程的父进程。(感谢 @powercode!)
  • Get-Process 中的内存列使用 MB 为单位,替换原来的 KB
  • Out-String 增加 -NoNewLine 开关。(感谢 @raghav710!)
  • Move-Item 添加 -Include / -Exclude / -Filter 参数。
  • 允许 * 用作 Remove-Item 的注册路径。
  • Get-Credential 增加 -Title 选项,并统一跨平台体验。
  • Test-Connection 增加 -TimeOut 选项
  • Get-AuthenticodeSignature cmdlet 现可以获取文件签名时间戳
  • 移除 Get-Help cmdlet 不主持的 -ShowWindow 开关
  • 修复 Get-Content -Delimiter 使其在返回的数组元素中不包含分界符。(感谢 @mklement0!)
  • ConvertTo-HTML 增加 Meta / Charset / Transitional 选项。(感谢 @ergo3114!)
  • Get-ComputerInfo 返回值添加 WindowsUBRWindowsVersion 属性。
  • Get-Verb 增加 -Group 参数。
  • New-FileCatalogTest-FileCatalog 增加 ShouldProcess 支持(修复 -WhatIf / -Confirm)。(感谢 @iSazonov!)
  • Start-Process cmdlet 增加 -WhatIf 开关。(感谢 @sarithsutha!)
  • 增加 ValidateNotNullOrEmpty 至现存参数

Tab 补全

  • 基于运行时变量值增强 Tab 补全中的类型推断功能。(感谢 @powercode!)这使得如下情况下的 Tab 补全可用:

    $p = Get-Process
    $p | Foreach-Object Prio<tab>
    
  • Select-Object-Property 选项添加哈希表 Tab 补全。(感谢 @powercode!)

  • Select-Object-ExcludeProperty-ExpandProperty 选项参数添加自动补全。(感谢 @iSazonov!)

  • 修复一个 Tab 补全中的 Bug:native.exe --<tab> 调起原生程序自带补全功能。(感谢 @powercode!)

断裂性改变

PowerShell Core 引入了大量断裂性改变,详细内容请参考 PowerShell Core 6.0 中的断裂性改变

调试

  • Invoke-Command -ComputerName 提供远程步进调试(remote step-in debugging)支持
  • 开启绑定式调试日志支持

文件系统更新

  • 支持从 UNC 路径提供的文件系统
  • Split-Path 现在可用于 UNC 根下
  • cd 不带参时,默认行为为 cd ~
  • 修复 PowerShell Core 以使其支持超过 260 字符的文件路径长度

Bug 修复与性能提升

我们已经为 PowerShell 平台配置了大量性能提升,包含对启动时间 / 多种内置 cmdlet 及与原生二进制交互性的优化。

同时,我们也修理了大量的 PowerShell Core 中发现的 Bug,完整列表与更改描述,请参考我们放置于 GitHub 上的 CHANGELOG

感知(数据收集)

  • PowerShell Core 6.0 为运行平台增加了远程感知功能以上报如下参数值:
    • 操作系统平台($PSVersionTable.OSDescription
    • 具体 PowerShell 版本($PSVersionTable.GitCommitId

如果用户希望自愿退出该项感知功能(即:信息收集)只需声明环境变量 POWERSHELL_TELEMETRY_OPTOUT 为如下的一个值:true / 1 /yes。声明该环境变量将忽略所有感知功能,即使于 PowerShell 首次启动时。我们已经计划公开从该项遥感计划中得到的数据和提炼的感知于社区中。你可以从该博客中获得更多详细信息。