Skip to content

Commit

Permalink
添加命令行补全功能
Browse files Browse the repository at this point in the history
修改add user子命令
  • Loading branch information
ren_jw committed Oct 3, 2020
1 parent 393136d commit 4e671f2
Show file tree
Hide file tree
Showing 8 changed files with 194 additions and 36 deletions.
25 changes: 16 additions & 9 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -31,17 +31,24 @@

## 安装

1.[下载release版本](https://github.com/weiliang-ms/easyctl/releases/)
> 下载上传
2.上传至/usr/sbin/下
[下载release版本](https://github.com/weiliang-ms/easyctl/releases/)

3.添加执行权限
上传至/usr/bin/下

chmod +x /usr/sbin/easyctl
> 添加执行权限
chmod +x /usr/bin/easyctl

4.查看版本信息
> 查看版本信息
easyctl version

> 配置命令补全
easyctl completion bash > /etc/bash_completion.d/easyctl
source <(easyctl completion bash)

# 命令介绍

Expand All @@ -65,11 +72,11 @@
1.添加可登录的linux用户(password可省,默认密码:user123)

easyctl add username password
easyctl add userad -u username -p password

2.添加非登录linux用户

easyctl add username --no-login=true
easyctl add -u username --no-login

# close指令集

Expand Down Expand Up @@ -117,7 +124,7 @@
easyctl install docker [flags]

flags 可选 --offline=true --file=./v19.03.13.tar.gz (离线安装)
flags 可选 --offline --file=./v19.03.13.tar.gz (离线安装)

> 在线安装样例
Expand Down Expand Up @@ -276,7 +283,7 @@ flag

8.主机host解析

9.添加命令自动补全
9.添加命令自动补全(已完成)

## 开源项目

Expand Down
28 changes: 16 additions & 12 deletions cmd/add.go
Original file line number Diff line number Diff line change
Expand Up @@ -5,12 +5,18 @@ import (
"github.com/spf13/cobra"
)

var Nologin bool
var (
Nologin bool
username string
password string
)

func init() {

addUserCmd.Flags().BoolVarP(&Nologin, "no-login", "n", false, "User type: no login")
addUserCmd.Flags().Parsed()
addUserCmd.Flags().StringVarP(&username, "username", "u", "", "user name")
addUserCmd.Flags().StringVarP(&password, "password", "p", "", "user password")
addUserCmd.MarkFlagRequired("username")

addCmd.AddCommand(addUserCmd)
rootCmd.AddCommand(addCmd)
Expand All @@ -30,21 +36,19 @@ var addCmd = &cobra.Command{

// addUser命令
var addUserCmd = &cobra.Command{
Use: "user [username] [password] [flags]",
Use: "user [flags]",
Short: "add linux user through easyctl, password default value: user123",
Example: "\neasyctl add user user1 password" +
"\neasyctl add user user1 password --no-login",
Example: "\neasyctl add user -u user1 -p password" +
"\neasyctl add user -u user1 --no-login",
Run: func(cmd *cobra.Command, args []string) {
addUser(args)
addUser()
},
Args: cobra.MinimumNArgs(1),
Args: cobra.NoArgs,
}

func addUser(args []string) {
password := ""
username := args[0]
if len(args) > 1 {
password = args[1]
func addUser() {
if password == "" {
password = "user123"
}
sys.AddUser(username, password, !Nologin)
}
61 changes: 61 additions & 0 deletions cmd/complete.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,61 @@
package cmd

import (
"github.com/spf13/cobra"
"os"
)

func init() {
rootCmd.AddCommand(completionCmd)
}

var completionCmd = &cobra.Command{
Use: "completion [bash|zsh|fish|powershell]",
Short: "Generate completion script",
Long: `To load completions:
Bash:
$ source <(yourprogram completion bash)
# To load completions for each session, execute once:
Linux:
$ yourprogram completion bash > /etc/bash_completion.d/yourprogram
MacOS:
$ yourprogram completion bash > /usr/local/etc/bash_completion.d/yourprogram
Zsh:
# If shell completion is not already enabled in your environment you will need
# to enable it. You can execute the following once:
$ echo "autoload -U compinit; compinit" >> ~/.zshrc
# To load completions for each session, execute once:
$ yourprogram completion zsh > "${fpath[1]}/_yourprogram"
# You will need to start a new shell for this setup to take effect.
Fish:
$ yourprogram completion fish | source
# To load completions for each session, execute once:
$ yourprogram completion fish > ~/.config/fish/completions/yourprogram.fish
`,
DisableFlagsInUseLine: true,
ValidArgs: []string{"bash", "zsh", "fish", "powershell"},
Args: cobra.ExactValidArgs(1),
Run: func(cmd *cobra.Command, args []string) {
switch args[0] {
case "bash":
cmd.Root().GenBashCompletion(os.Stdout)
case "zsh":
cmd.Root().GenZshCompletion(os.Stdout)
case "fish":
cmd.Root().GenFishCompletion(os.Stdout, true)
case "powershell":
cmd.Root().GenPowerShellCompletion(os.Stdout)
}
},
}
28 changes: 15 additions & 13 deletions cmd/install.go
Original file line number Diff line number Diff line change
Expand Up @@ -29,14 +29,14 @@ var (
func init() {
netConnectErr = errors.New("网络连接异常,请选择离线方式安装...")
installErr = errors.New("程序安装失败...")
installRedisCmd.Flags().BoolVarP(&offline, "offline", "o", false, "offline mode")
installRedisCmd.Flags().StringVarP(&redisPort, "port", "p", "6379", "Redis listen port")
installRedisCmd.Flags().StringVarP(&redisBindIP, "bind", "b", "0.0.0.0", "Redis bind address")
installRedisCmd.Flags().StringVarP(&redisPassword, "password", "a", "redis", "Redis password")
installRedisCmd.Flags().StringVarP(&redisDataDir, "data", "d", "/var/lib/redis", "Redis persistent directory")
installRedisCmd.Flags().StringVarP(&redisLogDir, "log-file", "", "/var/log/redis", "Redis logfile directory")
installRedisCmd.Flags().StringVarP(&filePath, "file", "f", "", "docker-x-x-x.tgz path")
installRedisCmd.Flags().StringVarP(&redisBinaryPath, "binary-path", "", "/usr/bin/", "redis-* binary file path")
installRedisCmd.Flags().BoolVarP(&offline, "offline", "o", false, "offline mode 离线模式")
installRedisCmd.Flags().StringVarP(&redisPort, "port", "p", "6379", "Redis listen port 监听端口")
installRedisCmd.Flags().StringVarP(&redisBindIP, "bind", "b", "0.0.0.0", "Redis bind address 监听地址")
installRedisCmd.Flags().StringVarP(&redisPassword, "password", "a", "redis", "Redis password 密码")
installRedisCmd.Flags().StringVarP(&redisDataDir, "data", "d", "/var/lib/redis", "Redis persistent directory 持久化目录")
installRedisCmd.Flags().StringVarP(&redisLogDir, "log-file", "", "/var/log/redis", "Redis logfile directory 日志目录")
installRedisCmd.Flags().StringVarP(&filePath, "file", "f", "", "docker-x-x-x.tgz path 安装包路径")
installRedisCmd.Flags().StringVarP(&redisBinaryPath, "binary-path", "", "/usr/bin/", "redis-* binary file path 二进制文件路径")

installDockerCmd.Flags().StringVarP(&filePath, "file", "f", "", "redis-x-x-x.tar.gz path")
installDockerCmd.Flags().BoolVarP(&offline, "offline", "o", false, "offline mode")
Expand All @@ -50,13 +50,16 @@ func init() {
// install命令
var installCmd = &cobra.Command{
Use: "install [OPTIONS] [flags]",
Short: "install some soft through easyctl",
Short: "install soft through easyctl",
Example: "\neasyctl install docker" +
"\neasyctl install nginx",
Run: func(cmd *cobra.Command, args []string) {
RunE: func(cmd *cobra.Command, args []string) error {
return parseCommand(cmd, args, installValidArgs)
},
Args: cobra.MinimumNArgs(1),
ValidArgsFunction: func(cmd *cobra.Command, args []string, toComplete string) ([]string, cobra.ShellCompDirective) {
return installValidArgs, cobra.ShellCompDirectiveNoFileComp
},
ValidArgs: installValidArgs,
Args: cobra.ExactValidArgs(1),
}

// install docker命令
Expand All @@ -66,7 +69,6 @@ var installDockerCmd = &cobra.Command{
Example: "\neasyctl install docker 在线安装docker" +
"\neasyctl install docker --offline --file=./docker-19.03.9.tgz 离线安装docker",
Run: func(cmd *cobra.Command, args []string) {
fmt.Println("dddddddddd", !offline)
if !offline {
installDockerOnline()
} else {
Expand Down
42 changes: 42 additions & 0 deletions cmd/root.go
Original file line number Diff line number Diff line change
@@ -1,9 +1,11 @@
package cmd

import (
"easyctl/util"
"fmt"
"github.com/spf13/cobra"
"os"
"strings"
)

var rootCmd = &cobra.Command{
Expand Down Expand Up @@ -37,3 +39,43 @@ func hasFlags(cmd *cobra.Command, args []string) bool {
)
return false
}

func findSuggestions(c *cobra.Command, arg string) string {
if c.DisableSuggestions {
return ""
}
if c.SuggestionsMinimumDistance <= 0 {
c.SuggestionsMinimumDistance = 2
}
suggestionsString := ""
if suggestions := c.SuggestionsFor(arg); len(suggestions) > 0 {
suggestionsString += "\n\nDid you mean this?\n"
for _, s := range suggestions {
suggestionsString += fmt.Sprintf("\t%v\n", s)
}
}
return suggestionsString
}

func parseCommand(cmd *cobra.Command, args []string, validArgs []string) error {
//func parseCommand(cmd *cobra.Command,args[] string,validArgs []string,minArgNum int,maxArgNum int) error{

//if minArgNum > len(args) {
// return fmt.Errorf("requires at least %d arg(s), only received %d", minArgNum, len(args))
//}
//
//if maxArgNum < len(args) {
// return fmt.Errorf("accepts at most %d arg(s), received %d", maxArgNum, len(args))
//}

for _, v := range validArgs {
validArgs = append(validArgs, strings.Split(v, "\t")[0])
}

for _, v := range args {
if !util.StringInSlice(v, validArgs) {
return fmt.Errorf("invalid argument %q for %q%s", v, cmd.CommandPath(), findSuggestions(cmd, args[0]))
}
}
return nil
}
2 changes: 1 addition & 1 deletion sys/info.go
Original file line number Diff line number Diff line change
Expand Up @@ -71,7 +71,7 @@ func init() {
func (system *SystemInfo) loadOSReleaseContent() {
//fmt.Println("获取操作系统版本信息...")
// todo 优化获取os类型代码
systemType, _ := util.ExecuteCmdAcceptResult("echo $OSTYPE")
systemType, _ := util.ExecuteCmdResult("echo $OSTYPE")
system.OSVersion.OSType = systemType
}

Expand Down
34 changes: 33 additions & 1 deletion util/execute.go
Original file line number Diff line number Diff line change
Expand Up @@ -27,7 +27,7 @@ func ExecuteCmd(command string) (err error, result string) {

func ExecuteCmdAcceptResult(command string) (result string, err error) {
cmd := exec.Command("/bin/bash", "-c", command)
fmt.Printf("[shell] 执行语句:%s\n", command)
//fmt.Printf("[shell] 执行语句:%s\n", command)
stderr, _ := cmd.StderrPipe()
stdout, _ := cmd.StdoutPipe()
if err := cmd.Start(); err != nil {
Expand Down Expand Up @@ -60,3 +60,35 @@ func ExecuteCmdAcceptResult(command string) (result string, err error) {
}
return result, nil
}

func ExecuteCmdResult(command string) (result string, err error) {
cmd := exec.Command("/bin/bash", "-c", command)
//fmt.Printf("[shell] 执行语句:%s\n", command)
stderr, _ := cmd.StderrPipe()
stdout, _ := cmd.StdoutPipe()
if err := cmd.Start(); err != nil {
return "", err
}
// 正常日志
logScan := bufio.NewScanner(stdout)
go func() {
for logScan.Scan() {
result = logScan.Text()
}
}()
// 错误日志
errBuf := bytes.NewBufferString("")
scan := bufio.NewScanner(stderr)
for scan.Scan() {
s := scan.Text()
errBuf.WriteString(s)
errBuf.WriteString("\n")
}
// 等待命令执行完
cmd.Wait()
if !cmd.ProcessState.Success() {
// 执行失败,返回错误信息
return "", errors.New(errBuf.String())
}
return result, nil
}
10 changes: 10 additions & 0 deletions util/slice.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
package util

func StringInSlice(a string, list []string) bool {
for _, b := range list {
if b == a {
return true
}
}
return false
}

0 comments on commit 4e671f2

Please sign in to comment.