Тип os.Process

Тип os.Process представляет собой запущенный процесс операционной системы. Он используется для управления внешними процессами, запущенными из Go-программы. Основные методы этого типа позволяют завершать процесс, отправлять ему сигналы, ожидать его завершения и освобождать связанные с ним системные ресурсы.

Объект типа os.Process можно получить при запуске нового процесса с помощью функции os.StartProcess или при поиске уже запущенного процесса по его идентификатору (PID) с помощью функции os.FindProcess.

Синтаксис

gotype Process struct {
  Pid int
  // содержит скрытые поля
}

Структура Process содержит поле Pid - идентификатор процесса и ряд скрытых полей для внутреннего использования. Для работы с процессами используются методы этой структуры.

Пример запуск процесса

Давайте запустим процесс с помощью os.StartProcess и получим объект os.Process:

gopackage main

import (
  "fmt"
  "os"
  "time"
)

func main() {
  // Запускаем процесс с командой echo
  attr := &os.ProcAttr{
    Files: []*os.File{os.Stdin, os.Stdout, os.Stderr},
  }
  proc, err := os.StartProcess("/bin/echo", []string{"echo", "Hello from process"}, attr)
  if err != nil {
    fmt.Println("Error:", err)
    return
  }
  // Выводим PID запущенного процесса
  fmt.Println("Process PID:", proc.Pid)

  // Ждем завершения процесса
  state, err := proc.Wait()
  if err != nil {
    fmt.Println("Wait error:", err)
    return
  }
  fmt.Println("Process exited:", state.Exited())
}

Результат выполнения кода:

go"Hello from process"
"Process PID: 12345"
"Process exited: true"

В этом примере мы запускаем команду echo, получаем объект процесса с его PID и дожидаемся его завершения с помощью метода Wait.

Пример поиск процесса по PID

Для поиска запущенного процесса по его идентификатору используется функция os.FindProcess:

gopackage main

import (
  "fmt"
  "os"
)

func main() {
  // PID существующего процесса (например, текущего)
  pid := os.Getpid()
  fmt.Println("Current PID:", pid)

  // Находим процесс по PID
  proc, err := os.FindProcess(pid)
  if err != nil {
    fmt.Println("Find process error:", err)
    return
  }
  fmt.Printf("Process found: PID=%d\n", proc.Pid)

  // Освобождаем ресурсы процесса
  err = proc.Release()
  if err != nil {
    fmt.Println("Release error:", err)
    return
  }
  fmt.Println("Process resources released")
}

Результат выполнения кода:

go"Current PID: 12345"
"Process found: PID=12345"
"Process resources released"

Функция FindProcess находит процесс по PID и возвращает объект Process, после чего метод Release освобождает ресурсы процесса в системе.

Пример отправка сигнала процессу

Метод Signal позволяет отправлять системные сигналы процессу. В этом примере мы отправим сигнал SIGTERM для завершения процесса:

gopackage main

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

func main() {
  // Запускаем долгий процесс (sleep)
  attr := &os.ProcAttr{
    Files: []*os.File{os.Stdin, os.Stdout, os.Stderr},
  }
  proc, err := os.StartProcess("/bin/sleep", []string{"sleep", "30"}, attr)
  if err != nil {
    fmt.Println("Start error:", err)
    return
  }
  fmt.Printf("Process started with PID: %d\n", proc.Pid)

  // Отправляем сигнал SIGTERM через 2 секунды
  time.Sleep(2 * time.Second)
  err = proc.Signal(syscall.SIGTERM)
  if err != nil {
    fmt.Println("Signal error:", err)
    return
  }
  fmt.Println("SIGTERM signal sent")

  // Ожидаем завершения процесса
  state, err := proc.Wait()
  if err != nil {
    fmt.Println("Wait error:", err)
    return
  }
  fmt.Printf("Process exited: %v\n", state.Exited())
}

Результат выполнения кода:

go"Process started with PID: 12346"
"SIGTERM signal sent"
"Process exited: true"

В этом примере процесс sleep завершается до истечения 30 секунд из-за отправленного сигнала SIGTERM. Метод Wait блокирует выполнение до завершения процесса и возвращает его состояние.

Пример завершение процесса

Метод Kill немедленно завершает процесс. Он аналогичен отправке сигнала SIGKILL:

gopackage main

import (
  "fmt"
  "os"
  "time"
)

func main() {
  // Запускаем долгий процесс
  attr := &os.ProcAttr{
    Files: []*os.File{os.Stdin, os.Stdout, os.Stderr},
  }
  proc, err := os.StartProcess("/bin/sleep", []string{"sleep", "20"}, attr)
  if err != nil {
    fmt.Println("Start error:", err)
    return
  }
  fmt.Printf("Process PID: %d\n", proc.Pid)

  // Завершаем процесс через 1 секунду
  time.Sleep(1 * time.Second)
  err = proc.Kill()
  if err != nil {
    fmt.Println("Kill error:", err)
    return
  }
  fmt.Println("Process killed")

  // Ожидаем завершения
  state, err := proc.Wait()
  if err != nil {
    fmt.Println("Wait error:", err)
    return
  }
  fmt.Printf("Process exited: %v\n", state.Exited())
}

Результат выполнения кода:

go"Process PID: 12347"
"Process killed"
"Process exited: true"

Метод Kill немедленно завершает процесс без возможности перехвата сигнала, в отличие от Signal с SIGTERM, который может быть обработан процессом.

Смотрите также

  • тип os.ProcessState,
    который содержит информацию о завершившемся процессе
  • функцию os.StartProcess,
    которая запускает новый процесс и возвращает os.Process
  • функцию os.FindProcess,
    которая находит процесс по идентификатору PID
  • метод os.Process.Wait,
    который ожидает завершения процесса и возвращает его состояние