commit
This commit is contained in:
1
.gitignore
vendored
Normal file
1
.gitignore
vendored
Normal file
@ -0,0 +1 @@
|
||||
qini
|
6
Makefile
Normal file
6
Makefile
Normal file
@ -0,0 +1,6 @@
|
||||
all: build
|
||||
|
||||
build: qini
|
||||
|
||||
qini: main.go
|
||||
go build -o qini main.go
|
52
README.md
Normal file
52
README.md
Normal 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
18
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)
|
||||
|
Reference in New Issue
Block a user