Golangデーモン

約1年前、小さなネットワークサービスを実装するLinuxデーモンを作成する必要がありました。 当時、私はGoを積極的に研究し、この言語が本当に好きだったので、賛否両論を検討した後、それにタスクを実装することにしました。 さらに、Goは既に安定しており、バージョン1.0.1でした。



私が直面しなければならなかった落とし穴について読んでください、カットの下で読んでください、しかし、私はすぐに予約をします:Goでの悪魔実装の微妙さだけを説明します。 「デーモン」とは何か、またはプロセスがどのように悪魔化されるのかわからない場合は、まずGoogleまたはLinuxデーモンハブで検索するか、記事の最後にあるリンクのリストを確認してください。



しかし、悪魔に戻って。 最初、私は古典的に行動することにしました:



標準のsyscallパッケージにクリーンフォークが存在しなかったからといって私を止めることはできず、疑念を抱くことすらありませんでした。 私はこのようなことをしました(簡略化された):

ret, _, err := syscall.Syscall(syscall.SYS_FORK, 0, 0, 0) if err != 0 { os.Exit(2) } if ret > 0 { //   os.Exit(0) }
      
      





すべてのポイントを実装し、デーモンを実行し、 ps -eafw



および lsof -p , , .



, Go os/signal. , . fork, . . , code.google.com/p/go/issues/detail?id=227, . : Go fork, .. , , (goroutines), , , .



. , fork . os/signal, , :

func init() { signal_enable(0) // first call - initialize go loop() }






, , loop() . main(). loop() . , fork, loop(). , fork. init() fork, .



os/signal , init() Init() fork. .



- , : - - . , - , . , StartProcess . , , fork exec . , , , - . , . , _GO_DAEMON=1



.



:

const ( envVarName = "_GO_DAEMON" envVarValue = "1" ) func Reborn(umask uint32, workDir string) (err error) { if !WasReborn() { var path string if path, err = filepath.Abs(os.Args[0]); err != nil { return } cmd := exec.Command(path, os.Args[1:]...) envVar := fmt.Sprintf("%s=%s", envVarName, envVarValue) cmd.Env = append(os.Environ(), envVar) if err = cmd.Start(); err != nil { return } os.Exit(0) } syscall.Umask(int(umask)) if len(workDir) == 0 { if err = os.Chdir(workDir); err != nil { return } } _, err = syscall.Setsid() return } func WasReborn() bool { return os.Getenv(envVarName) == envVarValue }





. os/exec - StartProcess .



, , , , Reborn(), . - WasReborn(). (, ), Reborn(), Reborn() ( panic()), - /dev/null.



, , github: go-daemon . pid- . Go. - .



:

- Wikipedia

linux

golang.org




     lsof -p ,  ,         . 
      



, Go os/signal. , . fork, . . , code.google.com/p/go/issues/detail?id=227, . : Go fork, .. , , (goroutines), , , .



. , fork . os/signal, , :

func init() { signal_enable(0) // first call - initialize go loop() }






, , loop() . main(). loop() . , fork, loop(). , fork. init() fork, .



os/signal , init() Init() fork. .



- , : - - . , - , . , StartProcess . , , fork exec . , , , - . , . , _GO_DAEMON=1



.



:

const ( envVarName = "_GO_DAEMON" envVarValue = "1" ) func Reborn(umask uint32, workDir string) (err error) { if !WasReborn() { var path string if path, err = filepath.Abs(os.Args[0]); err != nil { return } cmd := exec.Command(path, os.Args[1:]...) envVar := fmt.Sprintf("%s=%s", envVarName, envVarValue) cmd.Env = append(os.Environ(), envVar) if err = cmd.Start(); err != nil { return } os.Exit(0) } syscall.Umask(int(umask)) if len(workDir) == 0 { if err = os.Chdir(workDir); err != nil { return } } _, err = syscall.Setsid() return } func WasReborn() bool { return os.Getenv(envVarName) == envVarValue }





. os/exec - StartProcess .



, , , , Reborn(), . - WasReborn(). (, ), Reborn(), Reborn() ( panic()), - /dev/null.



, , github: go-daemon . pid- . Go. - .



:

- Wikipedia

linux

golang.org




lsof -p , , .



, Go os/signal. , . fork, . . , code.google.com/p/go/issues/detail?id=227, . : Go fork, .. , , (goroutines), , , .



. , fork . os/signal, , :

func init() { signal_enable(0) // first call - initialize go loop() }






, , loop() . main(). loop() . , fork, loop(). , fork. init() fork, .



os/signal , init() Init() fork. .



- , : - - . , - , . , StartProcess . , , fork exec . , , , - . , . , _GO_DAEMON=1



.



:

const ( envVarName = "_GO_DAEMON" envVarValue = "1" ) func Reborn(umask uint32, workDir string) (err error) { if !WasReborn() { var path string if path, err = filepath.Abs(os.Args[0]); err != nil { return } cmd := exec.Command(path, os.Args[1:]...) envVar := fmt.Sprintf("%s=%s", envVarName, envVarValue) cmd.Env = append(os.Environ(), envVar) if err = cmd.Start(); err != nil { return } os.Exit(0) } syscall.Umask(int(umask)) if len(workDir) == 0 { if err = os.Chdir(workDir); err != nil { return } } _, err = syscall.Setsid() return } func WasReborn() bool { return os.Getenv(envVarName) == envVarValue }





. os/exec - StartProcess .



, , , , Reborn(), . - WasReborn(). (, ), Reborn(), Reborn() ( panic()), - /dev/null.



, , github: go-daemon . pid- . Go. - .



:

- Wikipedia

linux

golang.org




     lsof -p ,  ,         . 
      



, Go os/signal. , . fork, . . , code.google.com/p/go/issues/detail?id=227, . : Go fork, .. , , (goroutines), , , .



. , fork . os/signal, , :

func init() { signal_enable(0) // first call - initialize go loop() }






, , loop() . main(). loop() . , fork, loop(). , fork. init() fork, .



os/signal , init() Init() fork. .



- , : - - . , - , . , StartProcess . , , fork exec . , , , - . , . , _GO_DAEMON=1



.



:

const ( envVarName = "_GO_DAEMON" envVarValue = "1" ) func Reborn(umask uint32, workDir string) (err error) { if !WasReborn() { var path string if path, err = filepath.Abs(os.Args[0]); err != nil { return } cmd := exec.Command(path, os.Args[1:]...) envVar := fmt.Sprintf("%s=%s", envVarName, envVarValue) cmd.Env = append(os.Environ(), envVar) if err = cmd.Start(); err != nil { return } os.Exit(0) } syscall.Umask(int(umask)) if len(workDir) == 0 { if err = os.Chdir(workDir); err != nil { return } } _, err = syscall.Setsid() return } func WasReborn() bool { return os.Getenv(envVarName) == envVarValue }





. os/exec - StartProcess .



, , , , Reborn(), . - WasReborn(). (, ), Reborn(), Reborn() ( panic()), - /dev/null.



, , github: go-daemon . pid- . Go. - .



:

- Wikipedia

linux

golang.org




lsof -p , , .



, Go os/signal. , . fork, . . , code.google.com/p/go/issues/detail?id=227, . : Go fork, .. , , (goroutines), , , .



. , fork . os/signal, , :

func init() { signal_enable(0) // first call - initialize go loop() }






, , loop() . main(). loop() . , fork, loop(). , fork. init() fork, .



os/signal , init() Init() fork. .



- , : - - . , - , . , StartProcess . , , fork exec . , , , - . , . , _GO_DAEMON=1



.



:

const ( envVarName = "_GO_DAEMON" envVarValue = "1" ) func Reborn(umask uint32, workDir string) (err error) { if !WasReborn() { var path string if path, err = filepath.Abs(os.Args[0]); err != nil { return } cmd := exec.Command(path, os.Args[1:]...) envVar := fmt.Sprintf("%s=%s", envVarName, envVarValue) cmd.Env = append(os.Environ(), envVar) if err = cmd.Start(); err != nil { return } os.Exit(0) } syscall.Umask(int(umask)) if len(workDir) == 0 { if err = os.Chdir(workDir); err != nil { return } } _, err = syscall.Setsid() return } func WasReborn() bool { return os.Getenv(envVarName) == envVarValue }





. os/exec - StartProcess .



, , , , Reborn(), . - WasReborn(). (, ), Reborn(), Reborn() ( panic()), - /dev/null.



, , github: go-daemon . pid- . Go. - .



:

- Wikipedia

linux

golang.org







All Articles