Windows PowerShell(以下简称 PowerShell)是微软专门为 Windows 系统管理员设计的命令行壳(Shell)程序。PowerShell 不再像一般的命令行程序接受脚本并返回结果,基于 .NET Framework 的设计让管理员可以在脚本中使用对象并以编程的方式来改变环境。
本场Chat首先会带领大家零基础入门 PowerShell,然后针对日常开发、运维场景介绍 PowerShell 命令,提供可操作的命令及参数组合,方便日常使用。最后将通过一些简单示例演示通过 PowerShell 一键部署环境等。
本场 Chat 您将学到如下内容:
近年来IT行业发展迅速,竞争激烈,软件项目周期越来越短,而项目的规模和复杂度却直线上升。无论是开发运维都充满挑战,软件团队开始采用敏捷、DevOps 等手段提高生产效率,个人方面也开始实施量化和时间管理,期待整体水平的提高。
DevOps 时代,运维与开发一样开始讲求统一、一致、持续、同构等特性,也同样需要被量化和管理。如同软件编程的领域语言,软件设计出现了 UML,我们也期待有工具能在一致性层面解决运维问题。
PowerShell 是微软命令行外壳(Shell)程序和脚本编程环境,因结合了 .NET CLI(公共语言接口)的设计,就拥有了类编程语言的部分能力,如面向对象概念中的类、方法和变量作用域,可以采用面向对象方式来编写脚本。另外PowerShell吸收了近年来流行的模块化设计和包管理的理念,提供编程模型可供第三方软件提供商开发可导入模块,如 MS SQL Server、Office、Azure、Amazon 等都根据自己的软件产品特点,开发了基于 PowerShell 支持的模块,方便了日常开发运维,为自动化提供了丰富的工具。
PowerShell 命令称为 Cmdlet(Command-let),大致为以下结构:
命令 -参数1 参数值1 -参数2 参数值2 ...|管道命令1 ...|管道命令2 ...|...
其组件主要包括:
PowerShell 的命令一般是动名词,如 Remove-Item
, Start-Process
等,功能从字面显而易见。
参数包含两部分:参数名和参数值,参数名代表参数的功能,同时约束了参数值的类型。PowerShell 的参数值类型非常丰富,可以但不限于以下类型:
文本——简单的字符串类型,如路径、名称、ID等
数组——基本类型的数组
列表——这里指无指定类型要求的参数列表,出现的比较少
管道(Pipe)
|
符号在命令行中代表管道,管道的意思是 |
前面的命令行表达式返回值作为 |
后命令行表达式的输入参数。
在 Windows 环境下,可直接在命令行下输入 PowerShell 进入命令行(脚本运行)环境,提示符左边会出现 PS
字样。Mac 环境下可通过安装 PowerShell app 然后点击图标进入。
与 Windows 命令行的命令执行和批处理方式类似,PowerShell 即支持直接运行命令,也执行通过脚本(.ps1)文件编写并于命令行中调用。除此以外部分第三方软件中也支持采用 PowerShell 实现部署及运维操作,我们称之为代码块(Script Block)方式,以下是各种模式的使用场景:
现在我们开始学习 PowerShell,本教程特别适合零基础学员,所有的语句都可随手尝试。不过我要打破一下常规,第一个命令不是输出 Hello,World!
,我们先要了解我们的 PowerShell。
PS > $PSVersionTable
请注意 >
右边才是命令。这是 PowerShell 环境下使用最频繁的系统变量 $PSVersionTable,它会输出你当前 PowerShell 的版本和环境信息,如果你的 PowerShell 版本低于 4,请从微软下载中心更新 PowerShell 软件包。
然后我们来学习如何获得帮助,可能有人会问“搜索”不就行了,不然,想要系统地学习 Cmdlet 获得更多的潜力你需要深入了解每一个你用过的 Cmdlet,我这里会带大家入门,要继续深入学习需要“官方手段”,那就是 PowerShell 标准获得帮助的方法。
Get-Help
:这个命令会给你讲述如何获得帮助,最基本的获得帮助方法如下:
Get-Process -?
:对指定 Cmdlet 问询帮助,直接加 -?
参数,想查询在线帮助?简单,请输入 Get-Help Get-Process -Online
此命令帮助你查询 Get-Process
的在线帮助,网页会直接在浏览器中打开。Get-Help About_Modules
:查看关于模块方面的帮助Get-Help remoting
:查看具有 remoting 关键字的内容对于“实用党”肯定是希望快速找到能“剪切+粘贴”的示例,请用 Get-Help Get-Process -examples
获得示例及相关说明。
最重要的是,如果你感觉你的帮助不是很新,或在开始你的 PowerShell 旅行之前更新一下你的知识库(帮助),请输入 Update-Help -Force
,这个命令会连线更新你所有已安装模块的帮助内容。下面我们就进入动手环境,大家来体验一下玩转 PowerShell 的快乐吧!
命令:
Add-Item C:\FOLDER\TEST.txt
作用: 创建文件,当文件不存在时会创建空文件(0字节文件)。
当文件存在的时候会出现警告信息如下:
new-item : The file 'C:\FOLDER\TEST.txt' already exists.
这时我们一般会有两种选择,第一是强制覆盖,第二则是忽略(不动原来文件)。
强制执行,一般代表着当前行为会执行,结果会改变原状态。对于 New-Item 来说就是用 0 字节文件覆盖原来已经存在的文件,增加强制参数 -Force,很多命令都会有强制执行参数需要时可灵活选择,如下:
Add-Item C:\FOLDER\TEST.txt -Force
作用:即如果存在文件并且有内容,这句命令过后也会被重置为 0 字节的空文件。
如果不想覆盖已经生成的文件,即忽略错误发生继续向下执行或结束,这时我们需要用到参数 ErrorAction 来定义错误发生时的动作即我们想如何处理错误,大多数情况下我们会采用忽略错误继续执行或结束,很多命令你也都会有此参数可灵活实用,如下:
Add-Item C:\FOLDER\TEST.txt -ErrorAction SilentlyContinue
作用:-ErrorAction SilentlyContinue
参数及参数值代表忽略错误继续执行。
命令:
Remove-Item C:\FOLDER\TEST.txt
作用:删除置顶目录的文件。
我们尝试了文件的创建和删除,小伙伴们可能会问,那目录呢?很简单,在上面的两个命令加上 Type 参数并且指定为 Directory 即可进行目录操作:
Add-Item C:\FOLDER -Type Directory Remove-Item C:\FOLDER -Type Directory
作用:添加/删除指定的目录。
上面我们通过命令介绍和动手的方式已经对 PowerShell 命令的执行有了部分了解,下面我们结合项目开发中的例子了解一下 PowerShell 脚本的编写。
假设我们有三个开发环境:开发环境(DEV)、集成测试环境(STG)、生产环境(PROD)。域名分别为 myapp.dev.company.com、myapp.stg.company.com、myapp.company.com(生产环境直接使用最终域名)。
我们采用 ASP.NET 进行开发,其默认配置文件为 web.config,为了不同的环境我们有不同的文件进行对应,如:web.dev.config、web.stg.config 和 web.prod.config,而不同环境中应用的文件夹名字与域名保持一致。
需求是,我们要在部署后使用不同环境的配置文件,即文件替换。
这时我们需要编写脚本,Windows 下的各位有福了,因为 Windows 环境有个 PowerShell 自带的 IDE 环境叫 PowerShell ISE,搜索并打开它就可以进行脚本编辑,它本身包括智能提示和一个位于右下方的 PowerShell 命令运行环境,完成脚本编辑可随时通过点击“运行”按钮执行。(脚本编写和脚本参数问题参加下面的“脚本编写”章节)Mac 同志们也不要太悲哀,找个文本编辑器复制下面脚本并在 PowerShell 命令行环境通过 PS scriptfilename.ps1
的方式运行脚本即可。
然后就让我们在 IDE 环境中尝试以下脚本:
$folder="myapp.dev.company.com" $environment="dev" $source="D:\"+$folder+"\web."+$environment+".config" $destination="D:\"+$folder+"\web.config" Copy-Item $source -Destination $destination
这里我们使用了变量 \$folder
和 \$destination
,做了字符串拼接,然后返回给字符串变量 \$source
和 \$destination
,最后将两个变量作为参数值传递给 Cmdlet 完成脚本。
你可能会问这样不就在脚本中固定了环境?我们可以给我们的脚本传值或者在部署工具如 Octopus 中设置环境变量(也就 是\$folder
和 \$environment
的值),这样就解决了不同环境使用不同的目录和文件的问题。
我们可以使用 Test-Path 命令“测试”目录或文件是否存在。
$if_file_existed = Test-Path "C:\FOLDER\TEST.txt"
然后通过 IF 进行判断,在“存在”和“不存在”两个程序块中填入我们需要执行的代码:
if(!$file_exist) { #不存在的情况 ... } else { #存在的情况 ... }
Windows PowerShell ISE 是 PowerShell 脚本编写的集成开发环境,是上下拆分的窗口结构,上面是脚本编辑区,下面是命令行区,方便实时对脚本运行调试。使用 ISE 的好处还有一个就是它带有智能提示,参数智能列表(包括参数名和参数值枚举)不说,如果参数是文件或目录,还会在参数值输入时自动提示文件夹或文件名,十分方便。
在命令行输入脚本名称要注意使用脚本全路径,所以在部署时首先要保证脚本在当前执行路径或固定路径才好调用。
For($i=0;$i -lt $args.Count; $i++) { Write-Host "parameter $i : $($args[$i])" }
这里的 Write-Host 是输出到控制台,如果向脚本传递了参数,所有的参数会以空格拆分赋值给 \$args
数组,此段代码的作用就是向控制台输出所有的参数。举例我们需要向脚本输入两个参数:
C:\script.ps1 "C:\FOLDER1\TEST.txt" "C:\FOLDER2\TEST.txt"
则如果需要取得"C:\FOLDER1\TEST.txt"和"C:\FOLDER2\TEST.txt",应该使用的变量就是 \$args[0]
和 \$args[1]
。
注册表操作一般用于复杂配置来改变已安装的软件环境,如 Office 配置、Windows 配置等,适合有一定注册表操作经验的开发人员使用,因本专题不是专门的注册表专题,这里直接列出示例代码供参考使用。
首先是删除已存在注册表项(保证不与我们要创建的注册表项冲突)
Remove-Item "HKLM:\SOFTWARE\Classes\AppID\{048EB43E-2059-422F-95E0-557DA96038AF}" -ErrorAction SilentlyContinue
然后是创建注册表项(Out-Null 代表空输出):
$root = "HKLM:\SOFTWARE\Classes\AppID" $appid="{048EB43E-2059-422F-95E0-557DA96038AF}" New-Item -Path $root -Name $appid -Force | Out-Null
最后是给注册表项创建键和值(Key/Value):
$registryPath = "HKLM:\SOFTWARE\Classes\AppID\{048EB43E-2059-422F-95E0-557DA96038AF}" New-ItemProperty -Path $registryPath -Name "(default)" -Value "Microsoft PowerPoint Slide" -PropertyType STRING -Force | Out-Null New-ItemProperty -Path $registryPath -Name "AuthenticationLevel" -Value "1" -PropertyType DWORD -Force | Out-Null
这里要注意注册表项的 PropertyType 参数类型代表着键的数据类型。
验证注册表项:
Get-Item "HKLM:\SOFTWARE\Classes\AppID\{048EB43E-2059-422F-95E0-557DA96038AF}"
示例 2:
$registryPath = "HKLM:\System\CurrentControlSet\Control\Lsa" New-ItemProperty -Path $registryPath -Name "DisableDomainCreds" -Value "0" -PropertyType DWORD -Force | Out-Null
Windows 环境进行 Web 开发就会用到 IIS 服务器,这时我们可能会需要 PowerShell 来为我们自动配置 IIS 站点应用的权限,这里面部分参数值涉及到 IIS Metadata 需要 IIS 相关开发经验或者到微软的网站及进行查询。
首先,引入 ServerManager,注意此包只在服务器版本 Windows 中才有:
Import-Module ServerManager
然后是添加 Feature,类似安装组件:
Add-WindowsFeature Web-Scripting-Tools
导入 Web 管理包:
Import-Module WebAdministration
然后的操作是获取 WebApp1 应用程序池的配置项,将其 IdentifyType 修改为 LocalSystem(0)。
$demoPool = Get-Item IIS:\AppPools\webapp1 $demoPool.processModel.identityType = 0 $demoPool | Set-Item
Windows 下 Web 开发经常需要对 Web App 目录配置 IUSR 权限以让 App 有权限进行文件访问:
$permission="IUSR",,"FullControl,Read,Modify","ContainerInherit,ObjectInherit","None","Allow" $rule = New-Object System.Security.AccessControl.FileSystemAccessRule $permission $folders = Get-Childitem "D:\apps" -Recurse | Where-Object {$_.PSISContainer} Foreach ($folder in $folders) { $path = $folder.FullName $acl = Get-Acl $path $acl.SetAccessRule($rule) Set-Acl $path $acl -ErrorAction SilentlyContinue }
以上代码实现为用户指定要配置的权限 \$permission
,创建访问规则对象 \$rule
,然后遍历文件夹将权限赋予到每个文件夹中。
命令:
invoke-command -scriptblock {iisreset /restart}`
作用:重启 IIS 以加载更新配置
此部分笔者整理了软件安装过程中经常会使用到的脚本:如普通软件安装、MSI 程序包安装、Windows 特性安装、程序包下载、解压缩等。
命令:
Start-Process -FilePath "D:\apps\software\vc14_vc_redist.x64.exe" -ArgumentList "/q /norestart" -Wait
作用:通过安装文件支持的静默安装(quiet installation,一般参数为 /q)或后台安装(background installation)参数等实现软件自动后台安装。
MSI 程序包安装脚本如下:
$install_folder="c:\lab\mysql" $arguments = @( "/i" "c:\lab\mysql.msi" "/qn" "/norestart" ) $arguments+="INSTALLDIR=\`"$install_folder\`"" #install with msi Start-Process -FilePath msiexec -ArgumentList $arguments -Wait
作用:
MSI 程序包可通过 msiexec 程序进行安装,msi 安装包普遍使用一致的安装参数,所以自动化起来更方便。
在很多时候我们需要加载需要的 Windows 特性以支持开发和软件运行,如下例子我们添加所有 ASP.NET Web 应用可能使用到的 Windows 特性:
Install-WindowsFeature -Name Web-Default-Doc, Web-Dir-Browsing, Web-Http-Errors, Web-Static-Content, Web-Http-Redirect, Web-Http-Logging,Web-Stat-Compression, Web-Dyn-Compression, Web-Filtering, Web-Basic-Auth, Web-Net-Ext, Web-Net-Ext45, Web-Asp-Net, Web-Asp-Net45,Web-CGI, Web-ISAPI-Ext, Web-ISAPI-Filter, Web-Mgmt-Console
命令:
Invoke-WebRequest -Uri $download_url -OutFile $destination_folder\$download_filename
作用:
下载 \$download_url
地址中的文件到 \$destination_folder
文件夹下并重命名为 \$download_filename
文件名。也可用于网页、Javascript、CSS 等网页静态资源的保存。
P.S: 对于 github 文件下载可能需要修改 Http 安全协议,在执行下在前执行下面脚本:
[Net.ServicePointManager]::SecurityProtocol = [Net.SecurityProtocolType]::Tls12
命令:
Add-Type -AssemblyName "[system.io.compression.filesystem](http://system.io.compression.filesystem/)" [[io.compression.zipfile](http://io.compression.zipfile/)]::ExtractToDirectory("C:\a.zip","C:\A")
作用:将 C 盘下面 a.zip 文件解压缩到 C:\A 目录。
命令:Start-Service -Name "MariaDB"
作用:一般用于软件安装后自动启动 Windows 服务。
命令:
Write-output "Adding votes to the replicas was successfull" >> $log_file
作用:为了调试脚本我们需要输出一些有助于分析的信息,可以采用 Write-Output 将内容推送到 $log_file
,每次一行形成日志文件。
笔者先要对各位看过说声抱歉,本来是要把所有实际项目中遇到的问题及通过 PowerShell 解决的办法分享出来,但部分解决方案在项目后有了更新的知识,还有一大部分涉及的 PowerShell 功能复杂并不是和新手理解也没办法在短小篇幅中解释清楚,后面我会做一个系列单独对每块有价值的部分详细阐述。对于动手实践,希望各位看官能根据你们开发和运维环境的需求,运用上面的命令实现自己项目中的开发和运维自动化,并来与我讨论,我会竭尽所能地帮助你们解决实际问题,欢迎关注微信公众号“敏捷架构”(minjiejiagou)一起交流学习。
本文首发于GitChat,未经授权不得转载,转载需与GitChat联系。
阅读全文: http://gitbook.cn/gitchat/activity/5b2714cc3130202ab558c687
您还可以下载 CSDN 旗下精品原创内容社区 GitChat App ,阅读更多 GitChat 专享技术内容哦。