PowerShell 技能连载 - 使用“Exit”和 Linux 通信
当一个 PowerShell 脚本结束时,您可以使用“Exit
”命令来返回一个数值。这在 Windows 世界中是一个很好的实践。它能够设置“Error Level”值,并能够被调用者(例如一个批处理文件或是定时任务管理器)读取到。
1 | exit 99 |
既然 PowerShell 在 Linux 上也可以运行,它也可以用来报告调用 Linux 进程的状态值。
当一个 PowerShell 脚本结束时,您可以使用“Exit
”命令来返回一个数值。这在 Windows 世界中是一个很好的实践。它能够设置“Error Level”值,并能够被调用者(例如一个批处理文件或是定时任务管理器)读取到。
1 | exit 99 |
既然 PowerShell 在 Linux 上也可以运行,它也可以用来报告调用 Linux 进程的状态值。
如果您在 Linux 上运行 PowerShell,您可以混合使用 Linux 命令和 PowerShell 命令。要将 Linux 命令的输出赋值给 PowerShell 变量,请像这样写:
1 | $content = (ls) |
请注意“ls
”在 Windows 系统上是一个别名,但在 Linux 系统上指向的是原始的 ls 命令。
Test-Path
可以检测一个文件或文件夹是否存在。如果您添加了 -PathType
来指定叶子节点(文件),或 -Container
(文件夹),结果会更具体:
$path = 'c:\windows'
Test-Path -Path $path
Test-Path -Path $path -PathType Leaf
Test-Path -Path $path -PathType Container
有些时候,您可能会需要不同的度量单位。例如整个系统的内存是以字节计算的。以下是一些将字节转换为 GB 并且仍然保证可读性的例子:
1 | $memory = Get-WmiObject -Class Win32_ComputerSystem | |
结果看起来类似如下:
15.8744087219238
16
16
15.9
15.9 GB
您可以用 New-TimeSpan
来定义时间的“量”,然后对某个日期增加或减少这个量。以下是一个例子:
1 | $1Day = New-TimeSpan -Days 1 |
更简单的办法是使用 DateTime
对象的内置方法:
1 | $today = Get-Date |
您也可以使用 TimeSpan
.NET 类来创建 time span 对象:
1 | PS C:\> [Timespan]::FromDays(1) |
有时候,一个 PowerShell 脚本需要等待外部进程结束。以下是一些用户的做法:
1 | $processNameToWaitForExit = 'notepad' |
这种做法不太理想,因为它至少等待了一秒钟,即便进程已经不在运行了。以下是一个更好的方法:
1 | $processNameToWaitForExit = 'notepad' |
不仅代码更短,Wait-Process
也支持超时时间。如果等待的时间过长,您可以通过超时时间来结束等待。
如果您设置了 PIN 用来登录您的电脑,对您自己的机器使用 PowerShell remoting 可能会失败,提示如下奇怪的错误信息:
1 | PS C:\> Invoke-Command { "Hello" } -ComputerName $env:computername |
要解决这个问题,您可以有两个选择:
Invoke-Command
的时候使用 -Credential
参数,然后指定账户和密码。如果您使用 PowerShell 远程操作来接收远程机器的信息,您可以指定多个计算机名(扇出)。PowerShell 会自动逐台访问所有的机器,这样可以节省很多时间(当然,这些操作的前提是设置并启用了 PowerShell,这里不再赘述)。
返回的结果顺序是随机的,因为所有被访问的机器都会在它们准备好数据的时候返回各自的信息。
要将结果数据按每台机器分割,请使用 Group-Object
命令:
1 | $pc1 = $env:computername |
当您指定了 -AsHashTable
参数时,Groutp-Object
创建了一个以计算机名为键的哈希表。通过这种方法,您可以并发执行操作以节约时间,并仍然按每台机器来区分数据。
用 Group-Object
可以基于共享的属性值对对象分组,但请不要忘记使用 -NoElement
参数来忽略实际的对象而只返回出现次数。
这行简单的代码告诉您指定文件夹中有哪些文件类型:
1 | Get-ChildItem -Path c:\Windows -File | Group-Object -Property Extension -NoElement |
结果看起来如下:
1 | Count Name |
指定了 -NoElement
之后,您可以节约相当客观的内存,因为原对象不再包括在结果中。
Cmdlet 和函数只能用认可的动词以便于用户查找命令,并且保持一致性。
以下是一个快速的审计代码,能够显示不符合这个规定的所有命令:
1 | $approved = Get-Verb | Select-Object -ExpandProperty Verb |
这里返回的是所有不符合规定或根本没有命令动词的 cmdlet 和函数。