Ответ
В Go для управления жизненным циклом дочерних процессов используется пакет os
. Завершить процесс по его PID можно несколькими способами, в основном через отправку системных сигналов.
Основные способы:
Graceful Shutdown (Мягкое завершение):
syscall.SIGTERM
- Это стандартный и предпочтительный способ попросить процесс завершиться.
- Процесс может перехватить этот сигнал и выполнить очистку перед выходом (например, закрыть соединения, сохранить данные).
- Отправляется через
process.Signal(syscall.SIGTERM)
.
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
.