dex

package
Version: v1.9.0 Latest Latest
Warning

This package is not in the latest version of its module.

Go to latest
Published: Jun 28, 2021 License: MIT Imports: 21 Imported by: 1

README

dex

dex is a new daemon plugin for cmdr. It's compatible with both windows, linux and macOS.

For more information, see
the example app: service

Install/Uninstall your service under linux distro

CentOS/RedHat/Ubuntu/Debian/...
sudo /path/to/app server install
sudo /path/to/app server uninstall

After installed, check out the service file at /etc/systemd/system/app-service-name.service.

These files/folders are compliant to standard systemd layouts:

  • Log file:
    • /var/log/app-service-name/app-service-name.out
    • /var/log/app-service-name/app-service-name.err
  • Working Directory:
    • /var/lib/app-service-name
  • Configurations: The configuration files must be copied to /etc ...
    • etc:
      • /etc/app-service-name/app-service-name.yml
      • /etc/app-service-name/conf.d/*.yml
      • /etc/app-service-name/certs: the certification files for web server
    • default: the default config options can be written to these locations
      • /etc/default/app-service-name for some distros, the location might be /etc/sysconfig/app-service-name.
SELinux PRB 203/EXEC

For CentOS and others SELinux enabled distros, you might get the error message or status about app-service-name.service: Main process exited, code=exited, status=203/EXEC, if you're running/starting up the service from a nonstandard location such as /home/you/go/bin/xxx.

In /var/log/messages, the slight clear information can be found like:

May  2 23:00:16 c8 systemd[21010]: my-service.service: Failed to execute command: Permission denied
May  2 23:00:16 c8 systemd[21010]: ny-service.service: Failed at step EXEC spawning /home/worker/src/backend/bin/my-service: Permission denied

So the reason is clear, the SELinux restricts binaries that can be used in ExecStart to paths that has system_u:object_r:bin_t:s0 attribute set. As we know, typically those are /usr/bin /usr/sbin /usr/libexec /usr/local/bin directories but /home/worker/src/backend/bin is not.

The solution is:

chcon -R -t bin_t /home/you/go/bin/

Sometimes you might wanna revoke it:

restorecon -r -v /home/you/go/bin/
start/stop the service

Use systemctl:

sudo systemctl start|stop|restart your-service.service

# start the service with OS starting?
sudo systemctl enable|disable your-service.service

Or start/stop/restart the service with its binary executable:

sudo /path/to/app server start|stop|restart
run from console

You can run the service at console mode:

/path/to/app server run
# Or: /path/to/app server start -f

dependencies

dex wraps "github.com/kardianos/service" to cmdr system.

Documentation

Index

Constants

This section is empty.

Variables

View Source
var (
	// DaemonServerCommand defines a group of sub-commands for daemon operations.
	DaemonServerCommand = &cmdr.Command{
		BaseOpt: cmdr.BaseOpt{

			Short:       "s",
			Full:        "server",
			Aliases:     []string{"svr", "daemon"},
			Description: "server ops: for linux daemon.",
			Group:       "Daemonization",
		},
		Flags: []*cmdr.Flag{
			{
				BaseOpt: cmdr.BaseOpt{
					Short:       "p",
					Full:        "port",
					Description: "main port (RESTful).",
				},
				DefaultValue: 3000,
			},
		},
		SubCommands: []*cmdr.Command{
			{
				BaseOpt: cmdr.BaseOpt{
					Short:       "s",
					Full:        "start",
					Aliases:     []string{"run", "startup"},
					Description: "startup this system service/daemon.",
					Action:      daemonStart,
					LongDescription: `**start** command make Program running as a daemon background.
**run** command make Program running in current tty foreground.
`,
					Examples: `
$ {{.AppName}} start
					make Program running as a daemon background.
$ {{.AppName}} start --foreground
					make Program running in current tty foreground.
$ {{.AppName}} run
					make Program running in current tty foreground.
$ {{.AppName}} stop
					stop daemonized Program.
$ {{.AppName}} reload
					send signal to trigger Program reload its configurations.
$ {{.AppName}} hot-reload [TODO]
					send signal to make Program restart itself without broken any connections.
$ {{.AppName}} status
					display the demonized Program running status.
$ {{.AppName}} install
					install Program as a daemon service (win, macOS, linux systemd/upstart/init).
$ {{.AppName}} uninstall
					remove the installed daemon service.
`,
				},
				Flags: []*cmdr.Flag{
					{
						BaseOpt: cmdr.BaseOpt{
							Short:       "f",
							Full:        "foreground",
							Aliases:     []string{"fg"},
							Description: "run on foreground, instead of demonized.",
						},
						DefaultValue: false,
					},
					{
						BaseOpt: cmdr.BaseOpt{
							Short:       "hr",
							Full:        "in-hot-reload",
							Aliases:     []string{"hot-restart"},
							Description: "app is been running in hot reload mode.",
							Hidden:      true,
						},
						DefaultValue: false,
					},
					{
						BaseOpt: cmdr.BaseOpt{
							Short:       "",
							Full:        "in-daemon",
							Description: "app is been running in daemon mode (special for windows service).",
							Hidden:      true,
						},
						DefaultValue: false,
					},
				},
			},
			{
				BaseOpt: cmdr.BaseOpt{
					Short:       "t",
					Full:        "stop",
					Aliases:     []string{"halt", "pause", "shutdown"},
					Description: "stop this system service/daemon.",
					Action:      daemonStop,
				},
				Flags: []*cmdr.Flag{
					{
						BaseOpt: cmdr.BaseOpt{
							Short:       "1",
							Full:        "hup",
							Description: "send SIGHUP - to reload service configurations",
						},
						DefaultValue: false,
					},
					{
						BaseOpt: cmdr.BaseOpt{
							Short:       "3",
							Full:        "quit",
							Description: "send SIGQUIT - to quit service gracefully",
						},
						DefaultValue: false,
					},
					{
						BaseOpt: cmdr.BaseOpt{
							Short:       "9",
							Full:        "kill",
							Description: "send SIGKILL - to quit service unconditionally",
						},
						DefaultValue: false,
					},
					{
						BaseOpt: cmdr.BaseOpt{
							Short:       "15",
							Full:        "term",
							Description: "send SIGTERM - to quit service gracefully",
						},
						DefaultValue: false,
					},
					{
						BaseOpt: cmdr.BaseOpt{
							Short:       "31",
							Full:        "usr2",
							Description: "send SIGUSR2 - to hot-restart service gracefully",
						},
						DefaultValue: false,
					},
				},
			},
			{
				BaseOpt: cmdr.BaseOpt{
					Short:       "re",
					Full:        "restart",
					Aliases:     []string{"reload"},
					Description: "reload configurations for this system service/daemon.",
					Action:      daemonRestart,
				},
			},
			{
				BaseOpt: cmdr.BaseOpt{
					Short:       "hr",
					Full:        "hot-reload",
					Aliases:     []string{"hot-restart", "live-reload"},
					Description: "hot-reload this system service/daemon.",
					LongDescription: `hot-restart/hot-reload/live-reload: 

This action will start a new child process and transfer all 
living connections to the child, and shutdown itself 
gracefully.
With this action, the service will keep serving without broken.
`,
					Action: daemonHotReload,
				},
			},
			{
				BaseOpt: cmdr.BaseOpt{
					Short:       "ss",
					Full:        "status",
					Aliases:     []string{"st"},
					Description: "display its running status as a system service/daemon.",
					Action:      daemonStatus,
				},
			},
			{
				BaseOpt: cmdr.BaseOpt{
					Short:       "i",
					Full:        "install",
					Aliases:     []string{"setup"},
					Description: "install as a system service/daemon.",
					Group:       "Config",
					Action:      daemonInstall,
				},
				Flags: []*cmdr.Flag{
					{
						BaseOpt: cmdr.BaseOpt{
							Short:       "s",
							Full:        "systemd",
							Aliases:     []string{"sys"},
							Description: "install as a systemd service.",
						},
						DefaultValue: true,
						ToggleGroup:  "service-type",
					},
					{
						BaseOpt: cmdr.BaseOpt{
							Short:       "u",
							Full:        "user",
							Aliases:     []string{"username"},
							Description: "service will run under this user.",
						},
						DefaultValue: "",
					},
					{
						BaseOpt: cmdr.BaseOpt{
							Short:       "g",
							Full:        "group",
							Aliases:     []string{"groupname"},
							Description: "service will run under this group.",
						},
						DefaultValue: "",
					},
				},
			},
			{
				BaseOpt: cmdr.BaseOpt{
					Short:       "u",
					Full:        "uninstall",
					Aliases:     []string{"remove"},
					Description: "remove from a system service/daemon.",
					Group:       "Config",
					Action:      daemonUninstall,
				},
				Flags: []*cmdr.Flag{
					{
						BaseOpt: cmdr.BaseOpt{
							Short:       "s",
							Full:        "systemd",
							Aliases:     []string{"sys"},
							Description: "uninstall the systemd service.",
						},
						DefaultValue: true,
						ToggleGroup:  "service-type",
					},
				},
			},
		},
	}
)
View Source
var ErrNoRoot = errors.New("MUST have administrator privileges")

ErrNoRoot error object: `MUST have administrator privileges`

Functions

func FindDaemonProcess

func FindDaemonProcess() (present bool, process *os.Process)

FindDaemonProcess locates the daemon process if running

func IsErrorAddressAlreadyInUse

func IsErrorAddressAlreadyInUse(err error) bool

IsErrorAddressAlreadyInUse tests if "bind: address already in use" found

func IsPidFileExists

func IsPidFileExists() bool

IsPidFileExists checks if the pid file exists or not

func IsRunningInDemonizedMode

func IsRunningInDemonizedMode() bool

IsRunningInDemonizedMode returns true if you are running under demonized mode. false means that you're running in normal console/tty mode.

func SetHotReloadSignals

func SetHotReloadSignals(sigfn func() []os.Signal)

SetHotReloadSignals allows an functor to provide a list of Signals

func SetOnGetListener

func SetOnGetListener(fn func() net.Listener)

SetOnGetListener returns tcp/http listener for daemon hot-restarting

func SetReloadSignals

func SetReloadSignals(sigfn func() []os.Signal)

SetReloadSignals allows an functor to provide a list of Signals

func SetSigEmtSignals

func SetSigEmtSignals(sigfn func() []os.Signal)

SetSigEmtSignals allows an functor to provide a list of Signals

func SetTermSignals

func SetTermSignals(sigfn func() []os.Signal)

SetTermSignals allows an functor to provide a list of Signals

func WithDaemon

func WithDaemon(daemonImplObject Daemon,

	opts ...Opt,
) cmdr.ExecOption

WithDaemon enables daemon plugin: - add daemon commands and sub-commands: start/run, stop, restart/reload, status, install/uninstall - pidfile -

Types

type Daemon

type Daemon interface {

	// OnRun will be invoked when daemon being started, run/fork at foreground, hot reload ...
	OnRun(program *Program, stopCh, doneCh chan struct{}, hotReloadListener net.Listener) (err error)
	OnStop(program *Program) (err error)
	OnReload(program *Program)
	OnStatus(program *Program, p *os.Process) (err error)
	OnInstall(program *Program) (err error)
	OnUninstall(program *Program) (err error)

	// OnReadConfigFromCommandLine(root *cmdr.RootCommand)
	BeforeServiceStart(program *Program, root *cmdr.Command) (err error)
	AfterServiceStop(program *Program, root *cmdr.Command) (err error)
	OnCmdrPrepare(program *Program, root *cmdr.RootCommand) (err error)
}

Daemon interface should be implemented when you are using `daemon.Enable()`.

type HotReloadable

type HotReloadable interface {
	OnHotReload(program *Program) (err error)
}

HotReloadable enables hot-restart/hot-reload feature

type Opt

type Opt func()

Opt is functional option type

func WithCommandsModifier

func WithCommandsModifier(modifier func(daemonServerCommand *cmdr.Command) *cmdr.Command) Opt

WithCommandsModifier could specify a modifier, which allows the tune can be applied onto daemon-server-command.

func WithLogger added in v1.7.6

func WithLogger(logger log.Logger) Opt

WithLogger sets the user-customizable logger

func WithLoggerForward

func WithLoggerForward(force bool) Opt

WithLoggerForward forwards all logging outputs to the out and err files. Typically the files could be found at `/var/log/<appname>/`.

func WithPostAction

func WithPostAction(action func(cmd *cmdr.Command, args []string)) Opt

WithPostAction appends a post-action handler to the post-actions chain.

func WithPreAction

func WithPreAction(action func(cmd *cmdr.Command, args []string) (err error)) Opt

WithPreAction appends a pre-action handler to the pre-actions chain.

func WithServiceConfig

func WithServiceConfig(config *service.Config) Opt

WithServiceConfig appends a customized *service.Config object

type Program

type Program struct {
	Config  *service.Config
	Service service.Service
	Logger  service.Logger

	// the arguments of cmdr entry.
	Command *cmdr.Command
	Args    []string
	Env     []string

	// InvokedInDaemon will be set to true if this daemon service is running under service/daemon manager.
	// For Windows, it's available if the service app has been starting from serivces.msc or by system automatically.
	// For macOS, the Launchctl starts it.
	// For Linux, systemd/upstart/sysv does it.
	//
	// The underlying detector
	InvokedInDaemon bool
	// InvokedDirectly means that administrator is running it from a tty/console/terminal.
	InvokedDirectly bool
	// ForwardLogToFile enables logging forward to /var/log if systemd mode enabled.
	ForwardLogToFile bool
	// contains filtered or unexported fields
}

func (*Program) EnvFileName

func (p *Program) EnvFileName() string

func (*Program) GetLogFileHandlers

func (p *Program) GetLogFileHandlers() (fOut, fErr *os.File)

func (*Program) LogStderrFileName

func (p *Program) LogStderrFileName() string

func (*Program) LogStdoutFileName

func (p *Program) LogStdoutFileName() string

func (*Program) PidFileName

func (p *Program) PidFileName() string

func (*Program) SocketFileName

func (p *Program) SocketFileName() string

func (*Program) Start

func (p *Program) Start(s service.Service) error

func (*Program) Stop

func (p *Program) Stop(s service.Service) (err error)

func (*Program) WorkDirName

func (p *Program) WorkDirName() string

Directories

Path Synopsis

Jump to

Keyboard shortcuts

? : This menu
/ : Search site
f or F : Jump to
y or Y : Canonical URL