github.com/vmware/govmomi@v0.37.2/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  }