// Package rcd provides the rcd command. package rcd import ( "context" "log" "sync" sysdnotify "github.com/iguanesolutions/go-systemd/v5/notify" "github.com/rclone/rclone/cmd" "github.com/rclone/rclone/fs/rc/rcflags" "github.com/rclone/rclone/fs/rc/rcserver" "github.com/rclone/rclone/lib/atexit" libhttp "github.com/rclone/rclone/lib/http" "github.com/spf13/cobra" ) func init() { cmd.Root.AddCommand(commandDefinition) } var commandDefinition = &cobra.Command{ Use: "rcd *", Short: `Run rclone listening to remote control commands only.`, Long: ` This runs rclone so that it only listens to remote control commands. This is useful if you are controlling rclone via the rc API. If you pass in a path to a directory, rclone will serve that directory for GET requests on the URL passed in. It will also open the URL in the browser when rclone is run. See the [rc documentation](/rc/) for more info on the rc flags. ` + libhttp.Help(rcflags.FlagPrefix) + libhttp.TemplateHelp(rcflags.FlagPrefix) + libhttp.AuthHelp(rcflags.FlagPrefix), Annotations: map[string]string{ "versionIntroduced": "v1.45", "groups": "RC", }, Run: func(command *cobra.Command, args []string) { cmd.CheckArgs(0, 1, command, args) if rcflags.Opt.Enabled { log.Fatalf("Don't supply --rc flag when using rcd") } // Start the rc rcflags.Opt.Enabled = true if len(args) > 0 { rcflags.Opt.Files = args[0] } s, err := rcserver.Start(context.Background(), &rcflags.Opt) if err != nil { log.Fatalf("Failed to start remote control: %v", err) } if s == nil { log.Fatal("rc server not configured") } // Notify stopping on exit var finaliseOnce sync.Once finalise := func() { finaliseOnce.Do(func() { _ = sysdnotify.Stopping() }) } fnHandle := atexit.Register(finalise) defer atexit.Unregister(fnHandle) // Notify ready to systemd if err := sysdnotify.Ready(); err != nil { log.Fatalf("failed to notify ready to systemd: %v", err) } s.Wait() finalise() }, }