문제:
긴- 여러 요구 사항을 충족하면서 Golang에서 프로세스를 실행합니다.
시도한 해결 방법:
exec.Command를 사용하여 솔루션을 시도했지만 특히 프로그램이 SIGTERM/SIGKILL 신호를 수신하는 경우 모든 요구 사항을 충족하지 않습니다.
이해해야 할 핵심 사항:
프로세스가 시작된 후에는 프로세스의 상위를 변경할 수 없다는 점에 유의하는 것이 중요합니다. 프로세스의 상위-하위 관계는 고정되어 있습니다.
대체 라이브러리:
바퀴를 다시 만드는 대신 이 문제를 해결하는 기존 라이브러리를 사용하는 것이 좋습니다. 다음 라이브러리가 제안됩니다:
go-reap의 예:
<code class="go">import ( "fmt" "os" "os/exec" "strings" "sync" "time" "github.com/fatih/color" "github.com/hashicorp/go-reap" ) func main() { if reap.IsSupported() { done := make(chan struct{}) var reapLock sync.RWMutex pids := make(reap.PidCh, 1) errors := make(reap.ErrorCh, 1) go reap.ReapChildren(pids, errors, done, &reapLock) go report(pids, errors, done) // Here is where you would start your long-running process Sh() close(done) } else { fmt.Println("Sorry, go-reap isn't supported on your platform.") } } func report(pids reap.PidCh, errors reap.ErrorCh, done chan struct{}) { sprintf := color.New(color.FgWhite, color.Bold).SprintfFunc() for ;; { select { case pid := <-pids: println(sprintf("raeper pid %d", pid)) case err := <-errors: println(sprintf("raeper er %s", err)) case <-done: return } } } func Sh() { args := os.Args[1:] script := args[0:0] if len(args) >= 1 { if args[0] == "-c" { script = args[1:] } } if len(script) == 0 { fn.CyanBold("cmd: expecting sh -c 'foobar'") os.Exit(111) } var cmd *exec.Cmd parts, _ := shlex.Split(strings.Join(script, " ")) if len(parts) >= 2 { cmd = fn.Merge(exec.Command(parts[0], parts[1:]...), nil) } if len(parts) == 1 { cmd = fn.Merge(exec.Command(parts[0]), nil) } // ... Here you can customize how the process is started and controlled if fn.IfEnv("HANG") { fn.CyanBold("cmd: %v\n start", parts) ex := cmd.Start() if ex != nil { fn.CyanBold("cmd %v err: %s", parts, ex) } go func() { time.Sleep(time.Millisecond * 100) errw := cmd.Wait() if errw != nil { fn.CyanBold("cmd %v err: %s", parts, errw) } else { fn.CyanBold("cmd %v all done.", parts) } }() fn.CyanBold("cmd: %v\n dispatched, hanging forever (i.e. to keep docker running)", parts) for { time.Sleep(time.Millisecond * time.Duration(fn.EnvInt("HANG", 2888))) fn.SystemCyan("/bin/ps", "-e", "-o", "stat,comm,user,etime,pid,ppid") } } else { if fn.IfEnv("NOWAIT") { ex := cmd.Start() if ex != nil { fn.CyanBold("cmd %v start err: %s", parts, ex) } } else { ex := cmd.Run() if ex != nil { fn.CyanBold("cmd %v run err: %s", parts, ex) } } fn.CyanBold("cmd %v\n dispatched, exit docker.", parts) } }</code>
이 예 go-reap을 사용하여 쉘(Sh() 함수)을 시작하고 해당 쉘 내에서 명령을 실행합니다. 하위 프로세스 정리를 처리하도록 리퍼를 설정합니다.
평판이 좋은 라이브러리를 사용하면 일반적인 함정을 피하고 애플리케이션이 의도한 대로 작동하는지 확인할 수 있습니다.
위 내용은 사용자를 제어하고 출력을 리디렉션하며 좀비가 되는 것을 방지하면서 Golang에서 장기 실행 프로세스를 실행하고 이를 내 프로그램에서 분리하려면 어떻게 해야 합니까?의 상세 내용입니다. 자세한 내용은 PHP 중국어 웹사이트의 기타 관련 기사를 참조하세요!