From f3af311a3077cff75e52e1a423a0535256f6898c Mon Sep 17 00:00:00 2001 From: "Timofey.Kovalev" Date: Fri, 25 Jul 2025 17:25:14 +0300 Subject: [PATCH] commit --- .gitignore | 1 + Makefile | 6 ++++++ README.md | 53 +++++++++++++++++++++++++++++++++++++++++++++++++++++ main.go | 18 ++++++++++-------- 4 files changed, 70 insertions(+), 8 deletions(-) create mode 100644 .gitignore create mode 100644 Makefile create mode 100644 README.md diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..2b9fcf4 --- /dev/null +++ b/.gitignore @@ -0,0 +1 @@ +qini diff --git a/Makefile b/Makefile new file mode 100644 index 0000000..7534fae --- /dev/null +++ b/Makefile @@ -0,0 +1,6 @@ +all: build + +build: qini + +qini: main.go + go build -o qini main.go diff --git a/README.md b/README.md new file mode 100644 index 0000000..c0fcba4 --- /dev/null +++ b/README.md @@ -0,0 +1,53 @@ +# Qini + +**Легковесный init для контейнеров**, который управляет несколькими процессами, связывая их `stdin/stdout` и гарантируя остановку всех процессов, если один из них завершается. + + **Идеально для Docker-контейнеров**, чтобы избежать "висящих" процессов и обеспечить корректное завершение работы. + +--- + +## Особенности + + **Автоматическое завершение всех процессов**, если один из них остановлен + **Перенаправление stdin/stdout** между процессами + **Простая конфигурация** в формате JSON + **Минималистичный и быстрый** (написан на Go) + **Простая сборка** через `make` + +--- + +## Установка + +### Сборка из исходников +```sh +git clone https://gitlab.stageoffice.ru/UCS-ENV/qini +cd qini +make +``` + +--- + +## Конфиг +Простой пример конфига в котором необходимо указать процессы сверху вниз в той последовательности как они будут собраны в цепочку связывания stdin/stdout + +``` +{ + "services": [ + { + "cmd": "/bin/ls", + }, + { + "cmd": "/bin/grep", + "args": ["main"] + } + ] +} +``` + +--- + +## Запуск + +``` +$ qini -c config.json +``` diff --git a/main.go b/main.go index 6a2fa91..7ccd326 100644 --- a/main.go +++ b/main.go @@ -47,7 +47,7 @@ func debug(s string, a ...any) { func stopAllServices(services []*Service) { for _, s := range services { - if s.cmd.Process == nil { + if s.cmd.Process == nil || s.cmd.ProcessState != nil { continue } @@ -84,7 +84,7 @@ func runServices(services []*Service) (int, error) { s.cmd = exec.Command(s.CMD, s.Args...) s.cmd.SysProcAttr = &syscall.SysProcAttr{ - Setsid: true, + //Setsid: true, } if s.PWD != "" { @@ -148,7 +148,7 @@ func loadConfig(cfg *Config, configFile string) error { } func forwardSignals(services []*Service) { - signals := []os.Signal{syscall.SIGCHLD, syscall.SIGTERM, syscall.SIGINT, syscall.SIGQUIT} + signals := []os.Signal{syscall.SIGCHLD, syscall.SIGTERM, syscall.SIGINT, syscall.SIGQUIT, syscall.SIGSEGV} sigCh := make(chan os.Signal, 1) signal.Notify(sigCh, signals...) @@ -169,20 +169,22 @@ func forwardSignals(services []*Service) { } func main() { - verbose = false + var ( + configFile string + cfg Config - err := unix.Prctl(unix.PR_SET_CHILD_SUBREAPER, 1, 0, 0, 0) + err error + ) + + err = unix.Prctl(unix.PR_SET_CHILD_SUBREAPER, 1, 0, 0, 0) if err != nil { printErr(err) } - var configFile string flag.StringVar(&configFile, "c", "./config.json", "JSON config file") flag.BoolVar(&verbose, "v", false, "Show debug output") flag.Parse() - var cfg Config - err = loadConfig(&cfg, configFile) if err != nil { printErr(err)