1/* 2 * Copyright (c) 2022 Huawei Device Co., Ltd. 3 * Licensed under the Apache License, Version 2.0 (the "License"); 4 * you may not use this file except in compliance with the License. 5 * You may obtain a copy of the License at 6 * 7 * http://www.apache.org/licenses/LICENSE-2.0 8 * 9 * Unless required by applicable law or agreed to in writing, software 10 * distributed under the License is distributed on an "AS IS" BASIS, 11 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 * See the License for the specific language governing permissions and 13 * limitations under the License. 14 */ 15 16package utils 17 18import ( 19 "context" 20 "errors" 21 "fmt" 22 "github.com/sirupsen/logrus" 23 "io" 24 "os" 25 "os/exec" 26 "time" 27) 28 29func ExecContext(ctx context.Context, name string, args ...string) error { 30 ctx, fn := context.WithTimeout(ctx, 6*time.Hour) 31 defer fn() 32 if err := execContext(ctx, name, args...); err != nil { 33 if errors.Is(err, context.Canceled) { 34 return err 35 } 36 logrus.Errorf("exec failed: %v, try again...", err) 37 return execContext(ctx, name, args...) 38 } 39 return nil 40} 41 42func execContext(ctx context.Context, name string, args ...string) error { 43 cmdStr := append([]string{name}, args...) 44 logrus.Infof("cmd: %s", cmdStr) 45 cmd := exec.CommandContext(ctx, name, args...) 46 stdout, err := cmd.StdoutPipe() 47 if err != nil { 48 return err 49 } 50 stderr, err := cmd.StderrPipe() 51 if err != nil { 52 return err 53 } 54 if err := cmd.Start(); err != nil { 55 return err 56 } 57 fmt.Printf("[%s] exec %s :\n", time.Now(), cmdStr) 58 go io.Copy(os.Stdout, stdout) 59 go io.Copy(os.Stderr, stderr) 60 return cmd.Wait() 61} 62 63func ExecCombinedOutputContext(ctx context.Context, name string, args ...string) ([]byte, error) { 64 ctx, fn := context.WithTimeout(ctx, 6*time.Hour) 65 defer fn() 66 out, err := execCombinedOutputContext(ctx, name, args...) 67 if err != nil { 68 if errors.Is(err, context.Canceled) { 69 return out, err 70 } 71 logrus.Errorf("exec failed: %v, try again...", err) 72 return execCombinedOutputContext(ctx, name, args...) 73 } 74 return out, nil 75} 76 77func execCombinedOutputContext(ctx context.Context, name string, args ...string) ([]byte, error) { 78 cmdStr := append([]string{name}, args...) 79 logrus.Infof("cmd: %s", cmdStr) 80 out, err := exec.CommandContext(ctx, name, args...).CombinedOutput() 81 fmt.Printf("[%s] exec %s :\n", time.Now(), cmdStr) 82 return out, err 83} 84 85func SleepContext(duration time.Duration, ctx context.Context) { 86 select { 87 case <-time.NewTimer(duration).C: 88 case <-ctx.Done(): 89 } 90} 91