diff --git a/cmd/mountlib/mount.go b/cmd/mountlib/mount.go index a94f4a7dd..34795be60 100644 --- a/cmd/mountlib/mount.go +++ b/cmd/mountlib/mount.go @@ -23,7 +23,7 @@ import ( "github.com/rclone/rclone/vfs/vfscommon" "github.com/rclone/rclone/vfs/vfsflags" - sysdnotify "github.com/iguanesolutions/go-systemd/v5/notify" + "github.com/coreos/go-systemd/v22/daemon" "github.com/spf13/cobra" "github.com/spf13/pflag" ) @@ -222,10 +222,10 @@ func NewMountCommand(commandName string, hidden bool, mount MountFn) *cobra.Comm } mnt := NewMountPoint(mount, args[1], cmd.NewFsDir(args), &Opt, &vfsflags.Opt) - daemon, err := mnt.Mount() + mountDaemon, err := mnt.Mount() // Wait for foreground mount, if any... - if daemon == nil { + if mountDaemon == nil { if err == nil { err = mnt.Wait() } @@ -235,15 +235,15 @@ func NewMountCommand(commandName string, hidden bool, mount MountFn) *cobra.Comm return } - // Wait for daemon, if any... + // Wait for mountDaemon, if any... killOnce := sync.Once{} killDaemon := func(reason string) { killOnce.Do(func() { - if err := daemon.Signal(os.Interrupt); err != nil { - fs.Errorf(nil, "%s. Failed to terminate daemon pid %d: %v", reason, daemon.Pid, err) + if err := mountDaemon.Signal(os.Interrupt); err != nil { + fs.Errorf(nil, "%s. Failed to terminate daemon pid %d: %v", reason, mountDaemon.Pid, err) return } - fs.Debugf(nil, "%s. Terminating daemon pid %d", reason, daemon.Pid) + fs.Debugf(nil, "%s. Terminating daemon pid %d", reason, mountDaemon.Pid) }) } @@ -251,7 +251,7 @@ func NewMountCommand(commandName string, hidden bool, mount MountFn) *cobra.Comm handle := atexit.Register(func() { killDaemon("Got interrupt") }) - err = WaitMountReady(mnt.MountPoint, Opt.DaemonWait, daemon) + err = WaitMountReady(mnt.MountPoint, Opt.DaemonWait, mountDaemon) if err != nil { killDaemon("Daemon timed out") } @@ -275,7 +275,7 @@ func NewMountCommand(commandName string, hidden bool, mount MountFn) *cobra.Comm } // Mount the remote at mountpoint -func (m *MountPoint) Mount() (daemon *os.Process, err error) { +func (m *MountPoint) Mount() (mountDaemon *os.Process, err error) { // Ensure sensible defaults m.SetVolumeName(m.MountOpt.VolumeName) @@ -283,9 +283,9 @@ func (m *MountPoint) Mount() (daemon *os.Process, err error) { // Start background task if --daemon is specified if m.MountOpt.Daemon { - daemon, err = daemonize.StartDaemon(os.Args) - if daemon != nil || err != nil { - return daemon, err + mountDaemon, err = daemonize.StartDaemon(os.Args) + if mountDaemon != nil || err != nil { + return mountDaemon, err } } @@ -305,7 +305,7 @@ func (m *MountPoint) Wait() error { var finaliseOnce sync.Once finalise := func() { finaliseOnce.Do(func() { - _ = sysdnotify.Stopping() + _, _ = daemon.SdNotify(false, daemon.SdNotifyStopping) // Unmount only if directory was mounted by rclone, e.g. don't unmount autofs hooks. if err := CheckMountReady(m.MountPoint); err != nil { fs.Debugf(m.MountPoint, "Unmounted externally. Just exit now.") @@ -322,7 +322,7 @@ func (m *MountPoint) Wait() error { defer atexit.Unregister(fnHandle) // Notify systemd - if err := sysdnotify.Ready(); err != nil { + if _, err := daemon.SdNotify(false, daemon.SdNotifyReady); err != nil { return fmt.Errorf("failed to notify systemd: %w", err) } diff --git a/cmd/serve/docker/driver.go b/cmd/serve/docker/driver.go index dfdb190f9..278a24e31 100644 --- a/cmd/serve/docker/driver.go +++ b/cmd/serve/docker/driver.go @@ -12,8 +12,7 @@ import ( "sync" "time" - sysdnotify "github.com/iguanesolutions/go-systemd/v5/notify" - + "github.com/coreos/go-systemd/v22/daemon" "github.com/rclone/rclone/cmd/mountlib" "github.com/rclone/rclone/fs" "github.com/rclone/rclone/fs/config" @@ -87,7 +86,7 @@ func NewDriver(ctx context.Context, root string, mntOpt *mountlib.Options, vfsOp }) // notify systemd - if err := sysdnotify.Ready(); err != nil { + if _, err := daemon.SdNotify(false, daemon.SdNotifyReady); err != nil { return nil, fmt.Errorf("failed to notify systemd: %w", err) } @@ -100,7 +99,10 @@ func (drv *Driver) Exit() { drv.mu.Lock() defer drv.mu.Unlock() - reportErr(sysdnotify.Stopping()) + reportErr(func() error { + _, err := daemon.SdNotify(false, daemon.SdNotifyStopping) + return err + }()) drv.monChan <- true // ask monitor to exit for _, vol := range drv.volumes { reportErr(vol.unmountAll()) diff --git a/cmd/serve/docker/systemd.go b/cmd/serve/docker/systemd.go index 981964c1b..8a69f6b08 100644 --- a/cmd/serve/docker/systemd.go +++ b/cmd/serve/docker/systemd.go @@ -6,8 +6,8 @@ package docker import ( "os" - "github.com/coreos/go-systemd/activation" - "github.com/coreos/go-systemd/util" + "github.com/coreos/go-systemd/v22/activation" + "github.com/coreos/go-systemd/v22/util" ) func systemdActivationFiles() []*os.File { diff --git a/fs/log/log.go b/fs/log/log.go index 9c66fdf02..bf2bfd74b 100644 --- a/fs/log/log.go +++ b/fs/log/log.go @@ -10,7 +10,6 @@ import ( "runtime" "strings" - systemd "github.com/iguanesolutions/go-systemd/v5" "github.com/rclone/rclone/fs" "github.com/sirupsen/logrus" ) @@ -49,7 +48,7 @@ func fnName() string { // Trace debugs the entry and exit of the calling function // -// It is designed to be used in a defer statement so it returns a +// It is designed to be used in a defer statement, so it returns a // function that logs the exit parameters. // // Any pointers in the exit function will be dereferenced @@ -141,7 +140,7 @@ func InitLogging() { // Activate systemd logger support if systemd invocation ID is // detected and output is going to stderr (not logging to a file or syslog) if !Redirected() { - if _, usingSystemd := systemd.GetInvocationID(); usingSystemd { + if isJournalStream() { Opt.LogSystemdSupport = true } } diff --git a/fs/log/systemd.go b/fs/log/systemd.go index 2e572790a..c09227b09 100644 --- a/fs/log/systemd.go +++ b/fs/log/systemd.go @@ -1,7 +1,7 @@ // Systemd interface for non-Unix variants only -//go:build windows || nacl || plan9 -// +build windows nacl plan9 +//go:build !unix +// +build !unix package log @@ -10,8 +10,12 @@ import ( "runtime" ) -// Enables systemd logs if configured or if auto detected +// Enables systemd logs if configured or if auto-detected func startSystemdLog() bool { log.Fatalf("--log-systemd not supported on %s platform", runtime.GOOS) return false } + +func isJournalStream() bool { + return false +} diff --git a/fs/log/systemd_unix.go b/fs/log/systemd_unix.go index a2aa8e51c..fa6700734 100644 --- a/fs/log/systemd_unix.go +++ b/fs/log/systemd_unix.go @@ -1,20 +1,21 @@ // Systemd interface for Unix variants only -//go:build !windows && !nacl && !plan9 -// +build !windows,!nacl,!plan9 +//go:build unix +// +build unix package log import ( "fmt" "log" + "strconv" "strings" - sysdjournald "github.com/iguanesolutions/go-systemd/v5/journald" + "github.com/coreos/go-systemd/v22/journal" "github.com/rclone/rclone/fs" ) -// Enables systemd logs if configured or if auto detected +// Enables systemd logs if configured or if auto-detected func startSystemdLog() bool { flagsStr := "," + Opt.Format + "," var flags int @@ -25,27 +26,36 @@ func startSystemdLog() bool { flags |= log.Lshortfile } log.SetFlags(flags) + // TODO: Use the native journal.Print approach rather than a custom implementation fs.LogPrint = func(level fs.LogLevel, text string) { - text = fmt.Sprintf("%s%-6s: %s", systemdLogPrefix(level), level, text) + text = fmt.Sprintf("<%s>%-6s: %s", systemdLogPrefix(level), level, text) _ = log.Output(4, text) } return true } -var logLevelToSystemdPrefix = []string{ - fs.LogLevelEmergency: sysdjournald.EmergPrefix, - fs.LogLevelAlert: sysdjournald.AlertPrefix, - fs.LogLevelCritical: sysdjournald.CritPrefix, - fs.LogLevelError: sysdjournald.ErrPrefix, - fs.LogLevelWarning: sysdjournald.WarningPrefix, - fs.LogLevelNotice: sysdjournald.NoticePrefix, - fs.LogLevelInfo: sysdjournald.InfoPrefix, - fs.LogLevelDebug: sysdjournald.DebugPrefix, +var logLevelToSystemdPrefix = []journal.Priority{ + fs.LogLevelEmergency: journal.PriEmerg, + fs.LogLevelAlert: journal.PriAlert, + fs.LogLevelCritical: journal.PriCrit, + fs.LogLevelError: journal.PriErr, + fs.LogLevelWarning: journal.PriWarning, + fs.LogLevelNotice: journal.PriNotice, + fs.LogLevelInfo: journal.PriInfo, + fs.LogLevelDebug: journal.PriDebug, } func systemdLogPrefix(l fs.LogLevel) string { if l >= fs.LogLevel(len(logLevelToSystemdPrefix)) { return "" } - return logLevelToSystemdPrefix[l] + return strconv.Itoa(int(logLevelToSystemdPrefix[l])) +} + +func isJournalStream() bool { + if usingJournald, _ := journal.StderrIsJournalStream(); usingJournald { + return true + } + + return false } diff --git a/go.mod b/go.mod index 228364041..046a3433c 100644 --- a/go.mod +++ b/go.mod @@ -23,7 +23,7 @@ require ( github.com/cloudsoda/go-smb2 v0.0.0-20231124195312-f3ec8ae2c891 github.com/colinmarc/hdfs/v2 v2.4.0 github.com/coreos/go-semver v0.3.1 - github.com/coreos/go-systemd v0.0.0-20191104093116-d3cd4ed1dbcf + github.com/coreos/go-systemd/v22 v22.5.0 github.com/dop251/scsu v0.0.0-20220106150536-84ac88021d00 github.com/dropbox/dropbox-sdk-go-unofficial/v6 v6.0.5 github.com/gabriel-vasile/mimetype v1.4.3 @@ -34,7 +34,6 @@ require ( github.com/hanwen/go-fuse/v2 v2.4.0 github.com/henrybear327/Proton-API-Bridge v1.0.0 github.com/henrybear327/go-proton-api v1.0.0 - github.com/iguanesolutions/go-systemd/v5 v5.1.1 github.com/jcmturner/gokrb5/v8 v8.4.4 github.com/jlaffaye/ftp v0.2.0 github.com/josephspurrier/goversioninfo v1.4.0 diff --git a/go.sum b/go.sum index dd7f7f0bc..f9b8ce299 100644 --- a/go.sum +++ b/go.sum @@ -140,8 +140,8 @@ github.com/colinmarc/hdfs/v2 v2.4.0 h1:v6R8oBx/Wu9fHpdPoJJjpGSUxo8NhHIwrwsfhFvU9 github.com/colinmarc/hdfs/v2 v2.4.0/go.mod h1:0NAO+/3knbMx6+5pCv+Hcbaz4xn/Zzbn9+WIib2rKVI= github.com/coreos/go-semver v0.3.1 h1:yi21YpKnrx1gt5R+la8n5WgS0kCrsPp33dmEyHReZr4= github.com/coreos/go-semver v0.3.1/go.mod h1:irMmmIw/7yzSRPWryHsK7EYSg09caPQL03VsM8rvUec= -github.com/coreos/go-systemd v0.0.0-20191104093116-d3cd4ed1dbcf h1:iW4rZ826su+pqaw19uhpSCzhj44qo35pNgKFGqzDKkU= -github.com/coreos/go-systemd v0.0.0-20191104093116-d3cd4ed1dbcf/go.mod h1:F5haX7vjVVG0kc13fIWeqUViNPyEJxv/OmvnBo0Yme4= +github.com/coreos/go-systemd/v22 v22.5.0 h1:RrqgGjYQKalulkV8NGVIfkXQf6YYmOyiJKk8iXXhfZs= +github.com/coreos/go-systemd/v22 v22.5.0/go.mod h1:Y58oyj3AT4RCenI/lSvhwexgC+NSVTIJ3seZv2GcEnc= github.com/cpuguy83/go-md2man/v2 v2.0.2/go.mod h1:tgQtvFlXSQOSOSIRvRPT7W67SCa46tRHOmNcaadrF8o= github.com/cpuguy83/go-md2man/v2 v2.0.3 h1:qMCsGGgs+MAzDFyp9LpAe1Lqy/fY/qCovCm0qnXZOBM= github.com/cpuguy83/go-md2man/v2 v2.0.3/go.mod h1:tgQtvFlXSQOSOSIRvRPT7W67SCa46tRHOmNcaadrF8o= @@ -315,8 +315,6 @@ github.com/henrybear327/go-proton-api v1.0.0 h1:zYi/IbjLwFAW7ltCeqXneUGJey0TN//X github.com/henrybear327/go-proton-api v1.0.0/go.mod h1:w63MZuzufKcIZ93pwRgiOtxMXYafI8H74D77AxytOBc= github.com/huandu/xstrings v1.0.0/go.mod h1:4qWG/gcEcfX4z/mBDHJ++3ReCw9ibxbsNJbcucJdbSo= github.com/ianlancetaylor/demangle v0.0.0-20181102032728-5e5cf60278f6/go.mod h1:aSSvb/t6k1mPoxDqO4vJh6VOCGPwU4O0C2/Eqndh1Sc= -github.com/iguanesolutions/go-systemd/v5 v5.1.1 h1:Hs0Z16knPGCBFnKECrICPh+RQ89Sgy0xyzcalrHMKdw= -github.com/iguanesolutions/go-systemd/v5 v5.1.1/go.mod h1:Quv57scs6S7T0rC6qyLfW20KU/P4p9hrbLPF+ILYrXY= github.com/inconshreveable/mousetrap v1.1.0 h1:wN+x4NVGpMsO7ErUn/mUI3vEoE6Jt13X2s0bqwp9tc8= github.com/inconshreveable/mousetrap v1.1.0/go.mod h1:vpF70FUmC8bwa3OWnCshd2FqLfsEA9PFc4w1p2J65bw= github.com/jcmturner/aescts/v2 v2.0.0 h1:9YKLH6ey7H4eDBXW8khjYslgyqG2xZikXP0EQFKrle8= @@ -395,7 +393,6 @@ github.com/mattn/go-runewidth v0.0.15 h1:UNAjwbU9l54TA3KzvqLGxwWjHmMgBUVhBiTjelZ github.com/mattn/go-runewidth v0.0.15/go.mod h1:Jdepj2loyihRzMpdS35Xk/zdY8IAYHsh153qUoGf23w= github.com/matttproud/golang_protobuf_extensions/v2 v2.0.0 h1:jWpvCLoY8Z/e3VKvlsiIGKtc+UG6U5vzxaoagmhXfyg= github.com/matttproud/golang_protobuf_extensions/v2 v2.0.0/go.mod h1:QUyp042oQthUoa9bqDv0ER0wrtXnBruoNd7aNjkbP+k= -github.com/miekg/dns v1.1.42/go.mod h1:+evo5L0630/F6ca/Z9+GAqzhjGyn8/c+TBaOyfEl0V4= github.com/minio/md5-simd v1.1.2 h1:Gdi1DZK69+ZVMoNHRXJyNcxrMA4dSxoYHZSQbirFg34= github.com/minio/md5-simd v1.1.2/go.mod h1:MzdKDxYpY2BT9XQFocsiZf/NKVtR7nkE4RoEpN+20RM= github.com/minio/minio-go/v6 v6.0.46/go.mod h1:qD0lajrGW49lKZLtXKtCB4X/qkMf0a5tBvN2PaZg7Gg= @@ -693,7 +690,6 @@ golang.org/x/sync v0.0.0-20200317015054-43a5402ce75a/go.mod h1:RxMgew5VJxzue5/jJ golang.org/x/sync v0.0.0-20200625203802-6e8e738ad208/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sync v0.0.0-20201020160332-67f06af15bc9/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sync v0.0.0-20201207232520-09787c993a3a/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= -golang.org/x/sync v0.0.0-20210220032951-036812b2e83c/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sync v0.0.0-20220722155255-886fb9371eb4/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sync v0.0.0-20220819030929-7fc1605a5dde/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sync v0.1.0/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= @@ -731,7 +727,6 @@ golang.org/x/sys v0.0.0-20200930185726-fdedc70b468f/go.mod h1:h1NjWce9XRLGQEsW7w golang.org/x/sys v0.0.0-20201119102817-f84b799fce68/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20201204225414-ed752295db88/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20210124154548-22da62e12c0c/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20210303074136-134d130e1a04/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20210423082822-04245dca01da/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20210514084401-e8d321eab015/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.0.0-20210615035016-665e8c7367d1/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= diff --git a/lib/systemd/notify.go b/lib/systemd/notify.go index a185b71a6..8dccafb4f 100644 --- a/lib/systemd/notify.go +++ b/lib/systemd/notify.go @@ -1,10 +1,11 @@ package systemd import ( + "fmt" "log" "sync" - sysdnotify "github.com/iguanesolutions/go-systemd/v5/notify" + "github.com/coreos/go-systemd/v22/daemon" "github.com/rclone/rclone/lib/atexit" ) @@ -13,13 +14,13 @@ import ( // stopping. This function will be called on exit if the service exits // on a signal. func Notify() func() { - if err := sysdnotify.Ready(); err != nil { + if _, err := daemon.SdNotify(false, daemon.SdNotifyReady); err != nil { log.Printf("failed to notify ready to systemd: %v", err) } var finaliseOnce sync.Once finalise := func() { finaliseOnce.Do(func() { - if err := sysdnotify.Stopping(); err != nil { + if _, err := daemon.SdNotify(false, daemon.SdNotifyStopping); err != nil { log.Printf("failed to notify stopping to systemd: %v", err) } }) @@ -30,3 +31,10 @@ func Notify() func() { finalise() } } + +// UpdateStatus updates the systemd status +func UpdateStatus(status string) error { + systemdStatus := fmt.Sprintf("STATUS=%s", status) + _, err := daemon.SdNotify(false, systemdStatus) + return err +} diff --git a/vfs/vfscache/cache.go b/vfs/vfscache/cache.go index e5bb19c79..9bcfc90ee 100644 --- a/vfs/vfscache/cache.go +++ b/vfs/vfscache/cache.go @@ -14,7 +14,6 @@ import ( "sync" "time" - sysdnotify "github.com/iguanesolutions/go-systemd/v5/notify" "github.com/rclone/rclone/fs" fscache "github.com/rclone/rclone/fs/cache" "github.com/rclone/rclone/fs/config" @@ -25,6 +24,7 @@ import ( "github.com/rclone/rclone/lib/diskusage" "github.com/rclone/rclone/lib/encoder" "github.com/rclone/rclone/lib/file" + "github.com/rclone/rclone/lib/systemd" "github.com/rclone/rclone/vfs/vfscache/writeback" "github.com/rclone/rclone/vfs/vfscommon" ) @@ -814,7 +814,7 @@ func (c *Cache) clean(kicked bool) { stats := fmt.Sprintf("objects %d (was %d) in use %d, to upload %d, uploading %d, total size %v (was %v)", newItems, oldItems, totalInUse, uploadsQueued, uploadsInProgress, newUsed, oldUsed) fs.Infof(nil, "vfs cache: cleaned: %s", stats) - if err = sysdnotify.Status(fmt.Sprintf("[%s] vfs cache: %s", time.Now().Format("15:04"), stats)); err != nil { + if err = systemd.UpdateStatus(fmt.Sprintf("[%s] vfs cache: %s", time.Now().Format("15:04"), stats)); err != nil { fs.Errorf(nil, "vfs cache: updating systemd status with current stats failed: %s", err) } }