设为首页 收藏本站
查看: 2138|回复: 0

利用Powershell在IIS上自动化部署网站

[复制链接]

尚未签到

发表于 2015-8-13 07:46:24 | 显示全部楼层 |阅读模式
  本文主要讲如何通过Powershell在IIS上自动化部署ASP.NET网站,而不涉及Powershell的基本语法,如果没有Powershell基础的同学也可以把本文作为学习Powershell的基石,通过学习本文中的脚本再去查阅具体的语法,可能会达到事半功倍的效果。
  一般我们建立网站大致需要以下几个步骤:
  1、安装.NET Framework
  2、安装了IIS
  3、注册、启用ISAPI和CGI限制
  4、建立网站
  5、设置默认首页、身份验证、设置MIME类型
  6、绑定域名或IP地址
  7、设置权限
  8、设置防火墙入站规则
  功能介绍
  该功能主要是将站点文件夹、Powershell脚本文件、.NET Framework安装程序、Powershell升级程序放在同一个文件夹下,以管理员身份运行脚本文件,脚本自动安装.NET Framework和升级Powershell并将站点文件拷贝到网站目录下,最终建立一个网站。
  接下来我们就讲讲如果通过Powershell实现上面的步骤:
  安装.NET Framework
  首先检查是否已经安装了.NET Framework,如果没有再安装。目前我知道的有两种方式可以判断是否已经安装了.NET Framework,一种是检查注册表,一种是检查安装路径(有点不靠谱),在本文中我将通过注册表来检查是否已经安装了.NET Framework。.NET Framework的注册表路径在“HKLM:\SOFTWARE\Microsoft\NET Framework Setup\”,所以可以通过以下代码来实现:



test-path "HKLM:\SOFTWARE\Microsoft\NET Framework Setup\"

  但是上面的代码只能检查.NET Framework的安装情况,并不知道是安装了哪个版本,所以还需要配合下面的代码:



$version = gci 'HKLM:\SOFTWARE\Microsoft\NET Framework Setup\NDP'| sort pschildname -desc | select -fi 1 -exp pschildname

  gci是Get-ChildItem的缩写,srot是Sort-Object的缩写,可以通过运行Get-Help Get-ChildItem -Detailed来查看该函数的详细信息,其他函数只要替换掉Get-ChilItem就可以了。具体的代码如下所示:



function CheckFramework
{
try
{
$exists = test-path "HKLM:\SOFTWARE\Microsoft\NET Framework Setup\"
if($exists -eq $false)
{
return $false
}
else
{
$version = gci 'HKLM:\SOFTWARE\Microsoft\NET Framework Setup\NDP'| sort pschildname -desc | select -fi 1 -exp pschildname
if($version -ge "v4.0")
{
return $true
}
else
{
return $false
}
}
}
catch
{
Write-Error $_.Exception.Message
}
}
  检查后就是安装.NET Framework,调用安装程序是通过Start-Process函数来实现的,只需找出文件夹下的exe文件,并调用Start-Process函数即可:



Write-Progress "正在安装.NET Framework" "请稍候……"
Get-ChildItem $PSScriptRoot -Filter *.exe | %{start -wait $_ -ArgumentList "/quiet"}
Write-Progress "completed" "completed" -Completed

  Write-Progress是显示进度条信息,$PSScriptRoot是获取当前脚本所在的路径。-ArgumentList参数表示该安装过程是以静默安装的方式进行,如果没有该参数就会显示具体的安装过程。接下来是升级Powershell到4.0版本,因为后面的脚本是基于4.0来写的。
  升级Powershell
  在升级之前同样是先检查Powershell的版本,如果已经是4.0版本了就没有必要再重新更新一次了。升级Powershell的方式跟安装.NET Framework的方式是一样的,只是在升级完成时系统会自动重启以完成升级,也可以在安装后不自动重启,只需在-ArgumentList参数里使用"/quiet /norestart"即可,但是本文中的脚本是会自动重启。如果你的脚本不是基于4.0版本的就可以设置为不自动重启了。那么,如何让系统重启后自动执行当前的脚本呢?你可能会想到注册表,没错,本文就是通过写注册表的方式来实现,如果已经是4.0版本的话就可以用另外一种方式来实现了,具体的代码如下:



#Register-ScheduledJob只能在3.0以后使用
#$scriptPath =  $MyInvocation.ScriptName
#$trigger = New-JobTrigger -AtStartup -RandomDelay 00:01:00
#Register-ScheduledJob -Trigger $trigger -FilePath $scriptPatp -Name UpgradePowershell
$registryValue = "{0}\system32\WindowsPowerShell\v1.0\powershell.exe {1}" -f $env:windir,$MyInvocation.ScriptName
$registryPath = "HKCU:\Software\Microsoft\Windows\CurrentVersion\RunOnce"
$exists = Test-Path $registryPath
if($exists -eq $false)
{
  New-Item $registryPath
}
New-ItemProperty "$registryPath" Upgrade -PropertyType String -Value "$registryValue"
  注释的代码就是另外一种实现方式,但是只能在3.0以后的版本中使用。在HKCU下是没有RunOnce这个项的,所以需要先判断该注册表路径是否存在,在HKLM下的话就有RunOnce路径了。RunOnce表示只会执行一次,执行完后该注册信息就会被删除。
  安装IIS
  在安装调用安装IIS的方法之前需要先使用下面的代码引入ServerManager模块,否则没有办法调用具体的函数:



Import-Module servermanager

  添加功能和角色主要用Add-WindowsFeature -name,name参数是功能或角色的名称,如果不知道具体功能和角色的名称可以用Get-WindowsFeature来获取相关角色或功能的名称:



$features = get-windowsfeature web-*
foreach($item in $features)
{
  if($item.installed -eq $false)
  {
    Write-Host "安装:$item.displayname"
    $item | add-windowsfeature
  }
}
  首先获取以web-开头的所有角色和功能,逐个判断是否已经安装,没有安装的再进行安装。
  注册、启用ISAPI和CGI限制
  在运行注册命令之前先判断是否已经注册,如果注册了判断是否已经启用。在Powershell注册ISAPI和在命令提示符中注册是差不多的,都是要以管理员身份身份运行。如果是直接运行aspnet_regiis.exe的全路径的话,Powershell和cmd中的命令是一样的,即: 



C:\Windows\Microsoft.NET\Framework\v4.0.30319\aspnet_regiis.exe -i

  如果是先切换到aspnet_regiis.exe的目录下,在cmd下可以直接运行aspnet_regiis.exe -i,在Powershell下则需要运行./aspnet_regiis.exe -i,否则Powershell无法识别aspnet_regiis.exe -i命令。通过下面的脚本获取是否已经注册和启用,并赋值给$isapiConfiguration变量:



$isapiConfiguration = get-webconfiguration "/system.webServer/security/isapiCgiRestriction/add[@path='$isapiPath']/@allowed"

  $isapiPath是一个变量,存放isapi的全路径。如果变量$isapiConfiguration等于null的话说明尚未注册isapi,如果变量不等于null,并且$isapiConfiguration.Value等于false的话说明未启用isapi。



#检查系统是否是64bit
function Is64Bit  
{  
[IntPtr]::Size -eq 8
}
#注册或启用ISAPI
function RegisterAndEnableIsapi
{
  $is64Bit = Is64Bit
  $isapiPath=""
  if($is64Bit)
  {
    $isapiPath ="$env:windir\Microsoft.NET\Framework64\v4.0.30319\aspnet_isapi.dll"
  }
  else
  {
    $isapiPath ="$env:windir\Microsoft.NET\Framework\v4.0.30319\aspnet_isapi.dll"
  }
  $isapiConfiguration = get-webconfiguration "/system.webServer/security/isapiCgiRestriction/add[@path='$isapiPath']/@allowed"
  if($isapiConfiguration -eq $null)
  {
    write-host "IIS尚未注册aspnet_isapi.dll"
    $tmpPath=""
    if($is64Bit)
    {
      $tmpPath = "$env:windir\Microsoft.NET\Framework64\v4.0.30319\"
    }
    else
    {
      $tmpPath = "$env:windir\Microsoft.NET\Framework\v4.0.30319\"
    }
    set-location $tmpPath
    .\aspnet_regiis.exe -i
    $isapiConfiguration = get-webconfiguration "/system.webServer/security/isapiCgiRestriction/add[@path='$isapiPath']/@allowed"
  }
  if($isapiConfiguration.Value -eq $false)
  {
    write-host "IIS已经注册过aspnet_isapi.dll,但未启用"
    set-webconfiguration "/system.webServer/security/isapiCgiRestriction/add[@path='$isapiPath']/@allowed" -value true
    if(Is64Bit)
    {  
      set-webconfiguration "/system.webServer/security/isapiCgiRestriction/add[@path='$env:windir\Microsoft.NET\Framework\v4.0.30319\aspnet_isapi.dll']/@allowed" -value true
    }
    Write-Host "isapi已启用"
  }
  else
  {
    write-host "IIS已经注册过aspnet_isapi.dll,且已启用"
  }
}
  创建应用程序池 
  在新建应用程序池和新建网站之前需要先引入“WebAdministration”模块,否则会出现下面的错误:
DSC0000.png
  该模块在2.0版本下是没有的,所以要升级到4.0版本。
  由于我们手动建立网站的时候会自动创建应用程序池,只需要设置应用程序池的相关属性就可以,但用Powershell脚本新建网站的时候是不会自动创建应用程序池的,所以我们需要先创建好应用程序池,在创建网站的时候将其指向到新建的应用程序池。



set-location iis:\AppPools
$existsAppPool = test-path $appPoolName
if($existsAppPool -eq $false)
{
  $appPool = new-item $appPoolName
  #设置标识:LocalService=1;LocalSystem=2;NewworkService=3;ApplicationPoolIdentity=4
  $appPool.ProcessModel.IdentityType=4
  #设置.NET Framework 版本
  $appPool.managedRuntimeVersion="v4.0"
  #设置托管管道模式:集成=0;经典=1
  $appPool.ManagedPipelineMode=0
  $appPool.startMode="AlwaysRunning"
  #设置启用32位应用程序 false=0;true=1
  $appPool.enable32BitAppOnWin64=0
  $appPool | set-item
}
else
{
  write-error "应用程序池已经存在"
}
  创建网站
  因为动态压缩功能只要有安装,在新建网站的时候会自动启用,所以有需要启用动态内容压缩功能的话就需要检查该功能是否已经安装。



#安装动态内容压缩功能
function EnableGZip
{
$check = get-windowsfeature web-dyn-compression
if($check.installed -eq $false)
{
add-windowsfeature web-dyn-compression
}
}
  检查网站目录是否存在,如果不存在就新建一个目录并设置权限,如果要关联的目录不存在的话就会出现下面的错误:




#设置权限
function SetSecurity($name,$path)
{
$acl= get-acl $path
$ar = new-object System.Security.AccessControl.FileSystemAccessRule("$name","ReadAndExecute","ContainerInherit,ObjectInherit","None","Allow")
$acl.SetAccessRule($ar)
set-acl $acl -path $path
}
function CheckDirectory($path)
{
  $existsPath=test-path $path
  if($existsPath -eq $false)
  {
    write-host "【$path】目录不存在,新建该目录"
    new-item -path $path -type directory
  }
  #设置network service用户的权限
  Write-Progress "正在设置目录权限,请稍候……"
  SetSecurity "network service" $path
  SetSecurity "everyone" $path
  Write-Progress "completed" -Completed
}
  $name是“组或用户名”,$path是站点路径。
  将当前文件夹下的站点文件拷贝到站点目录下,由于拷贝文件可能会比较耗时,所以使用了进度条显示拷贝进度,如果不使用进度条的话就只要两条语句就可以完成:



$siteFilePath = (get-childitem $psscriptroot | ?{$_.psiscontainer})[0].fullname
Copy-Item "$siteFilePath\*" $sitePath -Force -Recurse

  使用进度条的方式:



#将脚本文件所在目录下的文件夹下的文件全部拷贝到站点目录下
function CopyFiles
{
$siteFilePath = (get-childitem $psscriptroot | ?{$_.psiscontainer})[0].fullname
$files=Get-ChildItem "$siteFilePath\*"
$count = $files.Length
for($i=0;$i -lt $count;$i++)
{
$copied = $i+1;
Copy-Item $files[$i] $sitePath -Force -Recurse
$percentage = $copied/$count
$msg = "已拷贝:{0:p0}" -f $percentage
Write-Progress -Activity "正在拷贝文件到:【$sitePath】目录" -Status $msg -PercentComplete ($percentage*100)
}
Write-Progress "拷贝结束" -Completed
}

  上述准备工作做完之后就是建立网站了



set-location iis:\sites
if((test-path $siteName) -eq $true)
{
  write-error "站点已经存在";
}
else
{
  #新建站点
  new-website $siteName -physicalpath $sitepath
  #绑定域名
  new-webbinding -name $siteName -host $hostname -port 80 -protocol http
  #获取本机IP
  $ojbItem = Get-WmiObject -Class Win32_NetworkAdapterConfiguration -Filter IPEnabled=TRUE -ComputerName .
  $ipaddress = $ojbItem.IPAddress[0]
  #绑定IP地址和端口
  new-webbinding -name $siteName -ip $ipaddress -port $port -protocol http
  #设置应用程序池
  set-itemproperty $siteName -name applicationpool -value $appPoolName
  #启用Forms身份验证  
  $config = get-webconfiguration system.web/authentication $siteName
  $config.mode="Forms"
  $config|set-webconfiguration system.web/authentication
  #启用匿名身份验证
  Set-WebConfigurationProperty -Filter system.webServer/security/authentication/anonymousAuthentication -PSPath MACHINE/WEBROOT/APPHOST -Location $siteName -Name Enabled -Value $true
} 
  如果有开启防火墙的话还需要添加入站规则



function AddFirewallRule($name,$tcpPorts,$appName = $null,$serviceName = $null)
{
try
{
$fw = New-Object -ComObject hnetcfg.fwpolicy2
$rule = New-Object -ComObject HNetCfg.FWRule
$rule.Name = $name
if ($appName -ne $null) { $rule.ApplicationName = $appName }
if ($serviceName -ne $null) { $rule.serviceName = $serviceName }
$rule.Protocol = 6 #NET_FW_IP_PROTOCOL_TCP
$rule.LocalPorts = $tcpPorts
$rule.Enabled = $true
$rule.Grouping = "@firewallapi.dll,-23255"
$rule.Profiles = 7 # all
$rule.Action = 1 # NET_FW_ACTION_ALLOW
$rule.EdgeTraversal = $false
$fw.Rules.Add($rule)
Write-Host "防火墙入站规则添加成功"
}
catch
{
Write-Error $_.Exception.Message
}
}
  创建虚拟目录的比较简单,但是也需要检查虚拟目录的路径是否存在,设置虚拟目录的权限



new-item "$siteName\$name" -type virtualdirectory -physicalpath $path

  如果有需要还可以添加MIME类型



#添加扩展名 $mime为哈希表类型 如$mimes = @{".a"="application/stream";".b"="application/stream";".c"="application/stream";}
function AddMime($mime)
{
try
{
if($mimes -eq $null -or $mimes.count -le 0)
{
return
}
foreach($item in $mimes.Keys)
{
Write-Host "添加MIME类型:$item"
$extension = get-webconfigurationproperty //staticcontent -name collection | ?{$_.fileExtension -eq $item}
if($extension -ne $null)
{
write-host "该扩展名已经存在"
}
else
{
add-webconfigurationproperty //staticcontent -name collection -value @{fileExtension=$item;mimeType=$mimes[$item]}
}
}
Write-Host "MIME类型添加完成"
}
catch
{
Write-Error $_.Exception.Message
}
}
  测试网站



#请求接口
function GetRequest($url)
{
$request = [System.Net.HttpWebRequest]::Create($url)
$response = [System.Net.HttpWebResponse]$request.GetResponse()
$code = [System.Int32]$response.StatusCode
$response.Close()
$response.Dispose()
Write-Host $code
}

  测试网站是通过调用.NET Framework的相关函数来实现的。
  以上就是用Powershell脚本自动化部署网站的全部过程,可能还有遗落的功能没有实现。如果你对自动化部署网站有兴趣的话可以自己实现一个Powershell脚本。也请各位大牛多多指教,指出本文中的不足和错误的地方。

运维网声明 1、欢迎大家加入本站运维交流群:群②:261659950 群⑤:202807635 群⑦870801961 群⑧679858003
2、本站所有主题由该帖子作者发表,该帖子作者与运维网享有帖子相关版权
3、所有作品的著作权均归原作者享有,请您和我们一样尊重他人的著作权等合法权益。如果您对作品感到满意,请购买正版
4、禁止制作、复制、发布和传播具有反动、淫秽、色情、暴力、凶杀等内容的信息,一经发现立即删除。若您因此触犯法律,一切后果自负,我们对此不承担任何责任
5、所有资源均系网友上传或者通过网络收集,我们仅提供一个展示、介绍、观摩学习的平台,我们不对其内容的准确性、可靠性、正当性、安全性、合法性等负责,亦不承担任何法律责任
6、所有作品仅供您个人学习、研究或欣赏,不得用于商业或者其他用途,否则,一切后果均由您自己承担,我们对此不承担任何法律责任
7、如涉及侵犯版权等问题,请您及时通知我们,我们将立即采取措施予以解决
8、联系人Email:admin@iyunv.com 网址:www.yunweiku.com

所有资源均系网友上传或者通过网络收集,我们仅提供一个展示、介绍、观摩学习的平台,我们不对其承担任何法律责任,如涉及侵犯版权等问题,请您及时通知我们,我们将立即处理,联系人Email:kefu@iyunv.com,QQ:1061981298 本贴地址:https://www.yunweiku.com/thread-98155-1-1.html 上篇帖子: 【翻译】使用IIS 7.0 PowerShell 创建web站点,Web应用,虚拟路径和应用程序池 下篇帖子: Shell编程之正则表达式
您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

扫码加入运维网微信交流群X

扫码加入运维网微信交流群

扫描二维码加入运维网微信交流群,最新一手资源尽在官方微信交流群!快快加入我们吧...

扫描微信二维码查看详情

客服E-mail:kefu@iyunv.com 客服QQ:1061981298


QQ群⑦:运维网交流群⑦ QQ群⑧:运维网交流群⑧ k8s群:运维网kubernetes交流群


提醒:禁止发布任何违反国家法律、法规的言论与图片等内容;本站内容均来自个人观点与网络等信息,非本站认同之观点.


本站大部分资源是网友从网上搜集分享而来,其版权均归原作者及其网站所有,我们尊重他人的合法权益,如有内容侵犯您的合法权益,请及时与我们联系进行核实删除!



合作伙伴: 青云cloud

快速回复 返回顶部 返回列表