github.com/mattermosttest/mattermost-server/v5@v5.0.0-20200917143240-9dfa12e121f9/cmd/mattermost/commands/server.go (about)

     1  // Copyright (c) 2015-present Mattermost, Inc. All Rights Reserved.
     2  // See LICENSE.txt for license information.
     3  
     4  package commands
     5  
     6  import (
     7  	"net"
     8  	"os"
     9  	"os/signal"
    10  	"syscall"
    11  
    12  	"github.com/mattermost/mattermost-server/v5/api4"
    13  	"github.com/mattermost/mattermost-server/v5/app"
    14  	"github.com/mattermost/mattermost-server/v5/config"
    15  	"github.com/mattermost/mattermost-server/v5/manualtesting"
    16  	"github.com/mattermost/mattermost-server/v5/mlog"
    17  	"github.com/mattermost/mattermost-server/v5/utils"
    18  	"github.com/mattermost/mattermost-server/v5/web"
    19  	"github.com/mattermost/mattermost-server/v5/wsapi"
    20  	"github.com/mattermost/viper"
    21  	"github.com/pkg/errors"
    22  	"github.com/spf13/cobra"
    23  )
    24  
    25  var serverCmd = &cobra.Command{
    26  	Use:          "server",
    27  	Short:        "Run the Mattermost server",
    28  	RunE:         serverCmdF,
    29  	SilenceUsage: true,
    30  }
    31  
    32  func init() {
    33  	RootCmd.AddCommand(serverCmd)
    34  	RootCmd.RunE = serverCmdF
    35  }
    36  
    37  func serverCmdF(command *cobra.Command, args []string) error {
    38  	configDSN := viper.GetString("config")
    39  
    40  	disableConfigWatch, _ := command.Flags().GetBool("disableconfigwatch")
    41  	usedPlatform, _ := command.Flags().GetBool("platform")
    42  
    43  	interruptChan := make(chan os.Signal, 1)
    44  
    45  	if err := utils.TranslationsPreInit(); err != nil {
    46  		return errors.Wrapf(err, "unable to load Mattermost translation files")
    47  	}
    48  	configStore, err := config.NewStore(configDSN, !disableConfigWatch)
    49  	if err != nil {
    50  		return errors.Wrap(err, "failed to load configuration")
    51  	}
    52  
    53  	return runServer(configStore, disableConfigWatch, usedPlatform, interruptChan)
    54  }
    55  
    56  func runServer(configStore config.Store, disableConfigWatch bool, usedPlatform bool, interruptChan chan os.Signal) error {
    57  	options := []app.Option{
    58  		app.ConfigStore(configStore),
    59  		app.RunJobs,
    60  		app.JoinCluster,
    61  		app.StartSearchEngine,
    62  		app.StartMetrics,
    63  	}
    64  	server, err := app.NewServer(options...)
    65  	if err != nil {
    66  		mlog.Critical(err.Error())
    67  		return err
    68  	}
    69  	defer server.Shutdown()
    70  
    71  	if usedPlatform {
    72  		mlog.Error("The platform binary has been deprecated, please switch to using the mattermost binary.")
    73  	}
    74  
    75  	api := api4.Init(server, server.AppOptions, server.Router)
    76  	wsapi.Init(server)
    77  	web.New(server, server.AppOptions, server.Router)
    78  	api4.InitLocal(server, server.AppOptions, server.LocalRouter)
    79  
    80  	serverErr := server.Start()
    81  	if serverErr != nil {
    82  		mlog.Critical(serverErr.Error())
    83  		return serverErr
    84  	}
    85  
    86  	// If we allow testing then listen for manual testing URL hits
    87  	if *server.Config().ServiceSettings.EnableTesting {
    88  		manualtesting.Init(api)
    89  	}
    90  
    91  	notifyReady()
    92  
    93  	// wait for kill signal before attempting to gracefully shutdown
    94  	// the running service
    95  	signal.Notify(interruptChan, syscall.SIGINT, syscall.SIGTERM)
    96  	<-interruptChan
    97  
    98  	return nil
    99  }
   100  
   101  func notifyReady() {
   102  	// If the environment vars provide a systemd notification socket,
   103  	// notify systemd that the server is ready.
   104  	systemdSocket := os.Getenv("NOTIFY_SOCKET")
   105  	if systemdSocket != "" {
   106  		mlog.Info("Sending systemd READY notification.")
   107  
   108  		err := sendSystemdReadyNotification(systemdSocket)
   109  		if err != nil {
   110  			mlog.Error(err.Error())
   111  		}
   112  	}
   113  }
   114  
   115  func sendSystemdReadyNotification(socketPath string) error {
   116  	msg := "READY=1"
   117  	addr := &net.UnixAddr{
   118  		Name: socketPath,
   119  		Net:  "unixgram",
   120  	}
   121  	conn, err := net.DialUnix(addr.Net, nil, addr)
   122  	if err != nil {
   123  		return err
   124  	}
   125  	defer conn.Close()
   126  	_, err = conn.Write([]byte(msg))
   127  	return err
   128  }