You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

178 lines
3.5 KiB

6 years ago
6 years ago
6 years ago
4 years ago
6 years ago
6 years ago
6 years ago
6 years ago
6 years ago
  1. package shell
  2. import (
  3. "context"
  4. "fmt"
  5. "github.com/chrislusf/seaweedfs/weed/pb/filer_pb"
  6. "github.com/chrislusf/seaweedfs/weed/util/grace"
  7. "io"
  8. "os"
  9. "path"
  10. "regexp"
  11. "sort"
  12. "strings"
  13. "github.com/peterh/liner"
  14. )
  15. var (
  16. line *liner.State
  17. historyPath = path.Join(os.TempDir(), "weed-shell")
  18. )
  19. func RunShell(options ShellOptions) {
  20. sort.Slice(Commands, func(i, j int) bool {
  21. return strings.Compare(Commands[i].Name(), Commands[j].Name()) < 0
  22. })
  23. line = liner.NewLiner()
  24. defer line.Close()
  25. grace.OnInterrupt(func() {
  26. line.Close()
  27. })
  28. line.SetCtrlCAborts(true)
  29. line.SetTabCompletionStyle(liner.TabPrints)
  30. setCompletionHandler()
  31. loadHistory()
  32. defer saveHistory()
  33. reg, _ := regexp.Compile(`'.*?'|".*?"|\S+`)
  34. commandEnv := NewCommandEnv(options)
  35. go commandEnv.MasterClient.KeepConnectedToMaster()
  36. commandEnv.MasterClient.WaitUntilConnected()
  37. if commandEnv.option.FilerAddress != "" {
  38. commandEnv.WithFilerClient(func(filerClient filer_pb.SeaweedFilerClient) error {
  39. resp, err := filerClient.GetFilerConfiguration(context.Background(), &filer_pb.GetFilerConfigurationRequest{})
  40. if err != nil {
  41. return err
  42. }
  43. if resp.ClusterId != "" {
  44. fmt.Printf(`
  45. ---
  46. Free Monitoring Data URL:
  47. https://cloud.seaweedfs.com/ui/%s
  48. ---
  49. `, resp.ClusterId)
  50. }
  51. return nil
  52. })
  53. }
  54. for {
  55. cmd, err := line.Prompt("> ")
  56. if err != nil {
  57. if err != io.EOF {
  58. fmt.Printf("%v\n", err)
  59. }
  60. return
  61. }
  62. for _, c := range strings.Split(cmd, ";") {
  63. if processEachCmd(reg, c, commandEnv) {
  64. return
  65. }
  66. }
  67. }
  68. }
  69. func processEachCmd(reg *regexp.Regexp, cmd string, commandEnv *CommandEnv) bool {
  70. cmds := reg.FindAllString(cmd, -1)
  71. if len(cmds) == 0 {
  72. return false
  73. } else {
  74. line.AppendHistory(cmd)
  75. args := make([]string, len(cmds[1:]))
  76. for i := range args {
  77. args[i] = strings.Trim(string(cmds[1+i]), "\"'")
  78. }
  79. cmd := cmds[0]
  80. if cmd == "help" || cmd == "?" {
  81. printHelp(cmds)
  82. } else if cmd == "exit" || cmd == "quit" {
  83. return true
  84. } else {
  85. foundCommand := false
  86. for _, c := range Commands {
  87. if c.Name() == cmd || c.Name() == "fs."+cmd {
  88. if err := c.Do(args, commandEnv, os.Stdout); err != nil {
  89. fmt.Fprintf(os.Stderr, "error: %v\n", err)
  90. }
  91. foundCommand = true
  92. }
  93. }
  94. if !foundCommand {
  95. fmt.Fprintf(os.Stderr, "unknown command: %v\n", cmd)
  96. }
  97. }
  98. }
  99. return false
  100. }
  101. func printGenericHelp() {
  102. msg :=
  103. `Type: "help <command>" for help on <command>. Most commands support "<command> -h" also for options.
  104. `
  105. fmt.Print(msg)
  106. for _, c := range Commands {
  107. helpTexts := strings.SplitN(c.Help(), "\n", 2)
  108. fmt.Printf(" %-30s\t# %s \n", c.Name(), helpTexts[0])
  109. }
  110. }
  111. func printHelp(cmds []string) {
  112. args := cmds[1:]
  113. if len(args) == 0 {
  114. printGenericHelp()
  115. } else if len(args) > 1 {
  116. fmt.Println()
  117. } else {
  118. cmd := strings.ToLower(args[0])
  119. for _, c := range Commands {
  120. if c.Name() == cmd {
  121. fmt.Printf(" %s\t# %s\n", c.Name(), c.Help())
  122. }
  123. }
  124. }
  125. }
  126. func setCompletionHandler() {
  127. line.SetCompleter(func(line string) (c []string) {
  128. for _, i := range Commands {
  129. if strings.HasPrefix(i.Name(), strings.ToLower(line)) {
  130. c = append(c, i.Name())
  131. }
  132. }
  133. return
  134. })
  135. }
  136. func loadHistory() {
  137. if f, err := os.Open(historyPath); err == nil {
  138. line.ReadHistory(f)
  139. f.Close()
  140. }
  141. }
  142. func saveHistory() {
  143. if f, err := os.Create(historyPath); err != nil {
  144. fmt.Printf("Error creating history file: %v\n", err)
  145. } else {
  146. if _, err = line.WriteHistory(f); err != nil {
  147. fmt.Printf("Error writing history file: %v\n", err)
  148. }
  149. f.Close()
  150. }
  151. }