PowerShell实战指南 Chapter 3-7
你说彼岸灯火,心之所向;后来渔舟晚唱,烟雨彷徨。
Chapter 3 使用帮助系统
由于其他平台上的PowerShell功能没有Windows上完整,所以在未加特别说明的情况下,后面的截图等均基于Windows平台。
系统版本:
PowerShell版本:
- 输入参数名时只需输入能区分它的前缀即可
- 可选参数:参数名和参数值均在中括号内
- 必选参数
- 定位参数:参数名在中括号内,而参数值在小括号内(参数值必选),不必输入参数名,参数值的位置正确即可
建议刚开始一直输入参数名。
先执行括号里的命令:
Get-EventLog Application -computer (Get-Content names.txt)
# about 主题也有很多信息
help about*
# 如查看关于数组的内容
help Arrays
help about_core_commands
# 可以帮助查找有哪些可能有用的命令,比如找关于进程的
Get-Command *Process*
像下面这样的语法描述,即这个命令适应三种不同的语法规则(参数组合)。你输入的命令应该符合其中一种:
Chapter 4 运行命令
- Cmdlet 是原生PowerShell命令行工具
- 函数与其类似,但不是以.Net编写,而是以PowerShell自己的脚本语言编写
- 工作流是嵌入PowerShell的工作流执行系统的一类特殊函数
- 应用程序是任意类型的外部可执行程序(原cmd命令基本都可用)
Get-Verb
查看可用动词:
PS /Users/rambo> Get-Verb
Enable e Lifecycle Configures a resource to an available...
Verb AliasPrefix Group Description
---- ----------- ----- -----------
Add a Common Adds a resource to a container, or attaches an item to another item
Clear cl Common Removes all the resources from a container but does not delete the container
Close cs Common Changes the state of a resource to make it inaccessible, unavailable, or unusable
Copy cp Common Copies a resource to another name or to another container
Enter et Common Specifies an action that allows the user to move into a resource
Exit ex Common Sets the current environment or context to the most recently used context
Find fd Common Looks for an object in a container that is unknown, implied, optional, or specified
Format f Common Arranges objects in a specified form or layout
Get g Common Specifies an action that retrieves a resource
...
PowerShell允许开发人员自己命名名词。
使用New-Alias
创建自定义别名,其生命周期为当前Shell。所以如果以后要使用,则需要Export-Alias
。
Show-Command Get-Process
以GUI方式显示命令的用法:
- 显示最新的100个应用程序日志
Get-Eventlog -LogName Application -Newest 100
Chapter 5 使用提供程序
这一章的内容较为抽象。简略来说,文件系统、环境变量、PowerShell本身的变量、PowerShell的函数等等这些东西被抽象成Drives
,而PSProvider
作为访问这些数据介质的适配器。它向PSDrive
提供服务。用户则使用Cmdlet
去操作PSDrive
呈现的数据。
我画了张图来表达自己对上面这些概念的理解(不一定对):
对于数据介质的一个更高级的抽象是“项”(Item)。无论文件系统中的文件、文件夹,还是注册表中的项,在PowerShell都被视为“项”。(注意,注册表和文件系统具有相同的分层结构)这样一来,为数据的访问和操作提供了统一的术语。而相关的Cmdlet
也往往是包含Item
字符的:
Get-Command -Noun *Item*
所以,在PowerShell的cd
或者Set-Location
具有了更广泛的含义,它不仅仅是像传统命令行或Bash那样切换工作目录,甚至可以从文件系统切换到注册表中。
一般每个项都有其属性。如文件夹:
再如注册表键:
但有的PSProvider
并不具有项属性,如Environment
:
Get-PSProvider
Get-PSDrive
访问注册表并修改值:
最后别忘了改回默认值。
大部分Cmdlet
都包含-Path
,且默认情况下支持通配符。如果不希望自己输入的?*
被当作通配符,可以使用-LiteralPath
代替。
Chapter 6 管道:连接命令
格式化输出结果
输出结果到CSV (Comma-Separated Values):
Get-Process | Export-Csv procs.csv
相比直接在命令行中显示的内容,很明显输出到文件的内容更丰富。
之后可以在别处把procs.csv
导入到PowerShell进行查看:
Import-Csv procs.csv | more
注意,与Get-Content
相比,Import-Csv
会去解析它的格式,以更有序的形式展示出来。
另外也可以导出为XML
:
Get-Process | Export-Clixml procs.xml
还有其他的各种导出导入:
还有一个对比功能蛮有趣:
Compare-Object
或者diff
Compare-Object -ReferenceObject (Import-CliXML procs.xml) -DifferenceObject (Get-Process) -Property Name
=>
表示不存在于ReferenceObject
的进程,<=
表示不存在于DifferenceObject
的进程。另外注意小括号()
的妙用。
输出到文件或打印机
dir > x.txt
这种写法是为了向后兼容。实际上它是以管道实现:dir | Out-File x.txt
(Out-file
默认一行80列)。
输出到HTML
Get-Process | ConvertTo-Html | Out-File procs.html
注意,ConvertTo-
意味着只转换,不存储。Export
则还会自动帮你存储。但是如果接下来还要用管道处理数据,那么ConvertTo
更方便。
修改系统
Get-Process -Name notepad | Stop-Process
这个例子想要说明的是,带有相同名词(如上面的Process
)的Cmdlet
可以在彼此之间传递信息。
像Stop-
这种会修改系统的命令,都有impact level
,这些level
是不可修改的。同时,PowerShell有一个全局的$ConfirmPreference
:
如果命令的level
大于等于全局的,则PowerShell会问你是否确定要这么做。当然,你也可以强制它每次问你一下,即使命令的level
小于全局的:
-Confirm
会询问,-WhatIf
会告诉你将发生什么。
我们之前有提到PSProvider
。再次看一下这张图片:
其中,带有ShouldProcess
的PSProvider
支持-WhatIf
和-confirm
参数。
另外,Filter
指的是其支持-Filter
参数;Credentials
指的是“允许使用可变更的凭据连接数据存储。”,即-Credentials
参数;Transactions
说明其支持事务(即原子操作)。
Chapter 7 扩展命令
由于本章需要的某些模块在之前使用的Windows Server 2008中不存在,故本章采用如下版本的Windows Server 2012 R2
和PowerShell
:
本章学习PowerShell的两种扩展:
- 管理单元
- 模块
首先是管理单元。它类似于插件。这种方式正逐渐被微软遗弃。它使用的主要命令是:
Get-PSSnapin
Add-PSSnapin
深入学习模块:
模块不需要注册。PSModulePath
定义了PowerShell期望存放模块的路径,路径下的模块会自动被查找:
(图中两个路径分别存放系统和个人的模块)
另外,PSModulePath
不能在PowerShell中修改,需要到系统环境变量中修改。
测试:
首先移除所有模块:
之后查找一下network
相关命令,可以发现还是可以找到,即使你没有加载那个模块。PowerShell会为你自动发现和加载:
如果模块不在前面的路径下,那么需要手动导入:Import-Module
。
插件和模块都可以添加PSDrive
,所以在加载之后你可以使用Get-PSProvider
查看新添加了哪些。
注:如果加载多个模块,其中包含相同命令,那么在使用命令时需要加上模块或插件前缀。例如:
MyCoolPowerShellSnapin\Get-User
小实验:清除DNS缓存
首先查看一下有哪些命令可以用:
发现很多都来自DnsClient
模块。我们手动加载一下这个模块试一下(其实没有必要):
试一下Clear-DnsClientCache
:
Es klappt!
使用配置脚本
这个类似于Shell的profile
,这里的主要目的是帮你自动加载插件和模块。
- 在用户的
Documents
目录下新建目录WindowsPowerShell
- 在其中新建文件
profile.ps1
- 在刚刚的文件中输入
Add-PSSnapin
和Import-Module
,一行一个命令的格式来加载插件和模块 - 在PowerShell中修改执行策略(需要管理员身份)
Set-ExecutionPolicy RemoteSigned
- 关闭当前PowerShell并重启
动手实验:运行网络故障诊断包
用Get-Command
搜索network
没有找到有用的。看了英文版的题目才知道“网络故障诊断包”是Networking troubleshooting pack
,那就找一下trouble
吧:
Got it!
但是一开始不太会用这个东西,看一下帮助:
这个好像是声音相关的。那我看一下那个目录下都有什么:
太棒了。
然后把它传给Invoke-
:
不过,这个功能略鸡肋啊。
补充知识
注:在线教程。
交互式
基本C语言中的算术运算符在这里都能用。另外0xdeadbeef
这种十六进制也可以用。同时,它还能识别tb/gb/mb/kb
,如1gb
:
通过字符串执行外部程序:
通过Get-Command | gm
查看命令集的类型(目前我的环境上有三种):
- System.Management.Automation.AliasInfo
- System.Management.Automation.FunctionInfo
- System.Management.Automation.CmdletInfo
通过函数来将带有常用参数的命令扩展为别名:
function test-conn { Test-Connection -Count 2 -ComputerName $args}
注意,$args
为占位符。
执行VBS脚本:
cscript.exe .\test.vbs
Powershell调用入口的优先级
- 别名:控制台首先会寻找输入是否为一个别名,如果是,执行别名所指的命令。因此我们可以通过别名覆盖任意powershell命令,因为别名的优先级最高。
- 函数:如果没有找到别名,会继续寻找函数,函数类似别名,只不过它包含了更多的powershell命令。因此可以自定义函数扩充cmdlet 把常用的参数给固化进去。
- 命令:如果没有找到函数,控制台会继续寻找命令,即cmdlet,powershell的内部命令。
- 脚本:没有找到命令,继续寻找扩展名为“.ps1”的Powershell脚本。
- 文件:没有找到脚本,会继续寻找文件,如果没有可用的文件,控制台会抛出异常。
默认的安全设置禁止执行脚本:
变量
定义变量
- 不需要显式声明
- 可以自动创建变量
- 字母不区分大小写
- 变量的前缀为$
- 几乎可以把任何数据赋值给变量,一切都是对象
- 交换两变量的值非常简单
以上特性可以参照下图:
变量被存放在Variable
的Drive
中:
验证变量是否存在:
(这与验证文件是否存在一样,关于原理可以参考Chapter 5 使用提供程序)
PowerShell提供5个管理变量的命令:
- Clear-Variable
- Remove-Variable
- Set-Variable
- Get-Variable
- New-Variable
后两个比较有用。比如:
- 创建只读变量
- 创建常量
通过help about_scope
可以详细了解。
自动化变量
自动化变量是那些一旦打开Powershell就会自动加载的变量:
可以通过
help about_Automatic_Variables
深入了解。
环境变量
关于环境变量:
借助.Net
方法,可以使用户设置的环境变量在系统级别生效:
[environment]::SetEnvironmentvariable("myPath", ";c:\powershellscript", "User")
驱动器变量
可以通过${PATH}
直接访问文件内容(其实这也是一切皆为“项”的体现):
甚至函数也可以:
$()
子表达式: