Powershell 低调酷

发布: (2025年12月4日 GMT+8 21:51)
6 min read
原文: Dev.to

Source: Dev.to

PowerShell 常常因为不如其他更流行的 shell 而被忽视,但它提供了强大的功能,能够简化本地开发工作流。下面是一份逐步指南,展示如何使用 PowerShell 为 Go 项目构建文件监视器,从基本设置到使用后台作业处理长时间运行的进程。

什么是 PowerShell?

PowerShell 同时是基于 .NET 运行时的命令行 shell 和脚本语言。与传统的 Unix shell(例如 Bash)通过管道传递纯文本不同,PowerShell 的管道传递 对象,从而可以在 shell 中直接进行更丰富的数据操作。

设置监视器目录

# Create a directory for the watcher
mkdir watcher

PowerShell 提供 New-Item cmdlet 用于创建项,但出于便利常用的别名如 mkdir 也可使用。

# Navigate into the directory
cd watcher

# Create a placeholder Go source file
ni main.go

# Create the PowerShell script that will perform the watching
ni watcher.ps1

调整执行策略

PowerShell 的执行策略决定脚本是否可以运行。继续操作前请确保已将其设置为 RemoteSigned(或更宽松的级别)。

# View the current policy
Get-ExecutionPolicy

# If needed, set it to RemoteSigned
Set-ExecutionPolicy RemoteSigned -Scope CurrentUser -Force

示例 Go 程序

创建一个简单的 Go 程序,打印 “Hello World”。将其保存为 main.go,放在 watcher 文件夹中。

package main

import "fmt"

func main() {
    fmt.Println("Hello World")
}

基础监视脚本(同步)

下面的 PowerShell 脚本会监视当前目录(及子目录)下所有 .go 文件。当检测到变化时,重新运行 Go 程序。

# watcher.ps1
# Path to the Go file (can be overridden later)
$path = "main.go"

Write-Host 'GoWatcher *Press CTRL+C to quit*'

$dirname = "."
$files   = Get-ChildItem $dirname -Filter "*.go" -Recurse

# Initial run
go run $path

# Compute an initial signature (hash) of all Go files
$signature = $files | Get-FileHash -ErrorAction SilentlyContinue |
             Sort-Object Path | Out-String

while ($true) {
    $current_signature = $files | Get-FileHash -ErrorAction SilentlyContinue |
                         Sort-Object Path | Out-String

    if ($signature -ne $current_signature) {
        Write-Host 'File change detected: Restarting...'
        go run $path
        $signature = $current_signature
    }

    Start-Sleep -Milliseconds 300
}

运行脚本:

.\watcher.ps1

为文件路径添加参数

通过接受 Go 文件路径作为命令行参数,使脚本更具灵活性。

# watcher.ps1 (updated)
[CmdletBinding()]
Param(
    [Parameter(Mandatory)]
    $path
)

Write-Host 'GoWatcher *Press CTRL+C to quit*'

$dirname = "."
$files   = Get-ChildItem $dirname -Filter "*.go" -Recurse

go run $path
$signature = $files | Get-FileHash -ErrorAction SilentlyContinue |
             Sort-Object Path | Out-String

while ($true) {
    $current_signature = $files | Get-FileHash -ErrorAction SilentlyContinue |
                         Sort-Object Path | Out-String

    if ($signature -ne $current_signature) {
        Write-Host 'File change detected: Restarting...'
        go run $path
        $signature = $current_signature
    }

    Start-Sleep -Milliseconds 300
}

使用路径参数执行:

.\watcher.ps1 -path 'main.go'

使用后台作业处理长时间运行的进程

当 Go 应用运行 Web 服务器或其他阻塞操作时,监视脚本会卡住。PowerShell 作业可以让这些进程异步运行。

常用作业 Cmdlet

# Start a background job
Start-Job -Name GoServer -ScriptBlock { ... }

# Stop a job
Stop-Job -Name GoServer

# Remove a job
Remove-Job -Name GoServer

# Retrieve job output
Receive-Job -Name GoServer

# List jobs
Get-Job -Name GoServer

带作业管理的高级监视器

下面的脚本将 Go 服务器作为后台作业启动,在文件变化时重启,并在监视器退出时进行清理。

# watcher.ps1 (advanced version)
[CmdletBinding()]
Param(
    [Parameter(Mandatory)]
    $path
)

Write-Host 'GoWatcher *Press CTRL+C to quit*'

$dirname   = "."
$jobname   = "GoServer"
$binary    = "GoApp"

function Start-ServerJob {
    # Remove any existing job with the same name
    Get-Job -Name $jobname -ErrorAction SilentlyContinue | Remove-Job -Force

    # Start a new job that builds and runs the Go binary
    $job = Start-Job -Name $jobname -ScriptBlock {
        param($path, $dirname, $binary)
        Set-Location $dirname

        # Build the binary (adjust as needed for your project)
        go build -o "bin/$binary.exe" $path

        # Execute the binary
        & "./bin/$binary.exe"
    } -ArgumentList $path, $dirname, $binary

    return $job
}

# Gather all Go source files
$files = Get-ChildItem $dirname -Filter "*.go" -Recurse

# Initial launch
$job = Start-ServerJob

# Initial signature
$signature = $files | Get-FileHash -ErrorAction SilentlyContinue |
             Sort-Object Path | Out-String

try {
    while ($true) {
        $current_signature = $files | Get-FileHash -ErrorAction SilentlyContinue |
                             Sort-Object Path | Out-String

        if ($signature -ne $current_signature) {
            Write-Host 'File change detected: Restarting...'

            # Restart the server job
            $job = Start-ServerJob
            $signature = $current_signature
        }

        Start-Sleep -Milliseconds 300
    }
}
finally {
    # Clean up the background job
    Get-Job -Name $jobname -ErrorAction SilentlyContinue | Remove-Job -Force

    # Ensure the binary process is terminated
    if (Get-Process -Name $binary -ErrorAction SilentlyContinue) {
        Stop-Process -Name $binary -Force
    }
}

以相同方式运行高级监视器:

.\watcher.ps1 -path 'main.go'

该脚本现在:

  1. 构建 Go 程序为可执行文件。
  2. 运行 可执行文件作为后台作业。
  3. 检测 任意 .go 文件的变化。
  4. 在变化时重启 后台作业。
  5. 在终止时清理 资源。

结论

PowerShell 的面向对象管道、内置别名以及强大的作业系统,使其成为自动化开发任务(如文件监视和进程管理)的优秀选择。通过利用这些特性,你可以创建轻量、跨平台的工具,而无需依赖外部实用程序。

Back to Blog

相关文章

阅读更多 »

我终于消除的一个小摩擦

封面图片:我最终去除的一个小摩擦 https://media2.dev.to/dynamic/image/width=1000,height=420,fit=cover,gravity=auto,format=auto/https%3A%2F%2Fde...

开源邮件预热:完整指南

引言 开源电子邮件预热是逐步与邮箱提供商建立信任的过程,使您的邮件进入收件箱,而不是垃圾邮件文件夹....