在 Windows 上,有时 PostgreSQL 会遇到这样一种异常:数据库无法正常访问,但从任务管理器中看,仍然有一些名为 postgres.exe 在运行。而在任务管理器中,它的状态是“已停止”,但它却无法在任务管理器中启动。于是就陷入了一个死局。
解决这个问题的方法是 关闭所有残留的 postgres.exe 进程。
下面这个 powershell 脚本可以解决问题,读者只需要配置 参数 $PgServiceName,即数据库服务名即可:
# set-ExecutionPolicy UnRestricted -force
$DebugPreference="inquire"# Name of PostgreSQL Service
$PgServiceName = "postgresql-11"
$CurrentFile = $MyInvocation.MyCommand.Definition
$CurrentDir = Split-Path -Parent $MyInvocation.MyCommand.Definitionset-Location $CurrentDir
if (($PgServiceName -eq $null) -or ($PgServiceName -eq "/?"))
{
Write-Output "Please set parameter PgServiceName in this file."
Read-Host -Prompt "Press Enter to continue"
exit
}# check if the service exists or not
$pgService = Get-WmiObject -class win32_service -filter "name='$PgServiceName'"
if ($pgService -eq $null)
{
$CurrentTime = $(Get-Date).toString("yyyy-MM-dd HH:mm:ss")
$Message = "$CurrentTime ERROR: Service ""$PgServiceName"" does not exist."
Write-Output $Message
Start-Sleep -Seconds 3
exit
}
# find home directory of PostgreSQL
# PgHome: home directory of PostgreSQL
# BinDir: $PgHome/bin directory of postgresql
# DataDir: $PgHome/data of postgresql$Pathname = (Get-WmiObject -class win32_service -filter "name='$PgServiceName'").pathname
$PgHomeTemp = $Pathname -replace "\\bin\\pg_ctl\.exe.*", ""
$PgHome = $PgHomeTemp.TrimStart("""")$DataDirTemp = $Pathname -replace ".*"" -D """,""
$DataDir = $DataDirTemp.TrimEnd("""")$BinDir = $PgHome + "\bin"
$PgctlPath = $BinDir + "\pg_ctl.exe"
$PgctlPattern = $PgctlPath -replace "\\", "\\"
$PgctlFilter = "(Name='pg_ctl.exe' and ExecutablePath='" + $PgctlPattern + "')"
# check the if the service is running
$ServiceStatus = (Get-Service -Name $PgServiceName).Status
if ($ServiceStatus -eq "Running")
{
$PgctlProcess = (Get-WmiObject -class win32_process -filter $PgctlFilter)
if ($PgctlProcess)
{
$CurrentTime = $(Get-Date).toString("yyyy-MM-dd HH:mm:ss")
$Message = "$CurrentTime INFO: Service $PgServiceName started successfully."
Write-Output $Message
exit
}
}$PostgresPath = $BinDir + "\postgres.exe"
$PostgresPattern = $PostgresPath -replace "\\", "\\"
$PostgresFilter = "(Name='postgres.exe' and ExecutablePath='" + $PostgresPattern + "')"$CompleteFilter = "(" + $PgctlFilter + " or " + $PostgresFilter + ")"
Get-WmiObject -class win32_process -filter $CompleteFilter | Remove-WmiObject | Out-Null