Masalah:
Anda ingin melaksanakan lama- menjalankan proses di Golang sambil memenuhi beberapa keperluan:
Percubaan Penyelesaian:
Anda telah mencuba penyelesaian menggunakan exec.Command tetapi ia tidak memenuhi semua keperluan, terutamanya apabila program anda menerima isyarat SIGTERM/SIGKILL.
Perkara Penting untuk Difahami:
Adalah penting untuk ambil perhatian bahawa anda tidak boleh menukar induk proses setelah ia dimulakan - hubungan ibu bapa-anak proses telah ditetapkan.
Perpustakaan Alternatif:
Daripada mencipta semula roda, anda disyorkan untuk menggunakan perpustakaan sedia ada yang menyelesaikan masalah ini. Perpustakaan berikut dicadangkan:
Contoh dengan 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>
Contoh ini menggunakan go-reap untuk memulakan fungsi shell (Sh()) dan laksanakan arahan dalam shell tersebut. Ia menyediakan penuai untuk mengendalikan proses pembersihan kanak-kanak.
Dengan menggunakan perpustakaan yang bereputasi, anda boleh mengelakkan perangkap biasa dan memastikan aplikasi anda berkelakuan seperti yang dimaksudkan.
Atas ialah kandungan terperinci Bagaimanakah saya boleh melaksanakan proses yang berjalan lama di Golang dan menanggalkannya daripada program saya sambil mengawal pengguna, mengubah hala output dan menghalangnya daripada menjadi zombi?. Untuk maklumat lanjut, sila ikut artikel berkaitan lain di laman web China PHP!