Skip to content
webnicePublic

About

Решение задач связанных с запуском и взаимодействием с запущенными приложениями.

Resources

Stars

0 stars

Watchers

1 watching

Forks

Repository files navigation

Run


GoDoc Coverage Status

run

Библиотека Golang предоставляющая интерфейс к стандартным пакетам go, для решения задач связанных с запуском и взаимодействием с запущенными приложениями.


Описание

run — это обёртка над стандартными пакетами os, os/exec и context, решающая задачи запуска внешних приложений и обмена данными с ними через стандартные потоки ввода-вывода (STDIN, STDOUT, STDERR). Пакет берёт на себя управление вспомогательными горутинами и каналами, обеспечивает гарантированную доставку данных и корректное освобождение ресурсов после завершения процесса.

Особенности

  • Запуск приложений с ожиданием завершения и без ожидания;
  • Обмен данными через STDIN, STDOUT, STDERR, как через буферы, так и через каналы;
  • Передача больших объёмов данных без блокировки вспомогательных горутин;
  • Завершение запущенного приложения через контекст;
  • Настройка рабочей директории, переменных окружения, chroot, пользователя и группы;
  • Отправка сигналов запущенному приложению, принудительное завершение;
  • Сброс состояния и повторное использование объекта одной функцией Reset();
  • Нулевые зависимости, режим отладки с выводом внутренних сообщений.

Требования

  • Go 1.19 или новее.

Установка

go get -u github.com/webnice/run

Подключение:

import (
	"github.com/webnice/run"
)

Зависимости

NONE

Примеры использования

Запуск приложения с ожиданием завершения

obj := run.New()
if _, err := obj.RunWait(nil, "echo", "привет"); err != nil {
	log.Fatalf("запуск приложения прерван ошибкой: %s", err)
}
log.Printf("команда: %v, завершена успешно", obj.Command())

Передача данных в STDIN и чтение STDOUT

Функции StdIn, StdOut, StdErr работают с буферами: функции StdOut и StdErr блокируются до момента получения всех данных, в то время как в канал, открытый функциями StdInCh, StdOutCh, StdErrCh, данные поступают без задержки.

obj := run.New()
obj.StdIn([]byte("тестовые данные\n"))
if _, err := obj.RunWait(nil, "head", "-n", "1"); err != nil {
	log.Fatalf("запуск приложения прерван ошибкой: %s", err)
}
log.Printf("получено из STDOUT: %q", obj.StdOut())

Обмен данными через каналы

obj := run.New()
chIn := make(chan []byte)
obj.StdInCh(chIn)
chOut := obj.StdOutCh()
go func() {
	chIn <- []byte("тестовые данные\n")
	close(chIn)
}()
if _, err := obj.RunWait(nil, "head", "-n", "1"); err != nil {
	log.Fatalf("запуск приложения прерван ошибкой: %s", err)
}
for data := range chOut {
	log.Printf("получено из STDOUT: %q", data)
}

Завершение приложения через контекст

Если передан контекст не равный nil, тогда прерывание через контекст завершает работу приложения аналогично вызову функции Kill().

ctx, cancel := context.WithTimeout(context.Background(), time.Second)
defer cancel()
obj := run.New()
if _, err := obj.RunWait(ctx, "sleep", "60"); err != nil {
	log.Fatalf("запуск приложения прерван ошибкой: %s", err)
}

Запуск без ожидания и управление процессом

obj := run.New()
if obj.Run(nil, "sleep", "60").Error() != nil {
	log.Fatalf("запуск приложения прерван ошибкой: %s", obj.Error())
}
log.Printf("процесс запущен, PID: %d", obj.Pid())
if err := obj.Signal(syscall.SIGTERM); err != nil {
	log.Fatalf("передача сигнала прервана ошибкой: %s", err)
}
if _, err := obj.Wait(); err != nil {
	log.Fatalf("ожидание завершения прервано ошибкой: %s", err)
}

Настройки запуска приложения

obj := run.New()
obj.
	WorkingDirectory("/tmp").
	Environment("KEY1=Value1", "KEY2=Value2").
	Chroot("/").
	Sudo(0, 0, true)
if _, err := obj.RunWait(nil, "echo", "привет"); err != nil {
	log.Fatalf("запуск приложения прерван ошибкой: %s", err)
}

Идентификаторы пользователя и группы можно найти по их названиям:

uid, err := run.New().UserID("www-data")
if err != nil {
	log.Fatalf("поиск пользователя прерван ошибкой: %s", err)
}

Повторное использование объекта

Функция Reset() завершает приложение, если оно было запущено, сбрасывает все настройки и подготавливает объект для повторного использования.

obj := run.New()
for i := 0; i < 10; i++ {
	if _, err := obj.RunWait(nil, "echo", "привет"); err != nil {
		log.Fatalf("запуск приложения прерван ошибкой: %s", err)
	}
	obj.Reset()
}

Интерфейс пакета

Конструктор New() возвращает объект удовлетворяющий интерфейсу run.Interface:

  • StdInCh, StdIn, StdOutCh, StdOut, StdErrCh, StdErr — обмен данными с процессом;
  • WorkingDirectory, Environment, Chroot, Sudo — настройки запуска приложения;
  • UserID, GroupID — поиск идентификаторов пользователя и группы по их названиям;
  • Command — возвращает текущую запущенную команду;
  • Debug — включение режима отладки;
  • Run, RunWait, Wait — запуск и ожидание завершения приложения;
  • LookPath — поиск исполняемого файла программы;
  • Pid, Signal, Kill, Release — управление запущенным процессом;
  • Reset — сброс состояния и подготовка к повторному использованию;
  • Error — ошибка, возникшая в функции не возвращающей ошибку.

Полное описание методов интерфейса доступно в документации пакета: https://pkg.go.dev/github.com/webnice/run.

Тестирование

# Стандартный прогон с покрытием.
go test -cover ./...

# Прогон через Makefile (агрегированный профиль покрытия в coverage.log).
make test

Лицензия

© WEB NICE, распространяется под лицензией MIT.

About

Решение задач связанных с запуском и взаимодействием с запущенными приложениями.

Resources

Stars

0 stars

Watchers

1 watching

Forks

Releases

Packages

Used by

Contributors

Languages