code.gitea.io/gitea@v1.19.3/modules/process/manager_exec.go (about)

     1  // Copyright 2022 The Gitea Authors. All rights reserved.
     2  // SPDX-License-Identifier: MIT
     3  
     4  package process
     5  
     6  import (
     7  	"bytes"
     8  	"context"
     9  	"io"
    10  	"os/exec"
    11  	"time"
    12  )
    13  
    14  // Exec a command and use the default timeout.
    15  func (pm *Manager) Exec(desc, cmdName string, args ...string) (string, string, error) {
    16  	return pm.ExecDir(DefaultContext, -1, "", desc, cmdName, args...)
    17  }
    18  
    19  // ExecTimeout a command and use a specific timeout duration.
    20  func (pm *Manager) ExecTimeout(timeout time.Duration, desc, cmdName string, args ...string) (string, string, error) {
    21  	return pm.ExecDir(DefaultContext, timeout, "", desc, cmdName, args...)
    22  }
    23  
    24  // ExecDir a command and use the default timeout.
    25  func (pm *Manager) ExecDir(ctx context.Context, timeout time.Duration, dir, desc, cmdName string, args ...string) (string, string, error) {
    26  	return pm.ExecDirEnv(ctx, timeout, dir, desc, nil, cmdName, args...)
    27  }
    28  
    29  // ExecDirEnv runs a command in given path and environment variables, and waits for its completion
    30  // up to the given timeout (or DefaultTimeout if -1 is given).
    31  // Returns its complete stdout and stderr
    32  // outputs and an error, if any (including timeout)
    33  func (pm *Manager) ExecDirEnv(ctx context.Context, timeout time.Duration, dir, desc string, env []string, cmdName string, args ...string) (string, string, error) {
    34  	return pm.ExecDirEnvStdIn(ctx, timeout, dir, desc, env, nil, cmdName, args...)
    35  }
    36  
    37  // ExecDirEnvStdIn runs a command in given path and environment variables with provided stdIN, and waits for its completion
    38  // up to the given timeout (or DefaultTimeout if timeout <= 0 is given).
    39  // Returns its complete stdout and stderr
    40  // outputs and an error, if any (including timeout)
    41  func (pm *Manager) ExecDirEnvStdIn(ctx context.Context, timeout time.Duration, dir, desc string, env []string, stdIn io.Reader, cmdName string, args ...string) (string, string, error) {
    42  	if timeout <= 0 {
    43  		timeout = 60 * time.Second
    44  	}
    45  
    46  	stdOut := new(bytes.Buffer)
    47  	stdErr := new(bytes.Buffer)
    48  
    49  	ctx, _, finished := pm.AddContextTimeout(ctx, timeout, desc)
    50  	defer finished()
    51  
    52  	cmd := exec.CommandContext(ctx, cmdName, args...)
    53  	cmd.Dir = dir
    54  	cmd.Env = env
    55  	cmd.Stdout = stdOut
    56  	cmd.Stderr = stdErr
    57  	if stdIn != nil {
    58  		cmd.Stdin = stdIn
    59  	}
    60  	SetSysProcAttribute(cmd)
    61  
    62  	if err := cmd.Start(); err != nil {
    63  		return "", "", err
    64  	}
    65  
    66  	err := cmd.Wait()
    67  	if err != nil {
    68  		err = &Error{
    69  			PID:         GetPID(ctx),
    70  			Description: desc,
    71  			Err:         err,
    72  			CtxErr:      ctx.Err(),
    73  			Stdout:      stdOut.String(),
    74  			Stderr:      stdErr.String(),
    75  		}
    76  	}
    77  
    78  	return stdOut.String(), stdErr.String(), err
    79  }