github.com/minio/minio@v0.0.0-20240328213742-3f72439b8a27/cmd/main.go (about) 1 // Copyright (c) 2015-2021 MinIO, Inc. 2 // 3 // This file is part of MinIO Object Storage stack 4 // 5 // This program is free software: you can redistribute it and/or modify 6 // it under the terms of the GNU Affero General Public License as published by 7 // the Free Software Foundation, either version 3 of the License, or 8 // (at your option) any later version. 9 // 10 // This program is distributed in the hope that it will be useful 11 // but WITHOUT ANY WARRANTY; without even the implied warranty of 12 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 13 // GNU Affero General Public License for more details. 14 // 15 // You should have received a copy of the GNU Affero General Public License 16 // along with this program. If not, see <http://www.gnu.org/licenses/>. 17 18 package cmd 19 20 import ( 21 "fmt" 22 "io" 23 "os" 24 "path/filepath" 25 "runtime" 26 "runtime/debug" 27 "sort" 28 "strconv" 29 "strings" 30 "time" 31 32 "github.com/minio/cli" 33 "github.com/minio/minio/internal/color" 34 "github.com/minio/minio/internal/logger" 35 "github.com/minio/pkg/v2/console" 36 "github.com/minio/pkg/v2/env" 37 "github.com/minio/pkg/v2/trie" 38 "github.com/minio/pkg/v2/words" 39 ) 40 41 // GlobalFlags - global flags for minio. 42 var GlobalFlags = []cli.Flag{ 43 // Deprecated flag, so its hidden now - existing deployments will keep working. 44 cli.StringFlag{ 45 Name: "config-dir, C", 46 Value: defaultConfigDir.Get(), 47 Usage: "[DEPRECATED] path to legacy configuration directory", 48 Hidden: true, 49 }, 50 cli.StringFlag{ 51 Name: "certs-dir, S", 52 Value: defaultCertsDir.Get(), 53 Usage: "path to certs directory", 54 }, 55 cli.BoolFlag{ 56 Name: "quiet", 57 Usage: "disable startup and info messages", 58 }, 59 cli.BoolFlag{ 60 Name: "anonymous", 61 Usage: "hide sensitive information from logging", 62 }, 63 cli.BoolFlag{ 64 Name: "json", 65 Usage: "output logs in JSON format", 66 }, 67 // Deprecated flag, so its hidden now, existing deployments will keep working. 68 cli.BoolFlag{ 69 Name: "compat", 70 Usage: "enable strict S3 compatibility by turning off certain performance optimizations", 71 Hidden: true, 72 }, 73 // This flag is hidden and to be used only during certain performance testing. 74 cli.BoolFlag{ 75 Name: "no-compat", 76 Usage: "disable strict S3 compatibility by turning on certain performance optimizations", 77 Hidden: true, 78 }, 79 } 80 81 // Help template for minio. 82 var minioHelpTemplate = `NAME: 83 {{.Name}} - {{.Usage}} 84 85 DESCRIPTION: 86 {{.Description}} 87 88 USAGE: 89 {{.HelpName}} {{if .VisibleFlags}}[FLAGS] {{end}}COMMAND{{if .VisibleFlags}}{{end}} [ARGS...] 90 91 COMMANDS: 92 {{range .VisibleCommands}}{{join .Names ", "}}{{ "\t" }}{{.Usage}} 93 {{end}}{{if .VisibleFlags}} 94 FLAGS: 95 {{range .VisibleFlags}}{{.}} 96 {{end}}{{end}} 97 VERSION: 98 {{.Version}} 99 ` 100 101 func newApp(name string) *cli.App { 102 // Collection of minio commands currently supported are. 103 commands := []cli.Command{} 104 105 // Collection of minio commands currently supported in a trie tree. 106 commandsTree := trie.NewTrie() 107 108 // registerCommand registers a cli command. 109 registerCommand := func(command cli.Command) { 110 commands = append(commands, command) 111 commandsTree.Insert(command.Name) 112 } 113 114 findClosestCommands := func(command string) []string { 115 var closestCommands []string 116 closestCommands = append(closestCommands, commandsTree.PrefixMatch(command)...) 117 118 sort.Strings(closestCommands) 119 // Suggest other close commands - allow missed, wrongly added and 120 // even transposed characters 121 for _, value := range commandsTree.Walk(commandsTree.Root()) { 122 if sort.SearchStrings(closestCommands, value) < len(closestCommands) { 123 continue 124 } 125 // 2 is arbitrary and represents the max 126 // allowed number of typed errors 127 if words.DamerauLevenshteinDistance(command, value) < 2 { 128 closestCommands = append(closestCommands, value) 129 } 130 } 131 132 return closestCommands 133 } 134 135 // Register all commands. 136 registerCommand(serverCmd) 137 registerCommand(gatewayCmd) // hidden kept for guiding users. 138 139 // Set up app. 140 cli.HelpFlag = cli.BoolFlag{ 141 Name: "help, h", 142 Usage: "show help", 143 } 144 cli.VersionPrinter = printMinIOVersion 145 146 app := cli.NewApp() 147 app.Name = name 148 app.Author = "MinIO, Inc." 149 app.Version = ReleaseTag 150 app.Usage = "High Performance Object Storage" 151 app.Description = `Build high performance data infrastructure for machine learning, analytics and application data workloads with MinIO` 152 app.Flags = GlobalFlags 153 app.HideHelpCommand = true // Hide `help, h` command, we already have `minio --help`. 154 app.Commands = commands 155 app.CustomAppHelpTemplate = minioHelpTemplate 156 app.CommandNotFound = func(ctx *cli.Context, command string) { 157 console.Printf("‘%s’ is not a minio sub-command. See ‘minio --help’.\n", command) 158 closestCommands := findClosestCommands(command) 159 if len(closestCommands) > 0 { 160 console.Println() 161 console.Println("Did you mean one of these?") 162 for _, cmd := range closestCommands { 163 console.Printf("\t‘%s’\n", cmd) 164 } 165 } 166 167 os.Exit(1) 168 } 169 170 return app 171 } 172 173 func startupBanner(banner io.Writer) { 174 CopyrightYear = strconv.Itoa(time.Now().Year()) 175 fmt.Fprintln(banner, color.Blue("Copyright:")+color.Bold(" 2015-%s MinIO, Inc.", CopyrightYear)) 176 fmt.Fprintln(banner, color.Blue("License:")+color.Bold(" "+MinioLicense)) 177 fmt.Fprintln(banner, color.Blue("Version:")+color.Bold(" %s (%s %s/%s)", ReleaseTag, runtime.Version(), runtime.GOOS, runtime.GOARCH)) 178 } 179 180 func versionBanner(c *cli.Context) io.Reader { 181 banner := &strings.Builder{} 182 fmt.Fprintln(banner, color.Bold("%s version %s (commit-id=%s)", c.App.Name, c.App.Version, CommitID)) 183 fmt.Fprintln(banner, color.Blue("Runtime:")+color.Bold(" %s %s/%s", runtime.Version(), runtime.GOOS, runtime.GOARCH)) 184 fmt.Fprintln(banner, color.Blue("License:")+color.Bold(" GNU AGPLv3 <https://www.gnu.org/licenses/agpl-3.0.html>")) 185 fmt.Fprintln(banner, color.Blue("Copyright:")+color.Bold(" 2015-%s MinIO, Inc.", CopyrightYear)) 186 return strings.NewReader(banner.String()) 187 } 188 189 func printMinIOVersion(c *cli.Context) { 190 io.Copy(c.App.Writer, versionBanner(c)) 191 } 192 193 // Main main for minio server. 194 func Main(args []string) { 195 // Set the minio app name. 196 appName := filepath.Base(args[0]) 197 198 if env.Get("_MINIO_DEBUG_NO_EXIT", "") != "" { 199 freeze := func(_ int) { 200 // Infinite blocking op 201 <-make(chan struct{}) 202 } 203 204 // Override the logger os.Exit() 205 logger.ExitFunc = freeze 206 207 defer func() { 208 if err := recover(); err != nil { 209 fmt.Println("panic:", err) 210 fmt.Println("") 211 fmt.Println(string(debug.Stack())) 212 } 213 freeze(-1) 214 }() 215 } 216 217 // Run the app - exit on error. 218 if err := newApp(appName).Run(args); err != nil { 219 os.Exit(1) //nolint:gocritic 220 } 221 }