// StartProcess starts a new process with the program, arguments and attributes // specified by name, argv and attr. func StartProcess(name string, argv []string, attr *ProcAttr) (p *Process, err Error) { sysattr := &syscall.ProcAttr{ Dir: attr.Dir, Env: attr.Env, } if sysattr.Env == nil { sysattr.Env = Environ() } // Create array of integer (system) fds. intfd := make([]int, len(attr.Files)) for i, f := range attr.Files { if f == nil { intfd[i] = -1 } else { intfd[i] = f.Fd() } } sysattr.Files = intfd pid, h, e := syscall.StartProcess(name, argv, sysattr) if iserror(e) { return nil, &PathError{"fork/exec", name, Errno(e)} } return newProcess(pid, h), nil }
func startProcess(name string, argv []string, attr *ProcAttr) (p *Process, err error) { // If there is no SysProcAttr (ie. no Chroot or changed // UID/GID), double-check existence of the directory we want // to chdir into. We can make the error clearer this way. if attr != nil && attr.Sys == nil && attr.Dir != "" { if _, err := Stat(attr.Dir); err != nil { pe := err.(*PathError) pe.Op = "chdir" return nil, pe } } sysattr := &syscall.ProcAttr{ Dir: attr.Dir, Env: attr.Env, Sys: attr.Sys, } if sysattr.Env == nil { sysattr.Env = Environ() } for _, f := range attr.Files { sysattr.Files = append(sysattr.Files, f.Fd()) } pid, h, e := syscall.StartProcess(name, argv, sysattr) if e != nil { return nil, &PathError{"fork/exec", name, e} } return newProcess(pid, h), nil }
func spawnServer(cl libkb.CommandLine) (err error) { var files []uintptr var cmd string var args []string var devnull, log *os.File var pid int defer func() { if err != nil { if devnull != nil { devnull.Close() } if log != nil { log.Close() } } }() if devnull, err = os.OpenFile("nul", os.O_RDONLY, 0); err != nil { return } files = append(files, devnull.Fd()) if G.Env.GetSplitLogOutput() { files = append(files, uintptr(1), uintptr(2)) } else { if _, log, err = libkb.OpenLogFile(); err != nil { return } files = append(files, log.Fd(), log.Fd()) } // On 'nix this would include Setsid: true, which means // the new process inherits the session/terminal from the parent. // This is default on windows and need not be specified. attr := syscall.ProcAttr{ Env: os.Environ(), Files: files, } cmd, args, err = makeServerCommandLine(cl) if err != nil { return err } pid, _, err = syscall.StartProcess(cmd, args, &attr) if err != nil { err = fmt.Errorf("Error in StartProcess: %s", err) } else { G.Log.Info("Starting background server with pid=%d", pid) } return err }
func (this *Fetcher) startPhantomJSServer(phantomJSPath, fetcherJSPath string) error { args := []string{"phantomjs", fetcherJSPath, this.ProxyPort} execSpec := &syscall.ProcAttr{ Env: os.Environ(), Files: []uintptr{os.Stdin.Fd(), os.Stdout.Fd(), os.Stderr.Fd()}, } pid, handlePtr, execErr := syscall.StartProcess(phantomJSPath, args, execSpec) this.phantomJSPid = pid this.phantomJSHandlePtr = handlePtr return execErr }
func main() { daemon := flag.Bool("daemon", false, "Indicate it's daemon process. Never use it in command line.") flag.Parse() if *daemon { fd, err := syscall.Open("/dev/null", syscall.O_RDWR, 0) if err != nil { panic(err) } syscall.Dup2(fd, syscall.Stdin) syscall.Dup2(fd, syscall.Stdout) syscall.Dup2(fd, syscall.Stderr) if fd > syscall.Stderr { syscall.Close(fd) } } // start gio as daemon process if !*daemon { args := append([]string{os.Args[0], "-daemon"}, os.Args[1:]...) attr := syscall.ProcAttr{} _, _, err := syscall.StartProcess(os.Args[0], args, &attr) if err != nil { panic(err) return } return } router := routes.NewRouter() for _, function := range functions.Functions { router.Get(function.Path, funcwrapper(function.Func)) router.Post(function.Path, funcwrapper(function.Func)) } s := &http.Server{ Addr: ":1234", Handler: router, ReadTimeout: 10 * time.Second, WriteTimeout: 10 * time.Second, MaxHeaderBytes: 1 << 20, } err := s.ListenAndServe() if err != nil { log.Fatal(err) } }
func spawnServer(g *libkb.GlobalContext, cl libkb.CommandLine, forkType keybase1.ForkType) (pid int, err error) { var files []uintptr var cmd string var args []string var devnull *os.File defer func() { if err != nil && devnull != nil { devnull.Close() } }() // Failing to open nul is non-fatal here. devnull, err = os.OpenFile("nul", os.O_RDONLY, 0) if err != nil { G.Log.Warning("Cannot open nul: %v", err) // 0 is an invalid handle, but more importantly it will // not be passed to DuplicateHandle by Go. This works // with Go 1.6, but is hacky. This code path is taken // only on systems that are broken to begin with... files = append(files, 0, 0, 0) } else { nullfd := devnull.Fd() files = append(files, nullfd, nullfd, nullfd) } // On 'nix this would include Setsid: true, which means // the new process inherits the session/terminal from the parent. // This is default on windows and need not be specified. attr := syscall.ProcAttr{ Env: os.Environ(), Files: files, } cmd, args, err = makeServerCommandLine(g, cl, forkType) if err != nil { return } pid, _, err = syscall.StartProcess(cmd, args, &attr) if err != nil { err = fmt.Errorf("Error in StartProcess: %s", err) } else { G.Log.Info("Starting background server with pid=%d", pid) } return }
func main() { argsIndex := 1 // 0 is the name of this program, 1 is either the one to launch or the "wait" option if len(os.Args) < 2 { log.Fatal("ERROR: no arguments. Use [-wait] programname [arg arg arg]\n") } // Do this awkward thing so we can pass along the rest of the command line as-is doWait := false doHide := true for i := 1; i < 3 && (i+1) < len(os.Args); i++ { if strings.EqualFold(os.Args[argsIndex], "-wait") { argsIndex++ doWait = true } else if strings.EqualFold(os.Args[argsIndex], "-show") { argsIndex++ doHide = false } } attr := &syscall.ProcAttr{ Files: []uintptr{uintptr(syscall.Stdin), uintptr(syscall.Stdout), uintptr(syscall.Stderr)}, Env: syscall.Environ(), Sys: &syscall.SysProcAttr{ HideWindow: doHide, CreationFlags: flagCreateNewConsole, }, } fmt.Printf("Launching %s with args %v\n", os.Args[argsIndex], os.Args[argsIndex:]) pid, handle, err := syscall.StartProcess(os.Args[argsIndex], os.Args[argsIndex:], attr) fmt.Printf("%v, %v, %v\n", pid, handle, err) if doWait { p, err := os.FindProcess(pid) if err != nil { fmt.Printf("Launcher can't find %d\n", pid) } pstate, err := p.Wait() if err == nil && pstate.Success() { time.Sleep(100 * time.Millisecond) } else { fmt.Printf("Unsuccessful wait: Error %v, pstate %v\n", err, *pstate) } } }
func StartHttpServe(lis net.Listener, mux http.Handler) { // start http serve go func() { err := http.Serve(lis, mux) if err != nil { log.Fatal("ListenAndServe: ", err.Error()) } }() //received Signal ch := make(chan os.Signal) signal.Notify(ch, syscall.SIGINT, syscall.SIGUSR1, syscall.SIGUSR2, syscall.SIGHUP) //#WORKER is a new process tag. //get the current process args ... newArgs := append(os.Args, "#WORKER") for { sig := <-ch //log.Println("Signal received:", sig) switch sig { case syscall.SIGHUP: log.Println("get sighup sighup") case syscall.SIGINT: log.Println("get SIGINT ,exit!") os.Exit(1) case syscall.SIGUSR1: log.Println("get usr1 signal") //close the net if err := lis.Close(); err != nil { log.Println("Close ERROR ", err) } log.Println("Close connect!") attr := syscall.ProcAttr{ Env: os.Environ(), } //start a new same process if _, _, err := syscall.StartProcess(os.Args[0], newArgs, &attr); err != nil { log.Println(err) } //exit current process. return case syscall.SIGUSR2: log.Println("usr2 ") } } }
func startProcess(name string, argv []string, attr *ProcAttr) (p *Process, err error) { sysattr := &syscall.ProcAttr{ Dir: attr.Dir, Env: attr.Env, Sys: attr.Sys, } for _, f := range attr.Files { sysattr.Files = append(sysattr.Files, f.Fd()) } pid, h, e := syscall.StartProcess(name, argv, sysattr) if e != nil { return nil, &PathError{"fork/exec", name, e} } return newProcess(pid, h), nil }
// StartProcess starts a new process with the program, arguments and attributes // specified by name, argv and attr. // // StartProcess is a low-level interface. The exec package provides // higher-level interfaces. func StartProcess(name string, argv []string, attr *ProcAttr) (p *Process, err Error) { sysattr := &syscall.ProcAttr{ Dir: attr.Dir, Env: attr.Env, Sys: attr.Sys, } if sysattr.Env == nil { sysattr.Env = Environ() } for _, f := range attr.Files { sysattr.Files = append(sysattr.Files, f.Fd()) } pid, h, e := syscall.StartProcess(name, argv, sysattr) if iserror(e) { return nil, &PathError{"fork/exec", name, Errno(e)} } return newProcess(pid, h), nil }
// StartProcess forks the current process and execs argv0, stopping the // new process after the exec syscall. See os.StartProcess for additional // details. func StartProcess(argv0 string, argv []string, attr *os.ProcAttr) (Process, os.Error) { sysattr := &syscall.ProcAttr{ Dir: attr.Dir, Env: attr.Env, Sys: &syscall.SysProcAttr{ Ptrace: true, }, } p := newProcess(-1) // Create array of integer (system) fds. intfd := make([]int, len(attr.Files)) for i, f := range attr.Files { if f == nil { intfd[i] = -1 } else { intfd[i] = f.Fd() } } sysattr.Files = intfd // Fork from the monitor thread so we get the right tracer pid. err := p.do(func() os.Error { pid, _, errno := syscall.StartProcess(argv0, argv, sysattr) if errno != 0 { return &os.PathError{"fork/exec", argv0, os.Errno(errno)} } p.pid = pid // The process will raise SIGTRAP when it reaches execve. _, err := p.newThread(pid, syscall.SIGTRAP, false) return err }) if err != nil { p.stopMonitor(err) return nil, err } return p, nil }
func main() { // Get a new logger instance //log := l4g.NewLogger() // Create a default logger that is logging messages of FINE or higher log.AddFilter("file", log.FINE, log.NewFileLogWriter(filename, false)) //log.Close() /* Can also specify manually via the following: (these are the defaults) */ flw := log.NewFileLogWriter(filename, false) //flw.SetFormat("[%D %T] [%L] (%S) %M") //flw.SetRotate(false) //flw.SetRotateSize(0) //flw.SetRotateLines(0) //flw.SetRotateDaily(false) log.AddFilter("file", log.FINE, flw) mux := http.NewServeMux() staticDirHandler(mux, "/public/", "./public", 0) mux.HandleFunc("/", safeHandler(indexHandler)) mux.HandleFunc("/register", safeHandler(registerHandler)) mux.HandleFunc("/login", safeHandler(loginHandler)) mux.HandleFunc("/save", safeHandler(saveHandler)) mux.HandleFunc("/user_list", safeHandler(userListHandler)) lis, err := net.Listen("tcp", ":9090") check(err) go func() { http.Serve(lis, mux) //err := http.ListenAndServe(":8080", mux) if err != nil { log.Critical("ListenAndServe: ", err.Error()) } }() ch := make(chan os.Signal) signal.Notify(ch, syscall.SIGINT, syscall.SIGUSR1, syscall.SIGUSR2, syscall.SIGHUP) //#WORKER is a new process tag. //newArgs := append(os.Args, "#WORKER") attr := syscall.ProcAttr{ Env: os.Environ(), } for { sig := <-ch //log.Info("Signal received:", sig) switch sig { case syscall.SIGHUP: log.Info("get sighup sighup") case syscall.SIGINT: log.Info("get SIGINT ,exit!") os.Exit(1) case syscall.SIGUSR1: log.Info("usr1") //close the net lis.Close() log.Info("close connect") if _, _, err := syscall.StartProcess(os.Args[0], os.Args, &attr); err != nil { check(err) } //exit current process. return case syscall.SIGUSR2: log.Info("usr2 ") } } }
func main() { port := flag.Int("port", 0, "Port to serve http request. By default, the port is the last port you've used.") dir := flag.String("dir", "", "Dir served as www root. By default, current dir will be served.") alias := flag.String("alias", "", "URL alias to serve. By default, dir name will be used as alias.") remove := flag.Bool("remove", false, "Remove current dir so that no one can visit it thru http anymore.") list := flag.Bool("list", false, "List all running servers and hosted dirs.") worker := flag.Bool("worker", false, "Indicate it's a worker process. It's used to daemonize handyhttpd. Never use it in command line.") quit := flag.Bool("quit", false, "Quit server completely.") flag.Parse() tempdir := os.TempDir() file, err := os.OpenFile(tempdir+"/"+HANDY_LOG_FILENAME, os.O_APPEND|os.O_CREATE|os.O_RDWR, 0666) if err != nil { log.Println("cannot open log file to write. filename:", tempdir+"/"+HANDY_LOG_FILENAME, "err:", err) log.Println("print log to stdout now") file = os.Stdout } // worker need to close all std in/out/err if *worker { fd, err := syscall.Open("/dev/null", syscall.O_RDWR, 0) if err != nil { fmt.Println("cannot open /dev/null", "err:", err) panic(err) } syscall.Dup2(fd, syscall.Stdin) syscall.Dup2(fd, syscall.Stdout) syscall.Dup2(fd, syscall.Stderr) if fd > syscall.Stderr { syscall.Close(fd) } } gLogger = log.New(file, "", log.LstdFlags) gLogger.Printf("parsed params. [port: %d] [dir: %s] [alias: %s] [remove: %t] [list: %t] [quit: %t]\n", *port, *dir, *alias, *remove, *list, *quit) root := *dir if root == "" { root, _ = os.Getwd() } pattern := *alias if pattern == "" { pattern = filepath.Base(root) } socket := tempdir + "/" + HANDY_SOCK_FILENAME l, err := net.Listen("unix", socket) // there is a handyhttpd running. notify it with current options. if err != nil { // hack http client's transport to force it to use unix socket rather than tcp client := http.Client{ Transport: &http.Transport{ Dial: func(n, addr string) (conn net.Conn, err error) { return net.Dial("unix", socket) }, }, } var r *http.Response if *list { r, err = client.Get("http://localhost/list") } else if *quit { r, err = client.Get("http://localhost/quit") } else { var verb string if *remove { verb = "remove" } else { verb = "add" } // format is: // GET /?verb=add&alias=abc&dir=/path/to/www/root&port=9696 r, err = client.Get( fmt.Sprintf("http://localhost/?verb=%s&alias=%s&dir=%s&port=%d", verb, url.QueryEscape(pattern), url.QueryEscape(root), *port)) } if err != nil { gLogger.Println("cannot connect handy server. err:", err) return } if r.StatusCode != 200 { gLogger.Println("handy server denies the request. code:", r.StatusCode) return } io.Copy(os.Stdout, r.Body) return } defer l.Close() // daemonize handyhttpd if !*worker { args := append([]string{os.Args[0], "-worker"}, os.Args[1:]...) exec := os.Args[0] // if exec is called without any path separator, it must be in a PATH dir. if !strings.ContainsRune(exec, os.PathSeparator) { path := os.Getenv("PATH") paths := strings.Split(path, fmt.Sprintf("%c", os.PathListSeparator)) for _, s := range paths { if file, err := os.Stat(s + "/" + exec); err == nil && !file.IsDir() { exec = s + "/" + exec } } } _, _, err := syscall.StartProcess(exec, args, nil) if err != nil { fmt.Println("cannot daemonize handyhttpd", "err:", err) gLogger.Println("cannot daemonize handyhttpd", "err:", err) return } return } // there is no running handy, just return if *quit { gLogger.Println("gracefully exit with command line") return } // as this server is the only running server, nothing to list if *list { fmt.Println("No server is running") return } parseParams(root, pattern, *port, *remove) go func() { // handle other server's request http.HandleFunc("/list", func(w http.ResponseWriter, r *http.Request) { gLogger.Println("listing all ports per request") List(w) }) http.HandleFunc("/quit", func(w http.ResponseWriter, r *http.Request) { fmt.Fprintln(w, "Handy server is quiting now") // gracefully exit process, _ := os.FindProcess(os.Getpid()) process.Signal(syscall.SIGINT) }) http.HandleFunc("/", func(w http.ResponseWriter, r *http.Request) { gLogger.Println("handle a verb request. url:", r.URL) r.ParseForm() verb, verbOk := r.Form["verb"] alias, aliasOk := r.Form["alias"] dir, dirOk := r.Form["dir"] port, portOk := r.Form["port"] if !verbOk || !aliasOk || !dirOk || !portOk { gLogger.Println("missing required query string params") w.WriteHeader(http.StatusBadRequest) return } remove := false if verb[0] == "remove" { remove = true } portNumber, _ := strconv.Atoi(port[0]) if parseParams(dir[0], alias[0], portNumber, remove) { fmt.Fprintf(w, "%s dir %s as /%s on port %d\n", verb[0], dir[0], alias[0], LastPort()) } }) http.Serve(l, nil) }() defer Stop() sig := make(chan os.Signal, 1) signal.Notify(sig) for { s := <-sig if s == syscall.SIGKILL || s == syscall.SIGINT || s == syscall.SIGTERM { gLogger.Println("gracefully exit with signal", s) return } } }
func main() { var port = flag.Int("port", 11211, "TCP port number to listen on (default: 11211).") var daemon = flag.Bool("daemon", false, "Indicate it's daemon process.") var daemonized = flag.Bool("daemonized", false, "Indicate it's a daemonized process. Never use it in command line.") var logfile = flag.String("logfile", "", "Specify log file, defaults: stderr.") var maxconns = flag.Int("maxconns", 1024, "Max simultaneous connections (default: 1024).") flag.Parse() // Open log file. if len(*logfile) > 0 { file, err := os.OpenFile(*logfile, os.O_APPEND|os.O_CREATE|os.O_RDWR, 0666) if err != nil { return } logger = log.New(file, "", log.LstdFlags) } else { if *daemon { fmt.Println("Need to specify log file when runnning in background.") return } logger = log.New(os.Stderr, "", log.LstdFlags) } // Daemonize or not. if *daemon { if *daemonized { fd, err := syscall.Open("/dev/null", syscall.O_RDWR, 0) if err != nil { fmt.Println("cannot open /dev/null", "err:", err) panic(err) } syscall.Dup2(fd, syscall.Stdin) syscall.Dup2(fd, syscall.Stdout) syscall.Dup2(fd, syscall.Stderr) if fd > syscall.Stderr { syscall.Close(fd) } } else { // start a new process with "-daemonized" flag path, err := exec.LookPath(os.Args[0]) if err != nil { panic(err) } args := append([]string{path, "-daemonized"}, os.Args[1:]...) attr := syscall.ProcAttr{} logger.Println("Daemonizing...", args) _, _, err = syscall.StartProcess(path, args, &attr) if err != nil { panic(err) } return } } // Init semaphore sem = make(chan int, *maxconns) for i := 0; i < *maxconns; i++ { sem <- 1 } // Listing on specified port. ls, e := net.Listen("tcp", fmt.Sprintf(":%d", *port)) if e != nil { panic(e) } logger.Printf("Listening on port %d\n", *port) // Accepting connections from outside. for { c, e := ls.Accept() if e != nil { logger.Printf("Accept error: %v\n", e) continue } serve(c) } }