使用Packer在Windows Server 2019上安装PostgreSQL提前终止无报错
解决Packer在Windows Server 2019上安装PostgreSQL中途终止的问题
核心原因
Packer的Windows provisioner默认只等命令的父进程退出,但PostgreSQL安装程序(不管是exe版还是Chocolatey调用的)常会启动子进程后让父进程提前退出,导致Packer误判安装完成,直接跳到下一阶段。
具体解决方案
1. 用Start-Process强制等待所有子进程(exe安装)
把安装命令封装进Start-Process,加上-Wait和-NoNewWindow参数,确保Packer等所有安装相关进程结束,同时保留日志方便排查:
# 先创建日志目录 New-Item -Path C:\temp -ItemType Directory -Force # 执行PostgreSQL无人值守安装 Start-Process -FilePath "postgresql-12.17-1-windows-x64.exe" ` -ArgumentList "--mode unattended --superpassword yourSecurePassword --prefix ""C:\Program Files\PostgreSQL\12"" --datadir ""C:\Program Files\PostgreSQL\12\data"" --enable-components server,commandline-tools" ` -Wait -NoNewWindow ` -RedirectStandardOutput "C:\temp\pg_install.log" ` -RedirectStandardError "C:\temp\pg_install_err.log"
-Wait:强制等待整个安装流程结束,不是只等父进程-NoNewWindow:让安装输出直接显示在Packer控制台- 日志参数:把安装过程的输出/错误存到本地,事后能查具体卡在哪一步
2. 给Chocolatey加强制等待参数
用Chocolatey安装时,默认逻辑可能没等子进程,加上--wait参数强制它等所有安装进程结束:
choco install postgresql12 --version 12.17.0 --yes --force --wait ` --install-arguments="--mode unattended --superpassword yourSecurePassword"
--wait:关键参数,让Chocolatey不提前返回--force:避免缓存的旧安装包导致异常
3. 在Packer配置里加验证步骤
修改Packer的powershell provisioner,安装后直接检查PostgreSQL服务是否存在,没装成就中断构建,避免白跑后续流程:
provisioner "powershell" { elevated = true timeout = "30m" # 安装可能耗时久,调大超时时间 inline = [ "New-Item -Path C:\\temp -ItemType Directory -Force", "Start-Process -FilePath 'choco' -ArgumentList 'install postgresql12 --version 12.17.0 --yes --wait --install-arguments=""--mode unattended --superpassword yourSecurePassword""' -Wait -NoNewWindow -RedirectStandardOutput C:\\temp\\choco_pg.log -RedirectStandardError C:\\temp\\choco_pg_err.log", # 验证服务是否存在 "$pgService = Get-Service -Name postgresql-x64-12 -ErrorAction SilentlyContinue", "If (-not $pgService) { throw 'PostgreSQL安装失败,服务未创建' }" ] }
4. 手动捕获进程树(极端情况用)
如果以上方法还是不行,直接写脚本捕获安装程序的所有子进程,强制等它们全部结束:
$installProcess = Start-Process -FilePath "postgresql-12.17-1-windows-x64.exe" ` -ArgumentList "--mode unattended --superpassword yourSecurePassword" ` -PassThru -NoNewWindow # 循环等待主进程和所有子进程退出 do { $installProcess.Refresh() $childProcesses = Get-Process -Id $installProcess.Id -ErrorAction SilentlyContinue | Select-Object -ExpandProperty Id | ForEach-Object { Get-Process -Id $_ -ErrorAction SilentlyContinue | Select-Object -ExpandProperty Children } Start-Sleep -Seconds 5 } while ($installProcess.HasExited -eq $false -or $childProcesses.Count -gt 0)
排查技巧
- 看日志:打开
C:\temp下的安装日志,确认安装程序实际执行到哪一步停了 - Packer调试模式:用
packer build -debug启动,构建暂停时远程登机器,用tasklist看有没有PostgreSQL相关进程在跑 - Windows事件日志:去
Windows Logs > Application里找PostgreSQL的安装错误信息
内容的提问来源于stack exchange,提问作者kirkpatt
相关产品推荐
相关产品推荐

