//prog(state) runs in a child process func prog(state overseer.State) { // pp.Println(state) log.Println("Prog: start PID: ", os.Getpid(), os.Getppid()) log.Println("Building date: ", buildDate) log.Printf("app (%s) listening at %s...", state.ID, state.Listener.Addr()) http.Handle("/", http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { log.Println("Get handle from ", r.RemoteAddr, r.RequestURI) log.Println("PID=", os.Getpid()) fmt.Fprintln(w, "<h1>Test overseer server</h1>") fmt.Fprintln(w, `<a href="https://github.com/jpillora/overseer">Overseer home page</a>`) fmt.Fprintf(w, "<p>Build date: %s</p>", buildDate) counter++ fmt.Fprintf(w, "<p>My app (%s) says hello %d times</p>\n", state.ID, counter) fmt.Fprintf(w, "<p>PID=%d, PPID=%d</p>\n", os.Getpid(), os.Getppid()) fmt.Fprintf(w, "<p>Application: %s</p>\n", os.Args[0]) fmt.Fprintf(w, "<hr/><p>Args: %v</p>", os.Args[1:]) fmt.Fprintln(w, "<hr/><ul>\n") for _, env := range os.Environ() { fmt.Fprintf(w, "<li>Env: %v</li>\n", env) } fmt.Fprintln(w, "</ul>\n") })) http.Serve(state.Listener, nil) log.Println("Stop server ", os.Getpid()) }
// Serve will serve the given http.Servers and will monitor for signals // allowing for graceful termination (SIGTERM) or restart (SIGUSR2). func Serve(pidfile string, servers ...*http.Server) error { app := &App{Servers: servers, Pidfile: pidfile} inherited, err := app.Listen() if err != nil { return err } if *verbose { if inherited { ppid := os.Getppid() if ppid == 1 { log.Printf("Listening on init activated %s", pprintAddr(app.listeners)) } else { const msg = "Graceful handoff of %s with new pid %d and old pid %d" err = app.WriteParentPidfile(ppid) if err != nil { return err } defer app.DeletePidfile() log.Printf(msg, pprintAddr(app.listeners), os.Getpid(), ppid) } } else { err = app.WritePidfile() if err != nil { return err } defer app.DeletePidfile() const msg = "Serving %s with pid %d" log.Printf(msg, pprintAddr(app.listeners), os.Getpid()) } } app.Serve() // Close the parent if we inherited and it wasn't init that started us. if inherited && os.Getppid() != 1 { if err := grace.CloseParent(); err != nil { return fmt.Errorf("failed to close parent: %s", err) } } err = app.Wait() if *verbose { log.Printf("Exiting pid %d.", os.Getpid()) } return err }
//Called by backup //Kills the parent of the backup func killParent(ppid int) { if ppid != os.Getppid() { log.Println("Main dead. Backup now belongs to pid:", os.Getppid()) } else { log.Println("Missing signals, shutting down main for restart") syscall.Kill(ppid, syscall.SIGINT) <-time.After(300 * time.Millisecond) if ppid == os.Getppid() { syscall.Kill(ppid, syscall.SIGKILL) } } log.Println("Backup going down") return }
//DecodeGobFile adds imports Go-Binary contents that was set previously to the GetValue type with a map and references to strings func DecodeGobFile(suffix string, getValue *GetValue) (err error) { fileLocation := fmt.Sprintf("%v/%v-%v.gob", os.TempDir(), suffix, os.Getppid()) if os.Getenv("CLUE_DEBUG") == "true" { fmt.Println("fileLocation: " + fileLocation) } file, err := os.Open(fileLocation) if err != nil { if os.IsExist(err) { log.Fatal("Problem opening file:", err) } else { return nil } } defer func() { if err := file.Close(); err != nil { log.Fatal("Problem closing file:", err) } }() fileReader := bufio.NewReader(file) decoder := gob.NewDecoder(fileReader) err = decoder.Decode(&getValue) if err != nil { return fmt.Errorf("Problem decoding file: %v", err) } if os.Getenv("CLUE_DEBUG") == "true" { fmt.Printf("getValue: %+v\n", getValue) } return }
//EncodeGobFile encodes a Go-Binary file that is made of a UseValue type with a map. func EncodeGobFile(suffix string, useValue UseValue) (err error) { fileLocation := fmt.Sprintf("%v/%v-%v.gob", os.TempDir(), suffix, os.Getppid()) if os.Getenv("CLUE_DEBUG") == "true" { fmt.Println("fileLocaton: ", fileLocation) fmt.Printf("useValue: %+v\n", useValue) } file, err := os.Create(fileLocation) if err != nil { return fmt.Errorf("Problem creating file: %v", err) } if runtime.GOOS != "windows" { if err = file.Chmod(0600); err != nil { return fmt.Errorf("Problem setting persmission onfile: %v", err) } } defer func() { if err := file.Close(); err != nil { log.Fatal("Problem closing file:", err) } }() fileWriter := bufio.NewWriter(file) encoder := gob.NewEncoder(fileWriter) err = encoder.Encode(useValue) //fmt.Println(useValue) if err != nil { return fmt.Errorf("Problem encoding gob: %v", err) } fileWriter.Flush() return }
func Detect() (string, error) { shell := os.Getenv("SHELL") if shell == "" { shell, shellppid, err := getNameAndItsPpid(os.Getppid()) if err != nil { return "cmd", err // defaulting to cmd } if strings.Contains(strings.ToLower(shell), "powershell") { return "powershell", nil } else if strings.Contains(strings.ToLower(shell), "cmd") { return "cmd", nil } else { shell, _, err := getNameAndItsPpid(shellppid) if err != nil { return "cmd", err // defaulting to cmd } if strings.Contains(strings.ToLower(shell), "powershell") { return "powershell", nil } else if strings.Contains(strings.ToLower(shell), "cmd") { return "cmd", nil } else { fmt.Printf("You can further specify your shell with either 'cmd' or 'powershell' with the --shell flag.\n\n") return "cmd", nil // this could be either powershell or cmd, defaulting to cmd } } } if os.Getenv("__fish_bin_dir") != "" { return "fish", nil } return filepath.Base(shell), nil }
func CurrentProcessInfo() *ProcessInfo { var hasTty bool cwd, _ := os.Getwd() grp, _ := os.Getgroups() // no syscall.Getsid() wrapper on Linux? sid, _, _ := syscall.RawSyscall(syscall.SYS_GETSID, 0, 0, 0) if fh, err := os.Open("/dev/tty"); err == nil { hasTty = true fh.Close() } return &ProcessInfo{ Ppid: os.Getppid(), Pid: os.Getpid(), Uid: os.Getuid(), Euid: os.Geteuid(), Gid: os.Getgid(), Egid: os.Getegid(), Pgrp: syscall.Getpgrp(), Sid: int(sid), Dir: cwd, Groups: grp, Args: os.Args, Env: os.Environ(), HasTty: hasTty, } }
func runTriggers(triggers []*triggers.Trigger, action string) { // For "start" action, if there is a reboot trigger, just do that one. if action == "start" { for _, trigger := range triggers { if trigger.Service == "reboot" { logger.Print("Rebooting") // TODO(rgooch): Remove debugging output. cmd := exec.Command("echo", "reboot") cmd.Stdout = os.Stdout err := cmd.Run() if err != nil { logger.Print(err) } return } } } ppid := fmt.Sprint(os.Getppid()) for _, trigger := range triggers { if trigger.Service == "reboot" && action == "stop" { continue } logger.Printf("Action: service %s %s\n", trigger.Service, action) // TODO(rgooch): Remove debugging output. cmd := exec.Command("run-in-mntns", ppid, "echo", "service", action, trigger.Service) cmd.Stdout = os.Stdout err := cmd.Run() if err != nil { logger.Print(err) } // TODO(rgooch): Implement. } }
//create another main() to run the overseer process //and then convert your old main() into a 'prog(state)' func main() { log.Println("Main: start PID: ", os.Getpid(), os.Getppid()) for _, env := range os.Environ() { if strings.HasPrefix(env, "GO") { log.Println("Main env: ", env) } } // Следует иметь в виду, что oerseer запускает два процесса. // Первый - процесс мониторинга занимается проверкой обновлений и принимает запросы // Второй - собственно процесс обработки запросов. Он перезапускается при обновлении // или если первый процесс получает сигнал SIGUSR2 (по умолчанию, может быть переопределён) // Overseer не является менеджером процессов. Если второй процесс завершится по каким-то причинам, // то будет завершен и первый. overseer.Run(overseer.Config{ // Debug: true, Program: prog, PreUpgrade: checkBinary, Address: ":3000", Fetcher: &fetcher.HTTP{ // Для тестирования в отдаче файла лучше всего воспользоваться `webfsd -F -p 4000 -l -` // Он отдаёт корректные заголовки при изменении файла URL: "http://localhost:4000/overseer-test", Interval: 5 * time.Second, }, }) }
func TestGetNameAndItsPpidOfGrandParent(t *testing.T) { shell, shellppid, err := getNameAndItsPpid(os.Getppid()) shell, shellppid, err = getNameAndItsPpid(shellppid) assert.Equal(t, "powershell.exe", shell) assert.NoError(t, err) }
// StartedByExplorer returns true if the program was invoked by the user double-clicking // on the executable from explorer.exe // // It is conservative and returns false if any of the internal calls fail. // It does not guarantee that the program was run from a terminal. It only can tell you // whether it was launched from explorer.exe func StartedByExplorer() bool { pe, err := getProcessEntry(os.Getppid()) if err != nil { return false } return "explorer.exe" == syscall.UTF16ToString(pe.ExeFile[:]) }
// Lock creates a lockfile which prevents to open more than one instance // of the same node (on the same machine). func (ctx *Context) Lock() (err error) { var f *os.File var p *os.Process var pid int lockFile := path.Join(ctx.storageDir, ctx.nodeName+".lock") if f, err = os.Open(lockFile); err != nil { goto lock } if _, err = fmt.Fscanf(f, "%d", &pid); err != nil && pid == 0 { goto lock } if p, err = os.FindProcess(pid); err == nil && p != nil { if err = p.Signal(syscall.Signal(0)); err == nil { msg := fmt.Sprintf("node '%s' is already running", ctx.NodeName()) return errors.New(msg) } } lock: // Write a lock file. pidstr := []byte(fmt.Sprintf("%d", os.Getppid())) if err = ioutil.WriteFile(lockFile, pidstr, 0644); err != nil { return } return nil }
// CloseParent starts the close process in the parent. This does not wait for // the parent to close and simply sends it the TERM signal. func (p *Process) CloseParent() error { ppid := os.Getppid() if ppid == 1 { // init provided sockets, for example systemd return nil } return syscall.Kill(ppid, syscall.SIGTERM) }
// ListenAndServe listens on the TCP network address srv.Addr and then calls Serve // to handle requests on incoming connections. If srv.Addr is blank, ":http" is // used. func (srv *graceServer) ListenAndServe() (err error) { addr := srv.Addr if addr == "" { addr = ":http" } go srv.handleSignals() l, err := srv.getListener(addr) if err != nil { log.Println(err) return err } srv.GraceListener = newGraceListener(l, srv) if srv.isChild { process, err := os.FindProcess(os.Getppid()) if err != nil { log.Println(err) return err } err = process.Kill() if err != nil { return err } } log.Println(os.Getpid(), srv.Addr) return srv.Serve() }
func loop(wg *sync.WaitGroup) { forceShutdown = make(chan bool, 1) signalChan := make(chan os.Signal, 1) signal.Notify(signalChan, os.Interrupt, syscall.SIGTERM) saveResumeDataTicker := time.Tick(30 * time.Second) for { select { case <-forceShutdown: httpListener.Close() defer wg.Done() return case <-signalChan: forceShutdown <- true case <-time.After(500 * time.Millisecond): consumeAlerts() torrentFS.LoadFileProgress() state := torrentHandle.Status().GetState() if config.exitOnFinish && (state == STATE_FINISHED || state == STATE_SEEDING) { forceShutdown <- true } if os.Getppid() == 1 { forceShutdown <- true } case <-saveResumeDataTicker: saveResumeData(true) } } }
func TestProcExe(t *testing.T) { skipWindows(t) exe := ProcExe{} if assert.NoError(t, exe.Get(os.Getppid())) { assert.Regexp(t, "go(.exe)?", filepath.Base(exe.Name)) } }
func main() { fmt.Printf("%d,%d\n", os.Getpid(), os.Getppid()) for { time.Sleep(time.Second) } }
func TestProcArgs(t *testing.T) { skipWindows(t) args := ProcArgs{} if assert.NoError(t, args.Get(os.Getppid())) { assert.True(t, len(args.List) >= 2) } }
func main() { os.Chdir(filepath.Dir(os.Args[0])) oldQuit() if quit { fmt.Println("quit") return } if os.Getppid() != 1 && daemon { if pid, err := MakeDaemon(); err != nil { fmt.Println(err) os.Exit(1) } else { fmt.Println("daemonize success pid ", pid) os.Exit(0) } } logfh, _ := os.OpenFile("daemon.log", os.O_CREATE|os.O_WRONLY|os.O_APPEND, 0600) log.SetOutput(logfh) defer logfh.Close() time.Sleep(time.Millisecond) pidFileCreate() waitSignal() }
func TestGetNameAndItsPpidOfCurrent(t *testing.T) { shell, shellppid, err := getNameAndItsPpid(os.Getpid()) assert.Equal(t, "shell.test.exe", shell) assert.Equal(t, os.Getppid(), shellppid) assert.NoError(t, err) }
//Called by main //If main dies, we get missed signals -> kill the parent and return func backup() { missed_signal := 0 sigint := make(chan os.Signal, 1) sigquit := make(chan os.Signal, 1) sigusr := make(chan os.Signal, 1) signal.Notify(sigint, syscall.SIGINT) signal.Notify(sigquit, syscall.SIGQUIT) signal.Notify(sigusr, syscall.SIGUSR1) ppid := os.Getppid() log.Println("Backup started by pid: ", ppid) for { select { case <-sigusr: missed_signal = 0 time.Sleep(200 * time.Millisecond) case <-sigint: log.Println("Backup caught SIGINT, ignore") case <-sigquit: log.Println("Received SIGQUIT. Shutting down backup") os.Exit(0) default: if missed_signal == 3 { killParent(ppid) return } missed_signal += 1 time.Sleep(200 * time.Millisecond) } } }
func TestBusy(t *testing.T) { path, err := filepath.Abs("test_lockfile.pid") if err != nil { t.Fatal(err) return } pid := os.Getppid() if err := ioutil.WriteFile(path, []byte(strconv.Itoa(pid)+"\n"), 0666); err != nil { t.Fatal(err) return } defer os.Remove(path) lf, err := New(path) if err != nil { t.Fatal(err) return } got := lf.TryLock() if got != ErrBusy { t.Fatalf("expected error %q, got %v", ErrBusy, got) return } }
func runShell(version string) { if os.Getenv("GOBU") != "" { log.Fatalln("Already in boostraped env!") } os.Setenv("GOBU", "1") log.Println(">> You are now in a new GOBU shell. To exit, type 'exit'") shell := os.Getenv("SHELL") if runtime.GOOS == "windows" { parentID := os.Getppid() parentProcess, err := ps.FindProcess(parentID) if err != nil { log.Fatalln(err) } shell = parentProcess.Executable() } shellBinary := resolveBinary(shell) run(version, shellBinary, []string{shellBinary}) log.Println("Exited gobu shell") }
func newTermMonitor() (m *termMonitor) { ppid := os.Getppid() m = new(termMonitor) m.sigChan = make(chan os.Signal) m.handlerChan = make(chan int) signal.Notify(m.sigChan, syscall.SIGINT, syscall.SIGTERM) // If tor supports feature #15435, we can use Stdin being closed as an // indication that tor has died, or wants the PT to shutdown for any // reason. if ptShouldExitOnStdinClose() { go m.termOnStdinClose() } else { // Instead of feature #15435, use various kludges and hacks: // * Linux - Platform specific code that should always work. // * Other U*IX - Somewhat generic code, that works unless the // parent dies before the monitor is initialized. if termMonitorOSInit != nil { // Errors here are non-fatal, since it might still be // possible to fall back to a generic implementation. if err := termMonitorOSInit(m); err == nil { return } } if runtime.GOOS != "windows" { go m.termOnPPIDChange(ppid) } } return }
// CloseParentService Send TERM signal to old service processor. func (gs *GraceServer) CloseParentServer() error { parentPID := os.Getppid() if parentPID == 1 { return nil } return syscall.Kill(parentPID, syscall.SIGQUIT) }
// Lock creates a lockfile which prevents to open more than one instance // of the same node (on the same machine). func (ctx *Context) Lock() (err error) { var f *os.File var p *os.Process var pid int lockFile := path.Join(ctx.storageDir, ctx.nodeName+".lock") if f, err = os.Open(lockFile); err != nil { goto lock } if _, err = fmt.Fscanf(f, "%d", &pid); err != nil && pid == 0 { goto lock } if p, err = os.FindProcess(pid); err == nil && p != nil { if err = p.Signal(os.UnixSignal(0)); err == nil { return errors.New( fmt.Sprintf("node '%s' is already running", ctx.NodeName())) } } lock: // Write a lock file. if f, err = os.Create(lockFile); err == nil { pid := os.Getppid() f.Write([]byte(fmt.Sprintf("%d", pid))) f.Close() } return nil }
func main() { // 获取系统名字 fmt.Println(os.Hostname()) // 获取系统内存 fmt.Println(os.Getpagesize()) // 获取系统环境变量 for index, env := range os.Environ() { fmt.Println(index, " : ", env) } // 获取指定key的环境变量,环境变量不区分大小写 fmt.Println("当前系统目录为:", os.Getenv("windir")) // 设置环境变量 fmt.Println("cody的环境变量为:", os.Getenv("cody")) os.Setenv("Cody", "guo") fmt.Println("cody的环境变量为:", os.Getenv("cody")) // 删除所有环境变量 os.Clearenv() fmt.Println(os.Environ()) // 如果存在os.Exit()就不会执行defer // defer fmt.Println("我在退出吗?") // os.Exit(0) fmt.Println("程序已退出,不打印了...") fmt.Println(os.Getuid(), os.Getgid()) fmt.Println(os.Getgroups()) fmt.Println(os.Getpid(), os.Getppid()) fmt.Println(os.TempDir()) }
func main() { // Make sure we are properly multithreaded. runtime.GOMAXPROCS(runtime.NumCPU()) logging.SetFormatter(logging.MustStringFormatter("%{time:2006-01-02 15:04:05} %{level:.4s} %{module:-15s} %{message}")) logging.SetBackend(logging.NewLogBackend(os.Stdout, "", 0)) for _, line := range strings.Split(PulsarLogo, "\n") { log.Info(line) } log.Info("Version: %s Git: %s Go: %s", util.Version, util.GitCommit, runtime.Version()) conf := config.Reload() ensureSingleInstance() Migrate() xbmc.CloseAllDialogs() log.Info("Addon: %s v%s", conf.Info.Id, conf.Info.Version) btService := bittorrent.NewBTService(*makeBTConfiguration(conf)) var shutdown = func() { log.Info("Shutting down...") btService.Close() log.Info("Bye bye") os.Exit(0) } var watchParentProcess = func() { for { // did the parent die? shutdown! if os.Getppid() == 1 { log.Warning("Parent shut down. Me too.") go shutdown() break } time.Sleep(1 * time.Second) } } go watchParentProcess() http.Handle("/", api.Routes(btService)) http.Handle("/files/", http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { handler := http.StripPrefix("/files/", http.FileServer(bittorrent.NewTorrentFS(btService, config.Get().DownloadPath))) handler.ServeHTTP(w, r) })) http.Handle("/reload", http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { btService.Reconfigure(*makeBTConfiguration(config.Reload())) })) http.Handle("/shutdown", http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { shutdown() })) xbmc.Notify("Pulsar", "Pulsar daemon has started", config.AddonIcon()) http.ListenAndServe(":"+strconv.Itoa(config.ListenPort), nil) }
//DeleteGobFile deletes a specific cache file stored as suffix func DeleteGobFile(suffix string) (err error) { fileLocation := fmt.Sprintf("%v/%v-%v.gob", os.TempDir(), suffix, os.Getppid()) err = os.Remove(fileLocation) if err != nil { return fmt.Errorf("Problem removing file: %v", err) } return nil }
// watchParent periodically checks whether the parent process has exited and, if // so, kills the current process. Meant to be run in a goroutine. func watchParent() { for { if os.Getppid() == 1 { log.Fatal("gosh: parent process has exited") } time.Sleep(time.Second) } }