func main() { for Args = os.Args[1:]; Args != nil && len(Args) > 0 && Args[0][0] == '-'; Args = Args[1:] { switch Args[0] { case "--no-color": color = false slog.DisableColor() case "--log": tracefile, err := os.OpenFile(Args[1], os.O_WRONLY|os.O_APPEND|os.O_CREATE, 0666) if err == nil { slog.TraceLogger = slog.NewTraceLogger(tracefile) Args = Args[1:] } else { fmt.Printf("Could not open trace file %s", Args[1]) return } case "--file-change-delay": if len(Args) > 1 { delay, err := time.ParseDuration(Args[1]) if err != nil { execManPage("zeus") } Args = Args[1:] restarter.FileChangeWindow = delay } else { execManPage("zeus") } case "--version": printVersion() return } } if len(Args) == 0 { execManPage("zeus") } if generalHelpRequested(Args) { execManPage("zeus") } else if Args[0] == "help" { commandSpecificHelp(Args) } else if Args[0] == "version" { printVersion() } else if Args[0] == "start" { zeusmaster.Run() } else if Args[0] == "init" { zeusInit() } else if Args[0] == "commands" { zeusCommands() } else { tree := config.BuildProcessTree() for _, name := range tree.AllCommandsAndAliases() { if Args[0] == name { zeusclient.Run() return } } commandNotFound(Args[0]) } }
func Run(color bool) { if !color { slog.DisableColor() DisableErrorColor() } slog.StartingZeus() var tree *ProcessTree = BuildProcessTree() exitNow = make(chan int) localMasterFile, remoteMasterFile, err := unixsocket.Socketpair(syscall.SOCK_DGRAM) if err != nil { panic(err) } localMasterSocket, err := unixsocket.NewUsockFromFile(localMasterFile) if err != nil { panic(err) } quit1 := make(chan bool) quit2 := make(chan bool) quit3 := make(chan bool) go StartSlaveMonitor(tree, localMasterSocket, remoteMasterFile, quit1) go StartClientHandler(tree, quit2) go StartFileMonitor(tree, quit3) quit := make(chan bool, 1) c := make(chan os.Signal, 1) signal.Notify(c, os.Interrupt) go func() { <-c // FIXME: Unprecedented levels of jank, right here. terminateComponents(quit1, quit2, quit3, quit) }() go func() { exitStatus = <-exitNow terminateComponents(quit1, quit2, quit3, quit) }() <-quit <-quit <-quit os.Exit(exitStatus) }
func Run(color bool) { exitNow = make(chan int) if !color { slog.DisableColor() } startingZeus() var tree *ProcessTree = BuildProcessTree() quit1 := make(chan bool) quit2 := make(chan bool) quit3 := make(chan bool) quit4 := make(chan bool) go StartSlaveMonitor(tree, quit1) go StartClientHandler(tree, quit2) go StartFileMonitor(tree, quit3) go StartStatusChart(tree, quit4) quit := make(chan bool) c := make(chan os.Signal, 1) signal.Notify(c, os.Interrupt) go func() { <-c terminateComponents(quit1, quit2, quit3, quit4, quit) }() go func() { exitStatus = <-exitNow terminateComponents(quit1, quit2, quit3, quit4, quit) }() <-quit <-quit <-quit <-quit os.Exit(exitStatus) }
func main() { if len(os.Args) == 1 { execManPage("zeus") } var args []string if os.Args[1] == "--no-color" { color = false slog.DisableColor() args = os.Args[2:] } else { args = os.Args[1:] } if generalHelpRequested(args) { execManPage("zeus") } else if args[0] == "help" { commandSpecificHelp(args) } else if args[0] == "version" || args[0] == "--version" { println("Zeus version " + zeusversion.VERSION) } else if args[0] == "start" { zeusmaster.Run() } else if args[0] == "init" { zeusInit() } else if args[0] == "commands" { zeusCommands() } else { tree := zeusmaster.BuildProcessTree() for _, name := range tree.AllCommandsAndAliases() { if args[0] == name { zeusclient.Run() return } } commandNotFound(args[0]) } }
func main() { args := os.Args[1:] configFile := "zeus.json" fileChangeDelay := filemonitor.DefaultFileChangeDelay for ; args != nil && len(args) > 0 && args[0][0] == '-'; args = args[1:] { switch args[0] { case "--no-color": color = false slog.DisableColor() case "--log": tracefile, err := os.OpenFile(args[1], os.O_WRONLY|os.O_APPEND|os.O_CREATE, 0666) if err == nil { slog.SetTraceLogger(slog.NewTraceLogger(tracefile)) args = args[1:] } else { fmt.Printf("Could not open trace file %s\n", args[1]) return } case "--file-change-delay": if len(args) > 1 { delay, err := time.ParseDuration(args[1]) if err != nil { execManPage("zeus") } args = args[1:] fileChangeDelay = delay } else { execManPage("zeus") } case "--config": _, err := os.Stat(args[1]) if err != nil { fmt.Printf("Config file doesn't exist: %s (%e)\n", args[1], err) return } configFile = args[1] args = args[1:] case "--version": printVersion() return } } if len(args) == 0 { execManPage("zeus") return } if generalHelpRequested(args) { execManPage("zeus") } else if args[0] == "help" { commandSpecificHelp(args) } else if args[0] == "version" { printVersion() } else if args[0] == "start" { os.Exit(zeusmaster.Run(configFile, fileChangeDelay)) } else if args[0] == "init" { zeusInit() } else if args[0] == "commands" { zeusCommands(configFile) } else { tree := config.BuildProcessTree(configFile, nil) for _, name := range tree.AllCommandsAndAliases() { if args[0] == name { // Don't confuse the master by sending *full* args to // it; just those that are not zeus-specific. os.Exit(zeusclient.Run(args, os.Stdin, os.Stdout)) } } commandNotFound(args[0]) } }
func doRun(color bool) int { if !color { slog.DisableColor() DisableErrorColor() } if os.Getenv("RAILS_ENV") != "" { println("Warning: Specifying a Rails environment via RAILS_ENV has no effect for commands run with zeus.") } master, slave, err := pty.Open() if err != nil { panic(err) } defer master.Close() if ttyutils.IsTerminal(os.Stdout.Fd()) { oldState, err := ttyutils.MakeTerminalRaw(os.Stdout.Fd()) if err != nil { panic(err) } defer ttyutils.RestoreTerminalState(os.Stdout.Fd(), oldState) } ttyutils.MirrorWinsize(os.Stdout, master) addr, err := net.ResolveUnixAddr("unixgram", zeusSockName) if err != nil { panic("Can't resolve server address") } conn, err := net.DialUnix("unix", nil, addr) if err != nil { ErrorCantConnectToMaster() } usock := unixsocket.NewUsock(conn) msg := CreateCommandAndArgumentsMessage(os.Args[1], os.Args[2:]) usock.WriteMessage(msg) usock.WriteFD(int(slave.Fd())) slave.Close() msg, err = usock.ReadMessage() if err != nil { panic(err) } parts := strings.Split(msg, "\000") commandPid, err := strconv.Atoi(parts[0]) defer func() { if commandPid > 0 { // Just in case. syscall.Kill(commandPid, 9) } }() if err != nil { panic(err) } c := make(chan os.Signal, 1) signal.Notify(c, syscall.SIGWINCH, syscall.SIGCONT) go func() { for sig := range c { if sig == syscall.SIGCONT { syscall.Kill(commandPid, syscall.SIGCONT) } else if sig == syscall.SIGWINCH { ttyutils.MirrorWinsize(os.Stdout, master) syscall.Kill(commandPid, syscall.SIGWINCH) } } }() var exitStatus int = -1 if len(parts) > 2 { exitStatus, err = strconv.Atoi(parts[0]) if err != nil { panic(err) } } eof := make(chan bool) go func() { for { buf := make([]byte, 1024) n, err := master.Read(buf) if err != nil { eof <- true break } os.Stdout.Write(buf[:n]) } }() go func() { buf := make([]byte, 8192) for { n, err := os.Stdin.Read(buf) if err != nil { eof <- true break } for i := 0; i < n; i++ { switch buf[i] { case sigInt: syscall.Kill(commandPid, syscall.SIGINT) case sigQuit: syscall.Kill(commandPid, syscall.SIGQUIT) case sigTstp: syscall.Kill(commandPid, syscall.SIGTSTP) syscall.Kill(os.Getpid(), syscall.SIGTSTP) } } master.Write(buf[:n]) } }() <-eof if exitStatus == -1 { msg, err = usock.ReadMessage() if err != nil { panic(err) } parts := strings.Split(msg, "\000") exitStatus, err = strconv.Atoi(parts[0]) if err != nil { panic(err) } } return exitStatus }
func main() { for Args = os.Args[1:]; Args != nil && len(Args) > 0 && Args[0][0] == '-'; Args = Args[1:] { switch Args[0] { case "--no-color": color = false slog.DisableColor() case "--log": tracefile, err := os.OpenFile(Args[1], os.O_WRONLY|os.O_APPEND|os.O_CREATE, 0666) if err == nil { slog.SetTraceLogger(slog.NewTraceLogger(tracefile)) Args = Args[1:] } else { fmt.Printf("Could not open trace file %s\n", Args[1]) return } case "--file-change-delay": if len(Args) > 1 { delay, err := time.ParseDuration(Args[1]) if err != nil { execManPage("zeus") } Args = Args[1:] restarter.FileChangeWindow = delay } else { execManPage("zeus") } case "--config": _, err := os.Stat(Args[1]) if err != nil { fmt.Printf("Config file doesn't exist: %s (%e)\n", Args[1], err) return } config.ConfigFile = Args[1] Args = Args[1:] case "--version": printVersion() return } } if len(Args) == 0 { execManPage("zeus") } // Don't confuse the master by sending *full* args to it; just those that are // not zeus-specific. config.Args = Args if generalHelpRequested(Args) { execManPage("zeus") } else if Args[0] == "help" { commandSpecificHelp(Args) } else if Args[0] == "version" { printVersion() } else if Args[0] == "start" { zeusmaster.Run() } else if Args[0] == "init" { zeusInit() } else if Args[0] == "commands" { zeusCommands() } else { tree := config.BuildProcessTree() for _, name := range tree.AllCommandsAndAliases() { if Args[0] == name { zeusclient.Run() return } } commandNotFound(Args[0]) } }