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 | ||||||
							
								
								
									
										53
									
								
								README.md
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										53
									
								
								README.md
									
									
									
									
									
										Normal file
									
								
							| @ -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 | ||||||
|  | ``` | ||||||
							
								
								
									
										18
									
								
								main.go
									
									
									
									
									
								
							
							
						
						
									
										18
									
								
								main.go
									
									
									
									
									
								
							| @ -47,7 +47,7 @@ func debug(s string, a ...any) { | |||||||
|  |  | ||||||
| func stopAllServices(services []*Service) { | func stopAllServices(services []*Service) { | ||||||
| 	for _, s := range services { | 	for _, s := range services { | ||||||
| 		if s.cmd.Process == nil { | 		if s.cmd.Process == nil || s.cmd.ProcessState != nil { | ||||||
| 			continue | 			continue | ||||||
| 		} | 		} | ||||||
|  |  | ||||||
| @ -84,7 +84,7 @@ func runServices(services []*Service) (int, error) { | |||||||
| 		s.cmd = exec.Command(s.CMD, s.Args...) | 		s.cmd = exec.Command(s.CMD, s.Args...) | ||||||
|  |  | ||||||
| 		s.cmd.SysProcAttr = &syscall.SysProcAttr{ | 		s.cmd.SysProcAttr = &syscall.SysProcAttr{ | ||||||
| 			Setsid: true, | 			//Setsid: true, | ||||||
| 		} | 		} | ||||||
|  |  | ||||||
| 		if s.PWD != "" { | 		if s.PWD != "" { | ||||||
| @ -148,7 +148,7 @@ func loadConfig(cfg *Config, configFile string) error { | |||||||
| } | } | ||||||
|  |  | ||||||
| func forwardSignals(services []*Service) { | 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) | 	sigCh := make(chan os.Signal, 1) | ||||||
| 	signal.Notify(sigCh, signals...) | 	signal.Notify(sigCh, signals...) | ||||||
|  |  | ||||||
| @ -169,20 +169,22 @@ func forwardSignals(services []*Service) { | |||||||
| } | } | ||||||
|  |  | ||||||
| func main() { | 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 { | 	if err != nil { | ||||||
| 		printErr(err) | 		printErr(err) | ||||||
| 	} | 	} | ||||||
|  |  | ||||||
| 	var configFile string |  | ||||||
| 	flag.StringVar(&configFile, "c", "./config.json", "JSON config file") | 	flag.StringVar(&configFile, "c", "./config.json", "JSON config file") | ||||||
| 	flag.BoolVar(&verbose, "v", false, "Show debug output") | 	flag.BoolVar(&verbose, "v", false, "Show debug output") | ||||||
| 	flag.Parse() | 	flag.Parse() | ||||||
|  |  | ||||||
| 	var cfg Config |  | ||||||
|  |  | ||||||
| 	err = loadConfig(&cfg, configFile) | 	err = loadConfig(&cfg, configFile) | ||||||
| 	if err != nil { | 	if err != nil { | ||||||
| 		printErr(err) | 		printErr(err) | ||||||
|  | |||||||
		Reference in New Issue
	
	Block a user