This commit is contained in:
Timofey.Kovalev
2025-07-25 17:25:14 +03:00
parent a5055b226f
commit a69c534c11
4 changed files with 69 additions and 8 deletions

1
.gitignore vendored Normal file
View File

@ -0,0 +1 @@
qini

6
Makefile Normal file
View File

@ -0,0 +1,6 @@
all: build
build: qini
qini: main.go
go build -o qini main.go

52
README.md Normal file
View File

@ -0,0 +1,52 @@
# Qini
**Легковесный init для контейнеров**, который управляет несколькими процессами, связывая их `stdin/stdout` и гарантируя остановку всех процессов, если один из них завершается.
**Идеально для Docker-контейнеров**, чтобы избежать "висящих" процессов и обеспечить корректное завершение работы.
---
## Особенности
**Автоматическое завершение всех процессов**, если один из них остановлен
**Перенаправление stdin/stdout** между процессами
**Простая конфигурация** в формате JSON
**Минималистичный и быстрый** (написан на Go)
**Простая сборка** через `make`
---
## Установка
### Сборка из исходников
```sh
git clone https://gitlab.stageoffice.ru/UCS-ENV/qini
cd qini
make
```
---
## Конфиг
```
{
"services": [
{
"cmd": "/bin/ls",
},
{
"cmd": "/bin/grep",
"args": ["main"]
}
]
}
```
---
## Запуск
```
$ qini -c config.json
```

18
main.go
View File

@ -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)