root.go 7.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188
  1. // Package cmd provides Command Line Interface support
  2. package cmd
  3. import (
  4. "fmt"
  5. "os"
  6. "strconv"
  7. "github.com/drakkan/sftpgo/config"
  8. "github.com/drakkan/sftpgo/utils"
  9. "github.com/spf13/cobra"
  10. "github.com/spf13/viper"
  11. )
  12. const (
  13. logSender = "cmd"
  14. configDirFlag = "config-dir"
  15. configDirKey = "config_dir"
  16. configFileFlag = "config-file"
  17. configFileKey = "config_file"
  18. logFilePathFlag = "log-file-path"
  19. logFilePathKey = "log_file_path"
  20. logMaxSizeFlag = "log-max-size"
  21. logMaxSizeKey = "log_max_size"
  22. logMaxBackupFlag = "log-max-backups"
  23. logMaxBackupKey = "log_max_backups"
  24. logMaxAgeFlag = "log-max-age"
  25. logMaxAgeKey = "log_max_age"
  26. logCompressFlag = "log-compress"
  27. logCompressKey = "log_compress"
  28. logVerboseFlag = "log-verbose"
  29. logVerboseKey = "log_verbose"
  30. profilerFlag = "profiler"
  31. profilerKey = "profiler"
  32. defaultConfigDir = "."
  33. defaultConfigName = config.DefaultConfigName
  34. defaultLogFile = "sftpgo.log"
  35. defaultLogMaxSize = 10
  36. defaultLogMaxBackup = 5
  37. defaultLogMaxAge = 28
  38. defaultLogCompress = false
  39. defaultLogVerbose = true
  40. defaultProfiler = false
  41. )
  42. var (
  43. configDir string
  44. configFile string
  45. logFilePath string
  46. logMaxSize int
  47. logMaxBackups int
  48. logMaxAge int
  49. logCompress bool
  50. logVerbose bool
  51. profiler bool
  52. rootCmd = &cobra.Command{
  53. Use: "sftpgo",
  54. Short: "Full featured and highly configurable SFTP server",
  55. }
  56. )
  57. func init() {
  58. version := utils.GetAppVersion()
  59. rootCmd.Flags().BoolP("version", "v", false, "")
  60. rootCmd.Version = version.GetVersionAsString()
  61. rootCmd.SetVersionTemplate(`{{printf "SFTPGo version: "}}{{printf "%s" .Version}}
  62. `)
  63. }
  64. // Execute adds all child commands to the root command and sets flags appropriately.
  65. // This is called by main.main(). It only needs to happen once to the rootCmd.
  66. func Execute() {
  67. if err := rootCmd.Execute(); err != nil {
  68. fmt.Println(err)
  69. os.Exit(1)
  70. }
  71. }
  72. func addConfigFlags(cmd *cobra.Command) {
  73. viper.SetDefault(configDirKey, defaultConfigDir)
  74. viper.BindEnv(configDirKey, "SFTPGO_CONFIG_DIR")
  75. cmd.Flags().StringVarP(&configDir, configDirFlag, "c", viper.GetString(configDirKey),
  76. "Location for SFTPGo config dir. This directory should contain the \"sftpgo\" configuration file or the configured "+
  77. "config-file and it is used as the base for files with a relative path (eg. the private keys for the SFTP server, "+
  78. "the SQLite database if you use SQLite as data provider). This flag can be set using SFTPGO_CONFIG_DIR env var too.")
  79. viper.BindPFlag(configDirKey, cmd.Flags().Lookup(configDirFlag))
  80. viper.SetDefault(configFileKey, defaultConfigName)
  81. viper.BindEnv(configFileKey, "SFTPGO_CONFIG_FILE")
  82. cmd.Flags().StringVarP(&configFile, configFileFlag, "f", viper.GetString(configFileKey),
  83. "Name for SFTPGo configuration file. It must be the name of a file stored in config-dir not the absolute path to the "+
  84. "configuration file. The specified file name must have no extension we automatically load JSON, YAML, TOML, HCL and "+
  85. "Java properties. Therefore if you set \"sftpgo\" then \"sftpgo.json\", \"sftpgo.yaml\" and so on are searched. "+
  86. "This flag can be set using SFTPGO_CONFIG_FILE env var too.")
  87. viper.BindPFlag(configFileKey, cmd.Flags().Lookup(configFileFlag))
  88. }
  89. func addServeFlags(cmd *cobra.Command) {
  90. addConfigFlags(cmd)
  91. viper.SetDefault(logFilePathKey, defaultLogFile)
  92. viper.BindEnv(logFilePathKey, "SFTPGO_LOG_FILE_PATH")
  93. cmd.Flags().StringVarP(&logFilePath, logFilePathFlag, "l", viper.GetString(logFilePathKey),
  94. "Location for the log file. Leave empty to write logs to the standard output. This flag can be set using SFTPGO_LOG_FILE_PATH "+
  95. "env var too.")
  96. viper.BindPFlag(logFilePathKey, cmd.Flags().Lookup(logFilePathFlag))
  97. viper.SetDefault(logMaxSizeKey, defaultLogMaxSize)
  98. viper.BindEnv(logMaxSizeKey, "SFTPGO_LOG_MAX_SIZE")
  99. cmd.Flags().IntVarP(&logMaxSize, logMaxSizeFlag, "s", viper.GetInt(logMaxSizeKey),
  100. "Maximum size in megabytes of the log file before it gets rotated. This flag can be set using SFTPGO_LOG_MAX_SIZE "+
  101. "env var too. It is unused if log-file-path is empty.")
  102. viper.BindPFlag(logMaxSizeKey, cmd.Flags().Lookup(logMaxSizeFlag))
  103. viper.SetDefault(logMaxBackupKey, defaultLogMaxBackup)
  104. viper.BindEnv(logMaxBackupKey, "SFTPGO_LOG_MAX_BACKUPS")
  105. cmd.Flags().IntVarP(&logMaxBackups, "log-max-backups", "b", viper.GetInt(logMaxBackupKey),
  106. "Maximum number of old log files to retain. This flag can be set using SFTPGO_LOG_MAX_BACKUPS env var too. "+
  107. "It is unused if log-file-path is empty.")
  108. viper.BindPFlag(logMaxBackupKey, cmd.Flags().Lookup(logMaxBackupFlag))
  109. viper.SetDefault(logMaxAgeKey, defaultLogMaxAge)
  110. viper.BindEnv(logMaxAgeKey, "SFTPGO_LOG_MAX_AGE")
  111. cmd.Flags().IntVarP(&logMaxAge, "log-max-age", "a", viper.GetInt(logMaxAgeKey),
  112. "Maximum number of days to retain old log files. This flag can be set using SFTPGO_LOG_MAX_AGE env var too. "+
  113. "It is unused if log-file-path is empty.")
  114. viper.BindPFlag(logMaxAgeKey, cmd.Flags().Lookup(logMaxAgeFlag))
  115. viper.SetDefault(logCompressKey, defaultLogCompress)
  116. viper.BindEnv(logCompressKey, "SFTPGO_LOG_COMPRESS")
  117. cmd.Flags().BoolVarP(&logCompress, logCompressFlag, "z", viper.GetBool(logCompressKey), "Determine if the rotated "+
  118. "log files should be compressed using gzip. This flag can be set using SFTPGO_LOG_COMPRESS env var too. "+
  119. "It is unused if log-file-path is empty.")
  120. viper.BindPFlag(logCompressKey, cmd.Flags().Lookup(logCompressFlag))
  121. viper.SetDefault(logVerboseKey, defaultLogVerbose)
  122. viper.BindEnv(logVerboseKey, "SFTPGO_LOG_VERBOSE")
  123. cmd.Flags().BoolVarP(&logVerbose, logVerboseFlag, "v", viper.GetBool(logVerboseKey), "Enable verbose logs. "+
  124. "This flag can be set using SFTPGO_LOG_VERBOSE env var too.")
  125. viper.BindPFlag(logVerboseKey, cmd.Flags().Lookup(logVerboseFlag))
  126. viper.SetDefault(profilerKey, defaultProfiler)
  127. viper.BindEnv(profilerKey, "SFTPGO_PROFILER")
  128. cmd.Flags().BoolVarP(&profiler, profilerFlag, "p", viper.GetBool(profilerKey), "Enable the built-in profiler. "+
  129. "The profiler will be accessible via HTTP/HTTPS using the base URL \"/debug/pprof/\". "+
  130. "This flag can be set using SFTPGO_PROFILER env var too.")
  131. viper.BindPFlag(profilerKey, cmd.Flags().Lookup(profilerFlag))
  132. }
  133. func getCustomServeFlags() []string {
  134. result := []string{}
  135. if configDir != defaultConfigDir {
  136. configDir = utils.CleanDirInput(configDir)
  137. result = append(result, "--"+configDirFlag)
  138. result = append(result, configDir)
  139. }
  140. if configFile != defaultConfigName {
  141. result = append(result, "--"+configFileFlag)
  142. result = append(result, configFile)
  143. }
  144. if logFilePath != defaultLogFile {
  145. result = append(result, "--"+logFilePathFlag)
  146. result = append(result, logFilePath)
  147. }
  148. if logMaxSize != defaultLogMaxSize {
  149. result = append(result, "--"+logMaxSizeFlag)
  150. result = append(result, strconv.Itoa(logMaxSize))
  151. }
  152. if logMaxBackups != defaultLogMaxBackup {
  153. result = append(result, "--"+logMaxBackupFlag)
  154. result = append(result, strconv.Itoa(logMaxBackups))
  155. }
  156. if logMaxAge != defaultLogMaxAge {
  157. result = append(result, "--"+logMaxAgeFlag)
  158. result = append(result, strconv.Itoa(logMaxAge))
  159. }
  160. if logVerbose != defaultLogVerbose {
  161. result = append(result, "--"+logVerboseFlag+"=false")
  162. }
  163. if logCompress != defaultLogCompress {
  164. result = append(result, "--"+logCompressFlag+"=true")
  165. }
  166. if profiler != defaultProfiler {
  167. result = append(result, "--"+profilerFlag+"=true")
  168. }
  169. return result
  170. }