|
@@ -1,185 +1,39 @@
|
|
|
package cmd
|
|
|
|
|
|
import (
|
|
|
- "fmt"
|
|
|
- "net/http"
|
|
|
- "os"
|
|
|
- "time"
|
|
|
-
|
|
|
- "github.com/drakkan/sftpgo/api"
|
|
|
- "github.com/drakkan/sftpgo/config"
|
|
|
- "github.com/drakkan/sftpgo/dataprovider"
|
|
|
- "github.com/drakkan/sftpgo/logger"
|
|
|
- "github.com/drakkan/sftpgo/sftpd"
|
|
|
- "github.com/rs/zerolog"
|
|
|
+ "github.com/drakkan/sftpgo/service"
|
|
|
"github.com/spf13/cobra"
|
|
|
- "github.com/spf13/viper"
|
|
|
-)
|
|
|
-
|
|
|
-const (
|
|
|
- configDirFlag = "config-dir"
|
|
|
- configDirKey = "config_dir"
|
|
|
- configFileFlag = "config-file"
|
|
|
- configFileKey = "config_file"
|
|
|
- logFilePathFlag = "log-file-path"
|
|
|
- logFilePathKey = "log_file_path"
|
|
|
- logMaxSizeFlag = "log-max-size"
|
|
|
- logMaxSizeKey = "log_max_size"
|
|
|
- logMaxBackupFlag = "log-max-backups"
|
|
|
- logMaxBackupKey = "log_max_backups"
|
|
|
- logMaxAgeFlag = "log-max-age"
|
|
|
- logMaxAgeKey = "log_max_age"
|
|
|
- logCompressFlag = "log-compress"
|
|
|
- logCompressKey = "log_compress"
|
|
|
- logVerboseFlag = "log-verbose"
|
|
|
- logVerboseKey = "log_verbose"
|
|
|
)
|
|
|
|
|
|
var (
|
|
|
- configDir string
|
|
|
- configFile string
|
|
|
- logFilePath string
|
|
|
- logMaxSize int
|
|
|
- logMaxBackups int
|
|
|
- logMaxAge int
|
|
|
- logCompress bool
|
|
|
- logVerbose bool
|
|
|
- testVar string
|
|
|
- serveCmd = &cobra.Command{
|
|
|
+ serveCmd = &cobra.Command{
|
|
|
Use: "serve",
|
|
|
Short: "Start the SFTP Server",
|
|
|
- Long: `To start the SFTP Server with the default values for the command line flags simply use:
|
|
|
+ Long: `To start the SFTPGo with the default values for the command line flags simply use:
|
|
|
|
|
|
sftpgo serve
|
|
|
-
|
|
|
+
|
|
|
Please take a look at the usage below to customize the startup options`,
|
|
|
Run: func(cmd *cobra.Command, args []string) {
|
|
|
- startServe()
|
|
|
+ service := service.Service{
|
|
|
+ ConfigDir: configDir,
|
|
|
+ ConfigFile: configFile,
|
|
|
+ LogFilePath: logFilePath,
|
|
|
+ LogMaxSize: logMaxSize,
|
|
|
+ LogMaxBackups: logMaxBackups,
|
|
|
+ LogMaxAge: logMaxAge,
|
|
|
+ LogCompress: logCompress,
|
|
|
+ LogVerbose: logVerbose,
|
|
|
+ Shutdown: make(chan bool),
|
|
|
+ }
|
|
|
+ if err := service.Start(); err == nil {
|
|
|
+ service.Wait()
|
|
|
+ }
|
|
|
},
|
|
|
}
|
|
|
)
|
|
|
|
|
|
func init() {
|
|
|
rootCmd.AddCommand(serveCmd)
|
|
|
-
|
|
|
- viper.SetDefault(configDirKey, ".")
|
|
|
- viper.BindEnv(configDirKey, "SFTPGO_CONFIG_DIR")
|
|
|
- serveCmd.Flags().StringVarP(&configDir, configDirFlag, "c", viper.GetString(configDirKey),
|
|
|
- "Location for SFTPGo config dir. This directory should contain the \"sftpgo\" configuration file or the configured "+
|
|
|
- "config-file and it is used as the base for files with a relative path (eg. the private keys for the SFTP server, "+
|
|
|
- "the SQLite database if you use SQLite as data provider). This flag can be set using SFTPGO_CONFIG_DIR env var too.")
|
|
|
- viper.BindPFlag(configDirKey, serveCmd.Flags().Lookup(configDirFlag))
|
|
|
-
|
|
|
- viper.SetDefault(configFileKey, config.DefaultConfigName)
|
|
|
- viper.BindEnv(configFileKey, "SFTPGO_CONFIG_FILE")
|
|
|
- serveCmd.Flags().StringVarP(&configFile, configFileFlag, "f", viper.GetString(configFileKey),
|
|
|
- "Name for SFTPGo configuration file. It must be the name of a file stored in config-dir not the absolute path to the "+
|
|
|
- "configuration file. The specified file name must have no extension we automatically load JSON, YAML, TOML, HCL and "+
|
|
|
- "Java properties. Therefore if you set \"sftpgo\" then \"sftpgo.json\", \"sftpgo.yaml\" and so on are searched. "+
|
|
|
- "This flag can be set using SFTPGO_CONFIG_FILE env var too.")
|
|
|
- viper.BindPFlag(configFileKey, serveCmd.Flags().Lookup(configFileFlag))
|
|
|
-
|
|
|
- viper.SetDefault(logFilePathKey, "sftpgo.log")
|
|
|
- viper.BindEnv(logFilePathKey, "SFTPGO_LOG_FILE_PATH")
|
|
|
- serveCmd.Flags().StringVarP(&logFilePath, logFilePathFlag, "l", viper.GetString(logFilePathKey),
|
|
|
- "Location for the log file. Leave empty to write logs to the standard output. This flag can be set using SFTPGO_LOG_FILE_PATH "+
|
|
|
- "env var too.")
|
|
|
- viper.BindPFlag(logFilePathKey, serveCmd.Flags().Lookup(logFilePathFlag))
|
|
|
-
|
|
|
- viper.SetDefault(logMaxSizeKey, 10)
|
|
|
- viper.BindEnv(logMaxSizeKey, "SFTPGO_LOG_MAX_SIZE")
|
|
|
- serveCmd.Flags().IntVarP(&logMaxSize, logMaxSizeFlag, "s", viper.GetInt(logMaxSizeKey),
|
|
|
- "Maximum size in megabytes of the log file before it gets rotated. This flag can be set using SFTPGO_LOG_MAX_SIZE "+
|
|
|
- "env var too. It is unused if log-file-path is empty.")
|
|
|
- viper.BindPFlag(logMaxSizeKey, serveCmd.Flags().Lookup(logMaxSizeFlag))
|
|
|
-
|
|
|
- viper.SetDefault(logMaxBackupKey, 5)
|
|
|
- viper.BindEnv(logMaxBackupKey, "SFTPGO_LOG_MAX_BACKUPS")
|
|
|
- serveCmd.Flags().IntVarP(&logMaxBackups, "log-max-backups", "b", viper.GetInt(logMaxBackupKey),
|
|
|
- "Maximum number of old log files to retain. This flag can be set using SFTPGO_LOG_MAX_BACKUPS env var too. "+
|
|
|
- "It is unused if log-file-path is empty.")
|
|
|
- viper.BindPFlag(logMaxBackupKey, serveCmd.Flags().Lookup(logMaxBackupFlag))
|
|
|
-
|
|
|
- viper.SetDefault(logMaxAgeKey, 28)
|
|
|
- viper.BindEnv(logMaxAgeKey, "SFTPGO_LOG_MAX_AGE")
|
|
|
- serveCmd.Flags().IntVarP(&logMaxAge, "log-max-age", "a", viper.GetInt(logMaxAgeKey),
|
|
|
- "Maximum number of days to retain old log files. This flag can be set using SFTPGO_LOG_MAX_AGE env var too. "+
|
|
|
- "It is unused if log-file-path is empty.")
|
|
|
- viper.BindPFlag(logMaxAgeKey, serveCmd.Flags().Lookup(logMaxAgeFlag))
|
|
|
-
|
|
|
- viper.SetDefault(logCompressKey, false)
|
|
|
- viper.BindEnv(logCompressKey, "SFTPGO_LOG_COMPRESS")
|
|
|
- serveCmd.Flags().BoolVarP(&logCompress, logCompressFlag, "z", viper.GetBool(logCompressKey), "Determine if the rotated "+
|
|
|
- "log files should be compressed using gzip. This flag can be set using SFTPGO_LOG_COMPRESS env var too. "+
|
|
|
- "It is unused if log-file-path is empty.")
|
|
|
- viper.BindPFlag(logCompressKey, serveCmd.Flags().Lookup(logCompressFlag))
|
|
|
-
|
|
|
- viper.SetDefault(logVerboseKey, true)
|
|
|
- viper.BindEnv(logVerboseKey, "SFTPGO_LOG_VERBOSE")
|
|
|
- serveCmd.Flags().BoolVarP(&logVerbose, logVerboseFlag, "v", viper.GetBool(logVerboseKey), "Enable verbose logs. "+
|
|
|
- "This flag can be set using SFTPGO_LOG_VERBOSE env var too.")
|
|
|
- viper.BindPFlag(logVerboseKey, serveCmd.Flags().Lookup(logVerboseFlag))
|
|
|
-}
|
|
|
-
|
|
|
-func startServe() {
|
|
|
- logLevel := zerolog.DebugLevel
|
|
|
- if !logVerbose {
|
|
|
- logLevel = zerolog.InfoLevel
|
|
|
- }
|
|
|
- logger.InitLogger(logFilePath, logMaxSize, logMaxBackups, logMaxAge, logCompress, logLevel)
|
|
|
- logger.Info(logSender, "", "starting SFTPGo, config dir: %v, config file: %v, log max size: %v log max backups: %v "+
|
|
|
- "log max age: %v log verbose: %v, log compress: %v", configDir, configFile, logMaxSize, logMaxBackups, logMaxAge,
|
|
|
- logVerbose, logCompress)
|
|
|
- config.LoadConfig(configDir, configFile)
|
|
|
- providerConf := config.GetProviderConf()
|
|
|
-
|
|
|
- err := dataprovider.Initialize(providerConf, configDir)
|
|
|
- if err != nil {
|
|
|
- logger.Error(logSender, "", "error initializing data provider: %v", err)
|
|
|
- logger.ErrorToConsole("error initializing data provider: %v", err)
|
|
|
- os.Exit(1)
|
|
|
- }
|
|
|
-
|
|
|
- dataProvider := dataprovider.GetProvider()
|
|
|
- sftpdConf := config.GetSFTPDConfig()
|
|
|
- httpdConf := config.GetHTTPDConfig()
|
|
|
-
|
|
|
- sftpd.SetDataProvider(dataProvider)
|
|
|
-
|
|
|
- shutdown := make(chan bool)
|
|
|
-
|
|
|
- go func() {
|
|
|
- logger.Debug(logSender, "", "initializing SFTP server with config %+v", sftpdConf)
|
|
|
- if err := sftpdConf.Initialize(configDir); err != nil {
|
|
|
- logger.Error(logSender, "", "could not start SFTP server: %v", err)
|
|
|
- logger.ErrorToConsole("could not start SFTP server: %v", err)
|
|
|
- }
|
|
|
- shutdown <- true
|
|
|
- }()
|
|
|
-
|
|
|
- if httpdConf.BindPort > 0 {
|
|
|
- router := api.GetHTTPRouter()
|
|
|
- api.SetDataProvider(dataProvider)
|
|
|
-
|
|
|
- go func() {
|
|
|
- logger.Debug(logSender, "", "initializing HTTP server with config %+v", httpdConf)
|
|
|
- s := &http.Server{
|
|
|
- Addr: fmt.Sprintf("%s:%d", httpdConf.BindAddress, httpdConf.BindPort),
|
|
|
- Handler: router,
|
|
|
- ReadTimeout: 300 * time.Second,
|
|
|
- WriteTimeout: 300 * time.Second,
|
|
|
- MaxHeaderBytes: 1 << 20, // 1MB
|
|
|
- }
|
|
|
- if err := s.ListenAndServe(); err != nil {
|
|
|
- logger.Error(logSender, "", "could not start HTTP server: %v", err)
|
|
|
- logger.ErrorToConsole("could not start HTTP server: %v", err)
|
|
|
- }
|
|
|
- shutdown <- true
|
|
|
- }()
|
|
|
- } else {
|
|
|
- logger.Debug(logSender, "", "HTTP server not started, disabled in config file")
|
|
|
- logger.DebugToConsole("HTTP server not started, disabled in config file")
|
|
|
- }
|
|
|
-
|
|
|
- <-shutdown
|
|
|
+ addServeFlags(serveCmd)
|
|
|
}
|