github.com/vmware/govmomi@v0.37.1/govc/datastore/tail.go (about) 1 /* 2 Copyright (c) 2016 VMware, Inc. All Rights Reserved. 3 4 Licensed under the Apache License, Version 2.0 (the "License"); 5 you may not use this file except in compliance with the License. 6 You may obtain a copy of the License at 7 8 http://www.apache.org/licenses/LICENSE-2.0 9 10 Unless required by applicable law or agreed to in writing, software 11 distributed under the License is distributed on an "AS IS" BASIS, 12 WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 See the License for the specific language governing permissions and 14 limitations under the License. 15 */ 16 17 package datastore 18 19 import ( 20 "context" 21 "flag" 22 "io" 23 "os" 24 "time" 25 26 "github.com/vmware/govmomi/govc/cli" 27 "github.com/vmware/govmomi/govc/flags" 28 ) 29 30 type tail struct { 31 *flags.DatastoreFlag 32 *flags.HostSystemFlag 33 34 count int64 35 lines int 36 follow bool 37 } 38 39 func init() { 40 cli.Register("datastore.tail", &tail{}) 41 } 42 43 func (cmd *tail) Register(ctx context.Context, f *flag.FlagSet) { 44 cmd.DatastoreFlag, ctx = flags.NewDatastoreFlag(ctx) 45 cmd.DatastoreFlag.Register(ctx, f) 46 47 cmd.HostSystemFlag, ctx = flags.NewHostSystemFlag(ctx) 48 cmd.HostSystemFlag.Register(ctx, f) 49 50 f.Int64Var(&cmd.count, "c", -1, "Output the last NUM bytes") 51 f.IntVar(&cmd.lines, "n", 10, "Output the last NUM lines") 52 f.BoolVar(&cmd.follow, "f", false, "Output appended data as the file grows") 53 } 54 55 func (cmd *tail) Description() string { 56 return `Output the last part of datastore files. 57 58 Examples: 59 govc datastore.tail -n 100 vm-name/vmware.log 60 govc datastore.tail -n 0 -f vm-name/vmware.log` 61 } 62 63 func (cmd *tail) Process(ctx context.Context) error { 64 if err := cmd.DatastoreFlag.Process(ctx); err != nil { 65 return err 66 } 67 if err := cmd.HostSystemFlag.Process(ctx); err != nil { 68 return err 69 } 70 return nil 71 } 72 73 func (cmd *tail) Usage() string { 74 return "PATH" 75 } 76 77 func (cmd *tail) Run(ctx context.Context, f *flag.FlagSet) error { 78 if f.NArg() != 1 { 79 return flag.ErrHelp 80 } 81 82 p := cmd.Args(f.Args())[0] 83 84 ds, err := cmd.Datastore() 85 if err != nil { 86 return err 87 } 88 89 h, err := cmd.HostSystemIfSpecified() 90 if err != nil { 91 return err 92 } 93 94 if h != nil { 95 ctx = ds.HostContext(ctx, h) 96 } 97 98 file, err := ds.Open(ctx, p.Path) 99 if err != nil { 100 return err 101 } 102 103 var reader io.ReadCloser = file 104 105 var offset int64 106 107 if cmd.count >= 0 { 108 info, serr := file.Stat() 109 if serr != nil { 110 return serr 111 } 112 113 if info.Size() > cmd.count { 114 offset = info.Size() - cmd.count 115 116 _, err = file.Seek(offset, io.SeekStart) 117 if err != nil { 118 return err 119 } 120 } 121 } else if cmd.lines >= 0 { 122 err = file.Tail(cmd.lines) 123 if err != nil { 124 return err 125 } 126 } 127 128 if cmd.follow { 129 reader = file.Follow(time.Second) 130 } 131 132 _, err = io.Copy(os.Stdout, reader) 133 134 _ = reader.Close() 135 136 return err 137 }