mirror of
https://github.com/wahyd4/forego.git
synced 2026-08-08 21:01:01 +10:00
go fmt
This commit is contained in:
+21
-21
@@ -1,44 +1,44 @@
|
||||
package main
|
||||
|
||||
import (
|
||||
"flag"
|
||||
"fmt"
|
||||
"strings"
|
||||
"flag"
|
||||
"fmt"
|
||||
"strings"
|
||||
)
|
||||
|
||||
var flagEnv string
|
||||
var flagProcfile string
|
||||
|
||||
type Command struct {
|
||||
// args does not include the command name
|
||||
Run func(cmd *Command, args []string)
|
||||
Flag flag.FlagSet
|
||||
// args does not include the command name
|
||||
Run func(cmd *Command, args []string)
|
||||
Flag flag.FlagSet
|
||||
|
||||
Usage string // first word is the command name
|
||||
Short string // `forego help` output
|
||||
Long string // `forego help cmd` output
|
||||
Usage string // first word is the command name
|
||||
Short string // `forego help` output
|
||||
Long string // `forego help cmd` output
|
||||
}
|
||||
|
||||
func (c *Command) printUsage() {
|
||||
if c.Runnable() {
|
||||
fmt.Printf("Usage: forego %s\n\n", c.Usage)
|
||||
}
|
||||
fmt.Println(strings.Trim(c.Long, "\n"))
|
||||
if c.Runnable() {
|
||||
fmt.Printf("Usage: forego %s\n\n", c.Usage)
|
||||
}
|
||||
fmt.Println(strings.Trim(c.Long, "\n"))
|
||||
}
|
||||
|
||||
func (c *Command) Name() string {
|
||||
name := c.Usage
|
||||
i := strings.Index(name, " ")
|
||||
if i >= 0 {
|
||||
name = name[:i]
|
||||
}
|
||||
return name
|
||||
name := c.Usage
|
||||
i := strings.Index(name, " ")
|
||||
if i >= 0 {
|
||||
name = name[:i]
|
||||
}
|
||||
return name
|
||||
}
|
||||
|
||||
func (c *Command) Runnable() bool {
|
||||
return c.Run != nil
|
||||
return c.Run != nil
|
||||
}
|
||||
|
||||
func (c *Command) List() bool {
|
||||
return c.Short != ""
|
||||
return c.Short != ""
|
||||
}
|
||||
|
||||
@@ -1,19 +1,19 @@
|
||||
package main
|
||||
|
||||
import (
|
||||
"bufio"
|
||||
"fmt"
|
||||
"github.com/kr/pretty"
|
||||
"io"
|
||||
"os"
|
||||
"regexp"
|
||||
"bufio"
|
||||
"fmt"
|
||||
"github.com/kr/pretty"
|
||||
"io"
|
||||
"os"
|
||||
"regexp"
|
||||
)
|
||||
|
||||
var envEntryRegexp = regexp.MustCompile("^([A-Za-z_0-9]+)=(.*)$")
|
||||
|
||||
type EnvEntry struct {
|
||||
name string
|
||||
command string
|
||||
name string
|
||||
command string
|
||||
}
|
||||
|
||||
type Env map[string]string
|
||||
@@ -21,26 +21,26 @@ type Env map[string]string
|
||||
var _ = pretty.Println // lol
|
||||
|
||||
func ReadEnv(filename string) (Env, error) {
|
||||
if _, err := os.Stat(filename); os.IsNotExist(err) {
|
||||
return make(Env), nil
|
||||
}
|
||||
fd, err := os.Open(filename)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
defer fd.Close()
|
||||
return parseEnv(fd)
|
||||
if _, err := os.Stat(filename); os.IsNotExist(err) {
|
||||
return make(Env), nil
|
||||
}
|
||||
fd, err := os.Open(filename)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
defer fd.Close()
|
||||
return parseEnv(fd)
|
||||
}
|
||||
|
||||
func parseEnv(r io.Reader) (Env, error) {
|
||||
env := make(Env)
|
||||
scanner := bufio.NewScanner(r)
|
||||
for scanner.Scan() {
|
||||
parts := envEntryRegexp.FindStringSubmatch(scanner.Text())
|
||||
env[parts[1]] = parts[2]
|
||||
}
|
||||
if err := scanner.Err(); err != nil {
|
||||
return nil, fmt.Errorf("Reading Env: %s", err)
|
||||
}
|
||||
return env, nil
|
||||
env := make(Env)
|
||||
scanner := bufio.NewScanner(r)
|
||||
for scanner.Scan() {
|
||||
parts := envEntryRegexp.FindStringSubmatch(scanner.Text())
|
||||
env[parts[1]] = parts[2]
|
||||
}
|
||||
if err := scanner.Err(); err != nil {
|
||||
return nil, fmt.Errorf("Reading Env: %s", err)
|
||||
}
|
||||
return env, nil
|
||||
}
|
||||
|
||||
@@ -1,13 +1,13 @@
|
||||
package main
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"os"
|
||||
"fmt"
|
||||
"os"
|
||||
)
|
||||
|
||||
func handleError(err error) {
|
||||
if err != nil {
|
||||
fmt.Println("ERROR:", err)
|
||||
os.Exit(1)
|
||||
}
|
||||
if err != nil {
|
||||
fmt.Println("ERROR:", err)
|
||||
os.Exit(1)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,40 +1,40 @@
|
||||
package main
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"log"
|
||||
"os"
|
||||
"text/template"
|
||||
"fmt"
|
||||
"log"
|
||||
"os"
|
||||
"text/template"
|
||||
)
|
||||
|
||||
var cmdHelp = &Command{
|
||||
Usage: "help [topic]",
|
||||
Short: "Show this help",
|
||||
Long: `Help shows usage for a command.`,
|
||||
Usage: "help [topic]",
|
||||
Short: "Show this help",
|
||||
Long: `Help shows usage for a command.`,
|
||||
}
|
||||
|
||||
func init() {
|
||||
cmdHelp.Run = runHelp // break init loop
|
||||
cmdHelp.Run = runHelp // break init loop
|
||||
}
|
||||
|
||||
func runHelp(cmd *Command, args []string) {
|
||||
if len(args) == 0 {
|
||||
printUsage()
|
||||
return
|
||||
}
|
||||
if len(args) != 1 {
|
||||
log.Fatal("too many arguments")
|
||||
}
|
||||
if len(args) == 0 {
|
||||
printUsage()
|
||||
return
|
||||
}
|
||||
if len(args) != 1 {
|
||||
log.Fatal("too many arguments")
|
||||
}
|
||||
|
||||
for _, cmd := range commands {
|
||||
if cmd.Name() == args[0] {
|
||||
cmd.printUsage()
|
||||
return
|
||||
}
|
||||
}
|
||||
for _, cmd := range commands {
|
||||
if cmd.Name() == args[0] {
|
||||
cmd.printUsage()
|
||||
return
|
||||
}
|
||||
}
|
||||
|
||||
fmt.Fprintf(os.Stderr, "Unknown help topic: %q. Run 'forego help'.\n", args[0])
|
||||
os.Exit(2)
|
||||
fmt.Fprintf(os.Stderr, "Unknown help topic: %q. Run 'forego help'.\n", args[0])
|
||||
os.Exit(2)
|
||||
}
|
||||
|
||||
var usageTemplate = template.Must(template.New("usage").Parse(`
|
||||
@@ -47,14 +47,14 @@ Run 'forego help [command]' for details.
|
||||
`[1:]))
|
||||
|
||||
func printUsage() {
|
||||
usageTemplate.Execute(os.Stdout, struct {
|
||||
Commands []*Command
|
||||
}{
|
||||
commands,
|
||||
})
|
||||
usageTemplate.Execute(os.Stdout, struct {
|
||||
Commands []*Command
|
||||
}{
|
||||
commands,
|
||||
})
|
||||
}
|
||||
|
||||
func usage() {
|
||||
printUsage()
|
||||
os.Exit(2)
|
||||
printUsage()
|
||||
os.Exit(2)
|
||||
}
|
||||
|
||||
@@ -1,35 +1,35 @@
|
||||
package main
|
||||
|
||||
import (
|
||||
"github.com/kr/pretty"
|
||||
"os"
|
||||
"github.com/kr/pretty"
|
||||
"os"
|
||||
)
|
||||
|
||||
var _ = pretty.Println // lol
|
||||
|
||||
var commands = []*Command{
|
||||
cmdStart,
|
||||
cmdRun,
|
||||
cmdHelp,
|
||||
cmdStart,
|
||||
cmdRun,
|
||||
cmdHelp,
|
||||
}
|
||||
|
||||
func main() {
|
||||
args := os.Args[1:]
|
||||
if len(args) < 1 {
|
||||
usage()
|
||||
}
|
||||
args := os.Args[1:]
|
||||
if len(args) < 1 {
|
||||
usage()
|
||||
}
|
||||
|
||||
for _, cmd := range commands {
|
||||
if cmd.Name() == args[0] && cmd.Run != nil {
|
||||
cmd.Flag.Usage = func() {
|
||||
cmd.printUsage()
|
||||
}
|
||||
if err := cmd.Flag.Parse(args[1:]); err != nil {
|
||||
os.Exit(2)
|
||||
}
|
||||
cmd.Run(cmd, cmd.Flag.Args())
|
||||
return
|
||||
}
|
||||
}
|
||||
usage()
|
||||
for _, cmd := range commands {
|
||||
if cmd.Name() == args[0] && cmd.Run != nil {
|
||||
cmd.Flag.Usage = func() {
|
||||
cmd.printUsage()
|
||||
}
|
||||
if err := cmd.Flag.Parse(args[1:]); err != nil {
|
||||
os.Exit(2)
|
||||
}
|
||||
cmd.Run(cmd, cmd.Flag.Args())
|
||||
return
|
||||
}
|
||||
}
|
||||
usage()
|
||||
}
|
||||
|
||||
@@ -1,20 +1,20 @@
|
||||
package main
|
||||
|
||||
import (
|
||||
"bufio"
|
||||
"bytes"
|
||||
"fmt"
|
||||
"github.com/daviddengcn/go-colortext"
|
||||
"github.com/kr/pretty"
|
||||
"io"
|
||||
"os"
|
||||
"sync"
|
||||
"bufio"
|
||||
"bytes"
|
||||
"fmt"
|
||||
"github.com/daviddengcn/go-colortext"
|
||||
"github.com/kr/pretty"
|
||||
"io"
|
||||
"os"
|
||||
"sync"
|
||||
)
|
||||
|
||||
type Outlet struct {
|
||||
Name string
|
||||
Color ct.Color
|
||||
IsError bool
|
||||
Name string
|
||||
Color ct.Color
|
||||
IsError bool
|
||||
}
|
||||
|
||||
var _ = pretty.Println // lol
|
||||
@@ -25,59 +25,59 @@ var longest int
|
||||
var mutex = new(sync.Mutex)
|
||||
|
||||
var colors = []ct.Color{
|
||||
ct.Cyan,
|
||||
ct.Yellow,
|
||||
ct.Green,
|
||||
ct.Magenta,
|
||||
ct.Red,
|
||||
ct.Blue,
|
||||
ct.Cyan,
|
||||
ct.Yellow,
|
||||
ct.Green,
|
||||
ct.Magenta,
|
||||
ct.Red,
|
||||
ct.Blue,
|
||||
}
|
||||
|
||||
func (o *Outlet) Write(b []byte) (num int, err error) {
|
||||
mutex.Lock()
|
||||
defer mutex.Unlock()
|
||||
scanner := bufio.NewScanner(bytes.NewReader(b))
|
||||
for scanner.Scan() {
|
||||
formatter := fmt.Sprintf("%%-%ds | ", longest)
|
||||
ct.ChangeColor(o.Color, true, ct.None, false)
|
||||
fmt.Printf(formatter, o.Name)
|
||||
if (o.IsError) {
|
||||
ct.ChangeColor(ct.Red, true, ct.None, true)
|
||||
} else {
|
||||
ct.ResetColor()
|
||||
}
|
||||
fmt.Println(scanner.Text())
|
||||
ct.ResetColor()
|
||||
}
|
||||
num = len(b)
|
||||
return
|
||||
mutex.Lock()
|
||||
defer mutex.Unlock()
|
||||
scanner := bufio.NewScanner(bytes.NewReader(b))
|
||||
for scanner.Scan() {
|
||||
formatter := fmt.Sprintf("%%-%ds | ", longest)
|
||||
ct.ChangeColor(o.Color, true, ct.None, false)
|
||||
fmt.Printf(formatter, o.Name)
|
||||
if o.IsError {
|
||||
ct.ChangeColor(ct.Red, true, ct.None, true)
|
||||
} else {
|
||||
ct.ResetColor()
|
||||
}
|
||||
fmt.Println(scanner.Text())
|
||||
ct.ResetColor()
|
||||
}
|
||||
num = len(b)
|
||||
return
|
||||
}
|
||||
|
||||
func ProcessOutput(w io.Writer, str string) {
|
||||
w.Write([]byte(str))
|
||||
w.Write([]byte(str))
|
||||
}
|
||||
|
||||
var outlets = map[string]*Outlet{}
|
||||
|
||||
func createOutlet(name string, index int, isError bool) *Outlet {
|
||||
outlets[name] = &Outlet{name, colors[index%len(colors)], isError}
|
||||
return outlets[name]
|
||||
outlets[name] = &Outlet{name, colors[index%len(colors)], isError}
|
||||
return outlets[name]
|
||||
}
|
||||
|
||||
func SetLongestOutletName(l int) {
|
||||
longest = l
|
||||
longest = l
|
||||
}
|
||||
|
||||
func SystemOutput(str string) {
|
||||
ct.ChangeColor(ct.White, true, ct.None, false)
|
||||
formatter := fmt.Sprintf("%%-%ds | ", longest)
|
||||
fmt.Printf(formatter, "forego")
|
||||
ct.ResetColor()
|
||||
fmt.Println(str)
|
||||
ct.ResetColor()
|
||||
ct.ChangeColor(ct.White, true, ct.None, false)
|
||||
formatter := fmt.Sprintf("%%-%ds | ", longest)
|
||||
fmt.Printf(formatter, "forego")
|
||||
ct.ResetColor()
|
||||
fmt.Println(str)
|
||||
ct.ResetColor()
|
||||
}
|
||||
|
||||
func ErrorOutput(str string) {
|
||||
fmt.Printf("ERROR: %s\n", str)
|
||||
os.Exit(1)
|
||||
fmt.Printf("ERROR: %s\n", str)
|
||||
os.Exit(1)
|
||||
}
|
||||
|
||||
+40
-40
@@ -1,66 +1,66 @@
|
||||
package main
|
||||
|
||||
import (
|
||||
"bufio"
|
||||
"fmt"
|
||||
"github.com/kr/pretty"
|
||||
"io"
|
||||
"os"
|
||||
"regexp"
|
||||
"bufio"
|
||||
"fmt"
|
||||
"github.com/kr/pretty"
|
||||
"io"
|
||||
"os"
|
||||
"regexp"
|
||||
)
|
||||
|
||||
var procfileEntryRegexp = regexp.MustCompile("^([A-Za-z0-9_]+):\\s*(.+)$")
|
||||
|
||||
type ProcfileEntry struct {
|
||||
Name string
|
||||
Command string
|
||||
Name string
|
||||
Command string
|
||||
}
|
||||
|
||||
type Procfile struct {
|
||||
Entries []ProcfileEntry
|
||||
Entries []ProcfileEntry
|
||||
}
|
||||
|
||||
var _ = pretty.Println // lol
|
||||
|
||||
func ReadProcfile(filename string) (*Procfile, error) {
|
||||
fd, err := os.Open(filename)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
defer fd.Close()
|
||||
return parseProcfile(fd)
|
||||
fd, err := os.Open(filename)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
defer fd.Close()
|
||||
return parseProcfile(fd)
|
||||
}
|
||||
|
||||
func (pf *Procfile) HasProcess(name string) (exists bool) {
|
||||
exists = false
|
||||
for _, entry := range pf.Entries {
|
||||
if name == entry.Name {
|
||||
exists = true
|
||||
break
|
||||
}
|
||||
}
|
||||
return
|
||||
exists = false
|
||||
for _, entry := range pf.Entries {
|
||||
if name == entry.Name {
|
||||
exists = true
|
||||
break
|
||||
}
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
func (pf *Procfile) LongestProcessName() (longest int) {
|
||||
longest = 6 // length of forego
|
||||
for _, entry := range pf.Entries {
|
||||
if len(entry.Name) > longest {
|
||||
longest = len(entry.Name)
|
||||
}
|
||||
}
|
||||
return
|
||||
longest = 6 // length of forego
|
||||
for _, entry := range pf.Entries {
|
||||
if len(entry.Name) > longest {
|
||||
longest = len(entry.Name)
|
||||
}
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
func parseProcfile(r io.Reader) (*Procfile, error) {
|
||||
pf := new(Procfile)
|
||||
scanner := bufio.NewScanner(r)
|
||||
for scanner.Scan() {
|
||||
parts := procfileEntryRegexp.FindStringSubmatch(scanner.Text())
|
||||
pf.Entries = append(pf.Entries, ProcfileEntry{parts[1], parts[2]})
|
||||
}
|
||||
if err := scanner.Err(); err != nil {
|
||||
return nil, fmt.Errorf("Reading Procfile: %s", err)
|
||||
}
|
||||
return pf, nil
|
||||
pf := new(Procfile)
|
||||
scanner := bufio.NewScanner(r)
|
||||
for scanner.Scan() {
|
||||
parts := procfileEntryRegexp.FindStringSubmatch(scanner.Text())
|
||||
pf.Entries = append(pf.Entries, ProcfileEntry{parts[1], parts[2]})
|
||||
}
|
||||
if err := scanner.Err(); err != nil {
|
||||
return nil, fmt.Errorf("Reading Procfile: %s", err)
|
||||
}
|
||||
return pf, nil
|
||||
}
|
||||
|
||||
@@ -1,22 +1,22 @@
|
||||
package main
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"github.com/kr/pretty"
|
||||
"os"
|
||||
"os/exec"
|
||||
"strings"
|
||||
"syscall"
|
||||
"fmt"
|
||||
"github.com/kr/pretty"
|
||||
"os"
|
||||
"os/exec"
|
||||
"strings"
|
||||
"syscall"
|
||||
)
|
||||
|
||||
var _ = pretty.Println // lol
|
||||
var _ = os.Stdout
|
||||
|
||||
var cmdRun = &Command{
|
||||
Run: runRun,
|
||||
Usage: "run [-e env] [-c concurrency] [-p port]",
|
||||
Short: "Run a one-off command",
|
||||
Long: `
|
||||
Run: runRun,
|
||||
Usage: "run [-e env] [-c concurrency] [-p port]",
|
||||
Short: "Run a one-off command",
|
||||
Long: `
|
||||
Run a one-off command
|
||||
|
||||
Examples:
|
||||
@@ -26,29 +26,29 @@ Examples:
|
||||
}
|
||||
|
||||
func init() {
|
||||
cmdRun.Flag.StringVar(&flagEnv, "e", ".env", "env")
|
||||
cmdRun.Flag.StringVar(&flagEnv, "e", ".env", "env")
|
||||
}
|
||||
|
||||
func runRun(cmd *Command, args []string) {
|
||||
command := []string{"/bin/bash", "-c"}
|
||||
command = append(command, fmt.Sprintf("source .profile 2>/dev/null; %s", strings.Join(args, " ")))
|
||||
command := []string{"/bin/bash", "-c"}
|
||||
command = append(command, fmt.Sprintf("source .profile 2>/dev/null; %s", strings.Join(args, " ")))
|
||||
|
||||
env, err := ReadEnv(flagEnv)
|
||||
handleError(err)
|
||||
env, err := ReadEnv(flagEnv)
|
||||
handleError(err)
|
||||
|
||||
ps_env := os.Environ()
|
||||
for name, val := range env {
|
||||
ps_env = append(ps_env, fmt.Sprintf("%s=%s", name, val))
|
||||
}
|
||||
ps_env := os.Environ()
|
||||
for name, val := range env {
|
||||
ps_env = append(ps_env, fmt.Sprintf("%s=%s", name, val))
|
||||
}
|
||||
|
||||
ps := exec.Command(command[0], command[1:]...)
|
||||
ps.Dir, _ = os.Getwd()
|
||||
ps.Env = ps_env
|
||||
ps.Stdin = nil
|
||||
ps.Stdout = os.Stdout
|
||||
ps.Stderr = os.Stderr
|
||||
ps.SysProcAttr = &syscall.SysProcAttr{}
|
||||
ps.SysProcAttr.Setsid = true
|
||||
ps.Start()
|
||||
ps.Wait()
|
||||
ps := exec.Command(command[0], command[1:]...)
|
||||
ps.Dir, _ = os.Getwd()
|
||||
ps.Env = ps_env
|
||||
ps.Stdin = nil
|
||||
ps.Stdout = os.Stdout
|
||||
ps.Stderr = os.Stderr
|
||||
ps.SysProcAttr = &syscall.SysProcAttr{}
|
||||
ps.SysProcAttr.Setsid = true
|
||||
ps.Start()
|
||||
ps.Wait()
|
||||
}
|
||||
|
||||
@@ -1,15 +1,15 @@
|
||||
package main
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"github.com/kr/pretty"
|
||||
"os"
|
||||
"os/exec"
|
||||
"os/signal"
|
||||
"path/filepath"
|
||||
"sync"
|
||||
"syscall"
|
||||
"time"
|
||||
"fmt"
|
||||
"github.com/kr/pretty"
|
||||
"os"
|
||||
"os/exec"
|
||||
"os/signal"
|
||||
"path/filepath"
|
||||
"sync"
|
||||
"syscall"
|
||||
"time"
|
||||
)
|
||||
|
||||
const shutdownGraceTime = 3 * time.Second
|
||||
@@ -24,10 +24,10 @@ var shutdown_mutex = new(sync.Mutex)
|
||||
var wg sync.WaitGroup
|
||||
|
||||
var cmdStart = &Command{
|
||||
Run: runStart,
|
||||
Usage: "start [process name] [-f procfile] [-e env] [-c concurrency] [-p port]",
|
||||
Short: "Start the application",
|
||||
Long: `
|
||||
Run: runStart,
|
||||
Usage: "start [process name] [-f procfile] [-e env] [-c concurrency] [-p port]",
|
||||
Short: "Start the application",
|
||||
Long: `
|
||||
Start the application specified by a Procfile (defaults to ./Procfile)
|
||||
|
||||
Examples:
|
||||
@@ -39,96 +39,96 @@ Examples:
|
||||
}
|
||||
|
||||
func init() {
|
||||
cmdStart.Flag.StringVar(&flagProcfile, "f", "Procfile", "procfile")
|
||||
cmdStart.Flag.StringVar(&flagEnv, "e", "", "env")
|
||||
cmdStart.Flag.IntVar(&flagPort, "p", 5000, "port")
|
||||
cmdStart.Flag.StringVar(&flagProcfile, "f", "Procfile", "procfile")
|
||||
cmdStart.Flag.StringVar(&flagEnv, "e", "", "env")
|
||||
cmdStart.Flag.IntVar(&flagPort, "p", 5000, "port")
|
||||
}
|
||||
|
||||
func runStart(cmd *Command, args []string) {
|
||||
handler := make(chan os.Signal, 1)
|
||||
signal.Notify(handler, os.Interrupt)
|
||||
handler := make(chan os.Signal, 1)
|
||||
signal.Notify(handler, os.Interrupt)
|
||||
|
||||
go func() {
|
||||
for sig := range handler {
|
||||
switch (sig) {
|
||||
case os.Interrupt:
|
||||
fmt.Println(" | ctrl-c detected")
|
||||
go func() { ShutdownProcesses() }()
|
||||
}
|
||||
}
|
||||
}()
|
||||
go func() {
|
||||
for sig := range handler {
|
||||
switch sig {
|
||||
case os.Interrupt:
|
||||
fmt.Println(" | ctrl-c detected")
|
||||
go func() { ShutdownProcesses() }()
|
||||
}
|
||||
}
|
||||
}()
|
||||
|
||||
root := filepath.Dir(flagProcfile)
|
||||
root := filepath.Dir(flagProcfile)
|
||||
|
||||
if (flagEnv == "") {
|
||||
flagEnv = filepath.Join(root, ".env")
|
||||
}
|
||||
if flagEnv == "" {
|
||||
flagEnv = filepath.Join(root, ".env")
|
||||
}
|
||||
|
||||
var singleton string = ""
|
||||
if (len(args) > 0) {
|
||||
singleton = args[0]
|
||||
}
|
||||
var singleton string = ""
|
||||
if len(args) > 0 {
|
||||
singleton = args[0]
|
||||
}
|
||||
|
||||
pf, err := ReadProcfile(flagProcfile)
|
||||
handleError(err)
|
||||
env, err := ReadEnv(flagEnv)
|
||||
handleError(err)
|
||||
pf, err := ReadProcfile(flagProcfile)
|
||||
handleError(err)
|
||||
env, err := ReadEnv(flagEnv)
|
||||
handleError(err)
|
||||
|
||||
SetLongestOutletName(pf.LongestProcessName())
|
||||
SetLongestOutletName(pf.LongestProcessName())
|
||||
|
||||
ps_env := os.Environ()
|
||||
for name, val := range env {
|
||||
ps_env = append(ps_env, fmt.Sprintf("%s=%s", name, val))
|
||||
}
|
||||
ps_env := os.Environ()
|
||||
for name, val := range env {
|
||||
ps_env = append(ps_env, fmt.Sprintf("%s=%s", name, val))
|
||||
}
|
||||
|
||||
if singleton != "" {
|
||||
if !pf.HasProcess(singleton) {
|
||||
ErrorOutput(fmt.Sprintf("no such process: %s", singleton))
|
||||
}
|
||||
}
|
||||
if singleton != "" {
|
||||
if !pf.HasProcess(singleton) {
|
||||
ErrorOutput(fmt.Sprintf("no such process: %s", singleton))
|
||||
}
|
||||
}
|
||||
|
||||
for idx, proc := range pf.Entries {
|
||||
if (singleton == "") || (singleton == proc.Name) {
|
||||
wg.Add(1)
|
||||
command := []string{"/bin/bash", "-c", fmt.Sprintf("source \"%s\" 2>/dev/null; %s", filepath.Join(root, ".profile"), proc.Command)}
|
||||
ps := exec.Command(command[0], command[1:]...)
|
||||
port := flagPort + (idx * 100)
|
||||
processes[proc.Name] = ps
|
||||
ps.Dir = root
|
||||
ps.Env = append(ps_env, fmt.Sprintf("PORT=%d", port))
|
||||
ps.Stdin = nil
|
||||
ps.Stdout = createOutlet(proc.Name, idx, false)
|
||||
ps.Stderr = createOutlet(proc.Name, idx, true)
|
||||
ps.SysProcAttr = &syscall.SysProcAttr{}
|
||||
ps.SysProcAttr.Setsid = true
|
||||
ps.Start()
|
||||
SystemOutput(fmt.Sprintf("starting %s on port %d", proc.Name, port))
|
||||
go func(proc ProcfileEntry, ps *exec.Cmd) {
|
||||
ps.Wait()
|
||||
wg.Done()
|
||||
delete(processes, proc.Name)
|
||||
}(proc, ps)
|
||||
}
|
||||
}
|
||||
for idx, proc := range pf.Entries {
|
||||
if (singleton == "") || (singleton == proc.Name) {
|
||||
wg.Add(1)
|
||||
command := []string{"/bin/bash", "-c", fmt.Sprintf("source \"%s\" 2>/dev/null; %s", filepath.Join(root, ".profile"), proc.Command)}
|
||||
ps := exec.Command(command[0], command[1:]...)
|
||||
port := flagPort + (idx * 100)
|
||||
processes[proc.Name] = ps
|
||||
ps.Dir = root
|
||||
ps.Env = append(ps_env, fmt.Sprintf("PORT=%d", port))
|
||||
ps.Stdin = nil
|
||||
ps.Stdout = createOutlet(proc.Name, idx, false)
|
||||
ps.Stderr = createOutlet(proc.Name, idx, true)
|
||||
ps.SysProcAttr = &syscall.SysProcAttr{}
|
||||
ps.SysProcAttr.Setsid = true
|
||||
ps.Start()
|
||||
SystemOutput(fmt.Sprintf("starting %s on port %d", proc.Name, port))
|
||||
go func(proc ProcfileEntry, ps *exec.Cmd) {
|
||||
ps.Wait()
|
||||
wg.Done()
|
||||
delete(processes, proc.Name)
|
||||
}(proc, ps)
|
||||
}
|
||||
}
|
||||
|
||||
wg.Wait()
|
||||
shutdown_mutex.Unlock()
|
||||
wg.Wait()
|
||||
shutdown_mutex.Unlock()
|
||||
}
|
||||
|
||||
func ShutdownProcesses() {
|
||||
shutdown_mutex.Lock()
|
||||
SystemOutput("shutting down")
|
||||
for name, ps := range processes {
|
||||
SystemOutput(fmt.Sprintf("sending SIGTERM to %s", name))
|
||||
group, _ := os.FindProcess(-1 * ps.Process.Pid)
|
||||
group.Signal(syscall.SIGTERM)
|
||||
}
|
||||
go func() {
|
||||
time.Sleep(shutdownGraceTime)
|
||||
for name, ps := range processes {
|
||||
SystemOutput(fmt.Sprintf("sending SIGKILL to %s", name))
|
||||
group, _ := os.FindProcess(-1 * ps.Process.Pid)
|
||||
group.Signal(syscall.SIGKILL)
|
||||
}
|
||||
}()
|
||||
shutdown_mutex.Lock()
|
||||
SystemOutput("shutting down")
|
||||
for name, ps := range processes {
|
||||
SystemOutput(fmt.Sprintf("sending SIGTERM to %s", name))
|
||||
group, _ := os.FindProcess(-1 * ps.Process.Pid)
|
||||
group.Signal(syscall.SIGTERM)
|
||||
}
|
||||
go func() {
|
||||
time.Sleep(shutdownGraceTime)
|
||||
for name, ps := range processes {
|
||||
SystemOutput(fmt.Sprintf("sending SIGKILL to %s", name))
|
||||
group, _ := os.FindProcess(-1 * ps.Process.Pid)
|
||||
group.Signal(syscall.SIGKILL)
|
||||
}
|
||||
}()
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user