vitess.io/vitess@v0.16.2/go/vt/vttablet/onlineddl/util.go (about)

     1  /*
     2  Copyright 2019 The Vitess Authors.
     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 onlineddl
    18  
    19  import (
    20  	"crypto/rand"
    21  	"crypto/sha256"
    22  	"encoding/hex"
    23  	"fmt"
    24  	"io"
    25  	"os"
    26  	"os/exec"
    27  	"path/filepath"
    28  	"strings"
    29  	"time"
    30  
    31  	"vitess.io/vitess/go/vt/log"
    32  )
    33  
    34  const (
    35  	readableTimeFormat = "20060102150405"
    36  )
    37  
    38  // execCmd searches the PATH for a command and runs it, logging the output.
    39  // If input is not nil, pipe it to the command's stdin.
    40  func execCmd(name string, args, env []string, dir string, input io.Reader, output io.Writer) (cmd *exec.Cmd, err error) {
    41  	cmdPath, err := exec.LookPath(name)
    42  	if err != nil {
    43  		return cmd, err
    44  	}
    45  	log.Infof("execCmd: %v %v %v", name, cmdPath, args)
    46  
    47  	cmd = exec.Command(cmdPath, args...)
    48  	cmd.Env = env
    49  	cmd.Dir = dir
    50  	if input != nil {
    51  		cmd.Stdin = input
    52  	}
    53  	if output != nil {
    54  		cmd.Stdout = output
    55  		cmd.Stderr = output
    56  	}
    57  	err = cmd.Run()
    58  	if err != nil {
    59  		err = fmt.Errorf("failed running command: %v %s; error=%v", name, strings.Join(args, " "), err)
    60  		log.Errorf(err.Error())
    61  	}
    62  	log.Infof("execCmd success: %v", name)
    63  	return cmd, err
    64  }
    65  
    66  // createTempDir creates a temporary directory and returns its name
    67  func createTempDir(hint string) (dirName string, err error) {
    68  	if hint != "" {
    69  		return os.MkdirTemp("", fmt.Sprintf("online-ddl-%s-*", hint))
    70  	}
    71  	return os.MkdirTemp("", "online-ddl-*")
    72  }
    73  
    74  // createTempScript creates an executable file in given directory and with given text as content.
    75  func createTempScript(dirName, fileName, text string) (fullName string, err error) {
    76  	fullName = filepath.Join(dirName, fileName)
    77  	bytes := []byte(text)
    78  	err = os.WriteFile(fullName, bytes, 0755)
    79  	return fullName, err
    80  }
    81  
    82  // RandomHash returns a 64 hex character random string
    83  func RandomHash() string {
    84  	size := 64
    85  	rb := make([]byte, size)
    86  	_, _ = rand.Read(rb)
    87  
    88  	hasher := sha256.New()
    89  	hasher.Write(rb)
    90  	return hex.EncodeToString(hasher.Sum(nil))
    91  }
    92  
    93  // ToReadableTimestamp returns a timestamp, in seconds resolution, that is human readable
    94  // (as opposed to unix timestamp which is just a number)
    95  // Example: for Aug 25 2020, 16:04:25 we return "20200825160425"
    96  func ToReadableTimestamp(t time.Time) string {
    97  	return t.Format(readableTimeFormat)
    98  }
    99  
   100  // ReadableTimestamp returns a timestamp, in seconds resolution, that is human readable
   101  // (as opposed to unix timestamp which is just a number), and which corresponds to the time now.
   102  // Example: for Aug 25 2020, 16:04:25 we return "20200825160425"
   103  func ReadableTimestamp() string {
   104  	return ToReadableTimestamp(time.Now())
   105  }