如何确保在Powershell中完全停止IIS网站?

时间:2016-05-09 16:24:21

标签: powershell iis

我有一个Powershell脚本可以停止IIS网站和相应的应用程序池,然后删除应用程序日志(log4net日志)。这是脚本片段:

stop-website -name "MyWebsite"
stop-webapppool -name "MyWebsite"
del c:\inetpub\MyWebsite\logs\*.*

问题是stop-website和stop-webapppool似乎在网站完全关闭之前返回,这导致删除失败,说该文件正由另一个进程使用:

  

del:无法删除项目C:\ inetpub \ MyWebsite \ logs \ App.log:进程无法访问文件“C:\ inetpub \ MyWebsite \ logs \ App.log”,因为它正由另一个进程使用。

如果我在stop命令和del命令之间添加10秒的睡眠,则会成功删除日志。这是非常hackish但不可靠。有没有办法强制stop-website / stop-webapppool命令在网站/ apppool完全停止之前不返回?

感谢。

从以下链接实施解决方案。我会等待~60秒,然后在没有停止的情况下终止IIS进程。

https://greenfinch.ie/blog/powershellscript.html

        "Stopping IIS site [$name]" >> $logFile
        stop-website -name $name

        "Stopping app pool [$name]" >> $logFile
        stop-webapppool -name $name

        $sleepTime = 5
        $processId = $TRUE
        while ($processId)
        {
            $processId = Get-WmiObject -Class win32_process -filter "name='w3wp.exe'" |
                            ?{ ($_.CommandLine).Split("`"")[1] -eq $name } |
                            %{ $_.ProcessId }

            if ($sleepTime -gt 60)
            {
                "Waited [$sleepTime] sec for process [$processId] to stop and it is still running. Killing it." >> $logFile
                Stop-Process $processId
                break
            }

            if ($processId)
            {
                "App pool [$name] is running with process ID: [$processId]. Sleeping for [$sleepTime] sec and then checking again." >> $logFile
                Start-Sleep -s $sleepTime
                $sleepTime = $sleepTime + 10
            }
        }

5 个答案:

答案 0 :(得分:12)

您可以使用这两个命令来检查网站/应用的状态,比如10秒后,然后使用If语句仅在返回状态为stopped时删除日志

Get-WebsiteState -name "MyWebsite"
Get-WebAppPoolState -name "MyWebsite"

这个循环也应该对你有帮助

$currentRetry = 0;
$success = $false;
do{
    $status = Get-WebAppPoolState -name "MyWebsite"
    if ($status -eq "Stopped"){
         <....your code here....>
            $success = $true;
        }
        Start-Sleep -s 10
        $currentRetry = $currentRetry + 1;
    }
while (!$success -and $currentRetry -le 4)

2019年4月24日更新

根据评论和当前cmdlet document,看来返回类型确实是一个对象。因此,大概可以作为评论或下面的行代码段来处理。作者不再能够访问Windows Server环境,因此没有直接修改原始答案也无法测试更新

if ($status.Value -eq "Stopped")

答案 1 :(得分:2)

运行'Stop-WebAppPool'后,WebAppPool的状态将为“Stopping”,并且可能需要几秒钟才能实现WebAppPool的状态“停止”。
这是一个帮助WebAppPoolState

的小功能
localhost:{PORT}

您可以使用例如

运行此功能
function Stop-AppPool ($webAppPoolName,[int]$secs) {
$retvalue = $false
$wsec = (get-date).AddSeconds($secs)
Stop-WebAppPool -Name $webAppPoolName
Write-Output "$(Get-Date) waiting up to $secs seconds for the WebAppPool '$webAppPoolName' to stop"
$poolNotStopped = $true
while (((get-date) -lt $wsec) -and $poolNotStopped) {
    $pstate =  Get-WebAppPoolState -Name $webAppPoolName
    if ($pstate.Value -eq "Stopped") {
        Write-Output "$(Get-Date): WebAppPool '$webAppPoolName' is stopped"
        $poolNotStopped = $false
        $retvalue = $true
    }
}
return $retvalue
}

并检查返回值以查看WebAppPool是否已在给定的秒内停止

答案 2 :(得分:0)

以下是我使用Get-IISServerManager的方法。

$manager = Get-IISServerManager      
$site = $manager.Sites["mySiteName"]

if($site.State -ne "Stopped") {
  $site.Stop()
}

while ($site.State -ne "Stopped") {
  "waiting 1 second for site to stop..."
  Start-Sleep -s 1
}

"site stopped"

答案 3 :(得分:0)

我修复了@ user4531代码,如果在以下时间之前停止了应用程序池,则会失败:

function Stop-AppPool ($webAppPoolName,[int]$secs) {
    $retvalue = $false
    $wsec = (get-date).AddSeconds($secs)

    $pstate =  Get-WebAppPoolState -Name $webAppPoolName

    if($pstate.Value -eq "Stopped") {
         Write-Output "WebAppPool '$webAppPoolName' is stopped already"
         return $true
    }

    Stop-WebAppPool -Name $webAppPoolName
    Write-Output "$(Get-Date) waiting up to $secs seconds for the WebAppPool '$webAppPoolName' to stop"
    $poolNotStopped = $true
    while (((get-date) -lt $wsec) -and $poolNotStopped) {
        $pstate =  Get-WebAppPoolState -Name $webAppPoolName
        if ($pstate.Value -eq "Stopped") {
            Write-Output "WebAppPool '$webAppPoolName' is stopped"
            $poolNotStopped = $false
            $retvalue = $true
        }
    }
    return $retvalue
}

它可以像这样使用:

Stop-AppPool "SSO" 30

答案 4 :(得分:0)

停止应用程序池并使它进入“已停止”状态的最简单方法是使用appcmd.exe。当应用程序池真正停止或返回错误时,它将返回

只需在PowerShell上执行此操作:

& $env:windir\system32\inetsrv\appcmd.exe stop apppool /apppool.name:"YourAppPoolName"

正确弯曲您的AppPool后,您会收到以下消息:

“ YourAppPoolName”成功停止