约 2703 字

约 14 分钟

#跨平台部署

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 的服务管理方式不同:

操作WindowsLinux
查看服务Get-Servicesystemctl status
启动服务Start-Servicesystemctl start
停止服务Stop-Servicesystemctl stop
重启服务Restart-Servicesystemctl 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 判断成败。

#推荐阅读

更新: 2026/11/2

作者: planc

创建: 2026/11/2