github.com/10XDev/rclone@v1.52.3-0.20200626220027-16af9ab76b2a/fs/rc/internal.go (about) 1 // Define the internal rc functions 2 3 package rc 4 5 import ( 6 "context" 7 "os" 8 "runtime" 9 "time" 10 11 "github.com/pkg/errors" 12 13 "github.com/rclone/rclone/fs" 14 "github.com/rclone/rclone/fs/config/obscure" 15 "github.com/rclone/rclone/fs/version" 16 "github.com/rclone/rclone/lib/atexit" 17 ) 18 19 func init() { 20 Add(Call{ 21 Path: "rc/noopauth", 22 AuthRequired: true, 23 Fn: rcNoop, 24 Title: "Echo the input to the output parameters requiring auth", 25 Help: ` 26 This echoes the input parameters to the output parameters for testing 27 purposes. It can be used to check that rclone is still alive and to 28 check that parameter passing is working properly.`, 29 }) 30 Add(Call{ 31 Path: "rc/noop", 32 Fn: rcNoop, 33 Title: "Echo the input to the output parameters", 34 Help: ` 35 This echoes the input parameters to the output parameters for testing 36 purposes. It can be used to check that rclone is still alive and to 37 check that parameter passing is working properly.`, 38 }) 39 } 40 41 // Echo the input to the output parameters 42 func rcNoop(ctx context.Context, in Params) (out Params, err error) { 43 return in, nil 44 } 45 46 func init() { 47 Add(Call{ 48 Path: "rc/error", 49 Fn: rcError, 50 Title: "This returns an error", 51 Help: ` 52 This returns an error with the input as part of its error string. 53 Useful for testing error handling.`, 54 }) 55 } 56 57 // Return an error regardless 58 func rcError(ctx context.Context, in Params) (out Params, err error) { 59 return nil, errors.Errorf("arbitrary error on input %+v", in) 60 } 61 62 func init() { 63 Add(Call{ 64 Path: "rc/list", 65 Fn: rcList, 66 Title: "List all the registered remote control commands", 67 Help: ` 68 This lists all the registered remote control commands as a JSON map in 69 the commands response.`, 70 }) 71 } 72 73 // List the registered commands 74 func rcList(ctx context.Context, in Params) (out Params, err error) { 75 out = make(Params) 76 out["commands"] = Calls.List() 77 return out, nil 78 } 79 80 func init() { 81 Add(Call{ 82 Path: "core/pid", 83 Fn: rcPid, 84 Title: "Return PID of current process", 85 Help: ` 86 This returns PID of current process. 87 Useful for stopping rclone process.`, 88 }) 89 } 90 91 // Return PID of current process 92 func rcPid(ctx context.Context, in Params) (out Params, err error) { 93 out = make(Params) 94 out["pid"] = os.Getpid() 95 return out, nil 96 } 97 98 func init() { 99 Add(Call{ 100 Path: "core/memstats", 101 Fn: rcMemStats, 102 Title: "Returns the memory statistics", 103 Help: ` 104 This returns the memory statistics of the running program. What the values mean 105 are explained in the go docs: https://golang.org/pkg/runtime/#MemStats 106 107 The most interesting values for most people are: 108 109 * HeapAlloc: This is the amount of memory rclone is actually using 110 * HeapSys: This is the amount of memory rclone has obtained from the OS 111 * Sys: this is the total amount of memory requested from the OS 112 * It is virtual memory so may include unused memory 113 `, 114 }) 115 } 116 117 // Return the memory statistics 118 func rcMemStats(ctx context.Context, in Params) (out Params, err error) { 119 out = make(Params) 120 var m runtime.MemStats 121 runtime.ReadMemStats(&m) 122 out["Alloc"] = m.Alloc 123 out["TotalAlloc"] = m.TotalAlloc 124 out["Sys"] = m.Sys 125 out["Mallocs"] = m.Mallocs 126 out["Frees"] = m.Frees 127 out["HeapAlloc"] = m.HeapAlloc 128 out["HeapSys"] = m.HeapSys 129 out["HeapIdle"] = m.HeapIdle 130 out["HeapInuse"] = m.HeapInuse 131 out["HeapReleased"] = m.HeapReleased 132 out["HeapObjects"] = m.HeapObjects 133 out["StackInuse"] = m.StackInuse 134 out["StackSys"] = m.StackSys 135 out["MSpanInuse"] = m.MSpanInuse 136 out["MSpanSys"] = m.MSpanSys 137 out["MCacheInuse"] = m.MCacheInuse 138 out["MCacheSys"] = m.MCacheSys 139 out["BuckHashSys"] = m.BuckHashSys 140 out["GCSys"] = m.GCSys 141 out["OtherSys"] = m.OtherSys 142 return out, nil 143 } 144 145 func init() { 146 Add(Call{ 147 Path: "core/gc", 148 Fn: rcGc, 149 Title: "Runs a garbage collection.", 150 Help: ` 151 This tells the go runtime to do a garbage collection run. It isn't 152 necessary to call this normally, but it can be useful for debugging 153 memory problems. 154 `, 155 }) 156 } 157 158 // Do a garbage collection run 159 func rcGc(ctx context.Context, in Params) (out Params, err error) { 160 runtime.GC() 161 return nil, nil 162 } 163 164 func init() { 165 Add(Call{ 166 Path: "core/version", 167 Fn: rcVersion, 168 Title: "Shows the current version of rclone and the go runtime.", 169 Help: ` 170 This shows the current version of go and the go runtime 171 172 - version - rclone version, eg "v1.44" 173 - decomposed - version number as [major, minor, patch, subpatch] 174 - note patch and subpatch will be 999 for a git compiled version 175 - isGit - boolean - true if this was compiled from the git version 176 - os - OS in use as according to Go 177 - arch - cpu architecture in use according to Go 178 - goVersion - version of Go runtime in use 179 180 `, 181 }) 182 } 183 184 // Return version info 185 func rcVersion(ctx context.Context, in Params) (out Params, err error) { 186 decomposed, err := version.New(fs.Version) 187 if err != nil { 188 return nil, err 189 } 190 out = Params{ 191 "version": fs.Version, 192 "decomposed": decomposed, 193 "isGit": decomposed.IsGit(), 194 "os": runtime.GOOS, 195 "arch": runtime.GOARCH, 196 "goVersion": runtime.Version(), 197 } 198 return out, nil 199 } 200 201 func init() { 202 Add(Call{ 203 Path: "core/obscure", 204 Fn: rcObscure, 205 Title: "Obscures a string passed in.", 206 Help: ` 207 Pass a clear string and rclone will obscure it for the config file: 208 - clear - string 209 210 Returns 211 - obscured - string 212 `, 213 }) 214 } 215 216 // Return obscured string 217 func rcObscure(ctx context.Context, in Params) (out Params, err error) { 218 clear, err := in.GetString("clear") 219 if err != nil { 220 return nil, err 221 } 222 obscured, err := obscure.Obscure(clear) 223 if err != nil { 224 return nil, err 225 } 226 out = Params{ 227 "obscured": obscured, 228 } 229 return out, nil 230 } 231 232 func init() { 233 Add(Call{ 234 Path: "core/quit", 235 Fn: rcQuit, 236 Title: "Terminates the app.", 237 Help: ` 238 (optional) Pass an exit code to be used for terminating the app: 239 - exitCode - int 240 `, 241 }) 242 } 243 244 // Terminates app 245 func rcQuit(ctx context.Context, in Params) (out Params, err error) { 246 code, err := in.GetInt64("exitCode") 247 248 if IsErrParamInvalid(err) { 249 return nil, err 250 } 251 if IsErrParamNotFound(err) { 252 code = 0 253 } 254 exitCode := int(code) 255 256 go func(exitCode int) { 257 time.Sleep(time.Millisecond * 1500) 258 atexit.Run() 259 os.Exit(exitCode) 260 }(exitCode) 261 262 return nil, nil 263 } 264 265 func init() { 266 Add(Call{ 267 Path: "debug/set-mutex-profile-fraction", 268 Fn: rcSetMutexProfileFraction, 269 Title: "Set runtime.SetMutexProfileFraction for mutex profiling.", 270 Help: ` 271 SetMutexProfileFraction controls the fraction of mutex contention 272 events that are reported in the mutex profile. On average 1/rate 273 events are reported. The previous rate is returned. 274 275 To turn off profiling entirely, pass rate 0. To just read the current 276 rate, pass rate < 0. (For n>1 the details of sampling may change.) 277 278 Once this is set you can look use this to profile the mutex contention: 279 280 go tool pprof http://localhost:5572/debug/pprof/mutex 281 282 Parameters 283 284 - rate - int 285 286 Results 287 288 - previousRate - int 289 `, 290 }) 291 } 292 293 // Terminates app 294 func rcSetMutexProfileFraction(ctx context.Context, in Params) (out Params, err error) { 295 rate, err := in.GetInt64("rate") 296 if err != nil { 297 return nil, err 298 } 299 previousRate := runtime.SetMutexProfileFraction(int(rate)) 300 out = make(Params) 301 out["previousRate"] = previousRate 302 return out, nil 303 } 304 305 func init() { 306 Add(Call{ 307 Path: "debug/set-block-profile-rate", 308 Fn: rcSetBlockProfileRate, 309 Title: "Set runtime.SetBlockProfileRate for blocking profiling.", 310 Help: ` 311 SetBlockProfileRate controls the fraction of goroutine blocking events 312 that are reported in the blocking profile. The profiler aims to sample 313 an average of one blocking event per rate nanoseconds spent blocked. 314 315 To include every blocking event in the profile, pass rate = 1. To turn 316 off profiling entirely, pass rate <= 0. 317 318 After calling this you can use this to see the blocking profile: 319 320 go tool pprof http://localhost:5572/debug/pprof/block 321 322 Parameters 323 324 - rate - int 325 `, 326 }) 327 } 328 329 // Terminates app 330 func rcSetBlockProfileRate(ctx context.Context, in Params) (out Params, err error) { 331 rate, err := in.GetInt64("rate") 332 if err != nil { 333 return nil, err 334 } 335 runtime.SetBlockProfileRate(int(rate)) 336 return nil, nil 337 }