#跨平台部署
PowerShell 7 可以在 Windows、Linux、macOS 上运行,同一套脚本往往需要在不同平台完成环境检查、文件分发和服务重启。本页给出一种简单、可幂等的部署思路。
#环境检查
使用 $PSVersionTable.PSVersion 查看版本,并用 $IsWindows、$IsLinux、$IsMacOS 判断平台。这些变量在 PowerShell 6 及以上可用,Windows PowerShell 5.1 中不存在。需要兼容 5.1 时,可以改用 $env:OS 或 [System.Environment]::OSVersion.Platform。
deploy.ps1
param(
[string]$Source = './dist',
[string]$Target = '/opt/myapp'
)
if (-not (Test-Path -LiteralPath $Source)) {
Write-Error "源目录不存在:$Source"
exit 1
}
if ($IsWindows) {
$Target = 'C:\myapp'
}
if (-not (Test-Path -LiteralPath $Target)) {
New-Item -ItemType Directory -Path $Target -Force | Out-Null
}
#文件分发与幂等性
直接覆盖复制虽然简单,但每次部署都会改动文件时间戳。可以先比较哈希,只在内容不同时复制:
deploy.ps1
Get-ChildItem -Path $Source -File -Recurse | ForEach-Object {
$root = (Resolve-Path -LiteralPath $Source).Path
$relative = $_.FullName.Substring($root.Length).TrimStart([char[]]@('\', '/'))
$destination = Join-Path $Target $relative
$destinationDir = Split-Path -Parent $destination
if (-not (Test-Path -LiteralPath $destinationDir)) {
New-Item -ItemType Directory -Path $destinationDir -Force | Out-Null
}
$needCopy = $true
if (Test-Path -LiteralPath $destination) {
$needCopy = (Get-FileHash $_.FullName).Hash -ne (Get-FileHash $destination).Hash
}
if ($needCopy) {
Copy-Item -LiteralPath $_.FullName -Destination $destination -Force
Write-Host "已更新:$destination"
}
}
幂等性的关键是:重复执行不会产生额外副作用。上面的脚本第二次运行时不会重复复制内容相同的文件。
#服务重启
Windows 与 Linux 的服务管理方式不同:
| 操作 | Windows | Linux |
|---|---|---|
| 查看服务 | Get-Service | systemctl status |
| 启动服务 | Start-Service | systemctl start |
| 停止服务 | Stop-Service | systemctl stop |
| 重启服务 | Restart-Service | systemctl restart |
在 PowerShell 中按平台调用:
deploy.ps1
if ($IsWindows) {
Restart-Service -Name 'MyApp' -ErrorAction Stop
}
elseif ($IsLinux) {
& systemctl restart myapp
if ($LASTEXITCODE -ne 0) {
throw 'systemctl restart 失败'
}
}
Get-Service 在 Linux 上的支持有限,因此调用外部命令 systemctl 通常更可靠。外部命令的退出码保存在 $LASTEXITCODE 中。
#注意事项
- 路径分隔符不同,拼接路径时优先使用
Join-Path,不要手写\或/。 - 文件权限:Linux 上可能需要
chmod或chown,Windows 上使用 ACL。 - 服务名称、安装路径和日志位置通常因平台而异,建议把它们做成参数。
- 部署脚本应返回明确的退出码,便于 CI/CD 判断成败。