Способы завершения процесса в Go

Ответ

В Go для управления жизненным циклом дочерних процессов используется пакет os. Завершить процесс по его PID можно несколькими способами, в основном через отправку системных сигналов.

Основные способы:

  1. Graceful Shutdown (Мягкое завершение): syscall.SIGTERM

    • Это стандартный и предпочтительный способ попросить процесс завершиться.
    • Процесс может перехватить этот сигнал и выполнить очистку перед выходом (например, закрыть соединения, сохранить данные).
    • Отправляется через process.Signal(syscall.SIGTERM).
  2. Forceful Shutdown (Принудительное завершение): syscall.SIGKILL

    • Это сигнал немедленного "убийства" процесса. Его нельзя перехватить или проигнорировать.
    • Используется, когда процесс не отвечает на SIGTERM.
    • Метод process.Kill() является удобной оберткой для отправки SIGKILL.
package main

import (
    "fmt"
    "os"
    "os/exec"
    "syscall"
    "time"
)

func main() {
    // Запускаем дочерний процесс
    cmd := exec.Command("sleep", "10")
    err := cmd.Start()
    if err != nil {
        fmt.Println("Error starting command:", err)
        return
    }

    fmt.Printf("Процесс запущен с PID: %dn", cmd.Process.Pid)

    // --- Вариант 1: Мягкое завершение (предпочтительный) ---
    fmt.Println("Отправка сигнала SIGTERM...")
    cmd.Process.Signal(syscall.SIGTERM)

    // --- Вариант 2: Принудительное завершение ---
    // fmt.Println("Принудительное завершение через Kill (SIGKILL)...")
    // cmd.Process.Kill()

    // Ожидаем завершения процесса, чтобы освободить ресурсы
    state, err := cmd.Process.Wait()
    if err != nil {
        fmt.Println("Error waiting for process:", err)
    }
    fmt.Printf("Процесс завершен: %sn", state.String())
}

Ключевые моменты:

  • os.FindProcess(pid): Позволяет получить объект *os.Process для уже существующего процесса, зная его PID.
  • cmd.Process.Wait(): Важно вызывать этот метод для запущенных через exec.Command процессов. Он ожидает завершения процесса и освобождает связанные с ним системные ресурсы.
  • Windows: В Windows нет полноценной поддержки сигналов UNIX. Метод process.Kill() работает, вызывая TerminateProcess, что аналогично SIGKILL.