次の要件を満たす Go で新しいプロセスを開始する必要があります。
- Goプロセスが終了した後も開始プロセスは実行される必要がある
- 実行しているUnixユーザー/グループを設定できるようにする必要がある
- 継承された環境変数を設定できるようにする必要がある
- std in/out/errを制御する必要があります
ここに試みがあります:
var attr = os.ProcAttr {
Dir: "/bin",
Env: os.Environ(),
Files: []*os.File{
os.Stdin,
"stdout.log",
"stderr.log",
},
}
process, err := os.StartProcess("sleep", []string{"1"}, &attr)
これは正常に動作しますが、要件から見ると次の欠点があります。
- Unixユーザー/グループを設定する方法がない
- 開始されたプロセスは、Goプロセス(親)が停止すると終了します。
物事を簡素化できる場合にのみ、これを Linux 上で実行する必要があります。
ベストアンサー1
- process.Releaseを使用すると、子プロセスを親プロセスから切り離し、親プロセスの終了後も子プロセスを存続させることができます。
- *os.ProcAttr.Sys.Credentials 属性の定義を見てください。この属性を使用すると、プロセス ユーザーとグループ ID を設定できるようです。
これはあなたの例の実際のバージョンです(プロセス ID が実際に設定されているかどうかは確認していません)
package main
import "fmt"
import "os"
import "syscall"
const (
UID = 501
GUID = 100
)
func main() {
// The Credential fields are used to set UID, GID and attitional GIDS of the process
// You need to run the program as root to do this
var cred = &syscall.Credential{ UID, GUID, []uint32{} }
// the Noctty flag is used to detach the process from parent tty
var sysproc = &syscall.SysProcAttr{ Credential:cred, Noctty:true }
var attr = os.ProcAttr{
Dir: ".",
Env: os.Environ(),
Files: []*os.File{
os.Stdin,
nil,
nil,
},
Sys:sysproc,
}
process, err := os.StartProcess("/bin/sleep", []string{"/bin/sleep", "100"}, &attr)
if err == nil {
// It is not clear from docs, but Realease actually detaches the process
err = process.Release();
if err != nil {
fmt.Println(err.Error())
}
} else {
fmt.Println(err.Error())
}
}