Involved Source Files
Package exec runs external commands. It wraps os.StartProcess to make it
easier to remap stdin and stdout, connect I/O with pipes, and do other
adjustments.
Unlike the "system" library call from C and other languages, the
os/exec package intentionally does not invoke the system shell and
does not expand any glob patterns or handle other expansions,
pipelines, or redirections typically done by shells. The package
behaves more like C's "exec" family of functions. To expand glob
patterns, either call the shell directly, taking care to escape any
dangerous input, or use the path/filepath package's Glob function.
To expand environment variables, use package os's ExpandEnv.
Note that the examples in this package assume a Unix system.
They may not run on Windows, and they do not run in the Go Playground
used by golang.org and godoc.org.
exec_unix.golp_unix.go
Code Examples
package main
import (
"fmt"
"log"
"os/exec"
)
func main() {
cmd := exec.Command("sh", "-c", "echo stdout; echo 1>&2 stderr")
stdoutStderr, err := cmd.CombinedOutput()
if err != nil {
log.Fatal(err)
}
fmt.Printf("%s\n", stdoutStderr)
}
package main
import (
"fmt"
"log"
"os/exec"
)
func main() {
out, err := exec.Command("date").Output()
if err != nil {
log.Fatal(err)
}
fmt.Printf("The date is %s\n", out)
}
package main
import (
"log"
"os/exec"
)
func main() {
cmd := exec.Command("sleep", "1")
log.Printf("Running command and waiting for it to finish...")
err := cmd.Run()
log.Printf("Command finished with error: %v", err)
}
package main
import (
"log"
"os/exec"
)
func main() {
cmd := exec.Command("sleep", "5")
err := cmd.Start()
if err != nil {
log.Fatal(err)
}
log.Printf("Waiting for command to finish...")
err = cmd.Wait()
log.Printf("Command finished with error: %v", err)
}
package main
import (
"fmt"
"io"
"log"
"os/exec"
)
func main() {
cmd := exec.Command("sh", "-c", "echo stdout; echo 1>&2 stderr")
stderr, err := cmd.StderrPipe()
if err != nil {
log.Fatal(err)
}
if err := cmd.Start(); err != nil {
log.Fatal(err)
}
slurp, _ := io.ReadAll(stderr)
fmt.Printf("%s\n", slurp)
if err := cmd.Wait(); err != nil {
log.Fatal(err)
}
}
package main
import (
"fmt"
"io"
"log"
"os/exec"
)
func main() {
cmd := exec.Command("cat")
stdin, err := cmd.StdinPipe()
if err != nil {
log.Fatal(err)
}
go func() {
defer stdin.Close()
io.WriteString(stdin, "values written to stdin are passed to cmd's standard input")
}()
out, err := cmd.CombinedOutput()
if err != nil {
log.Fatal(err)
}
fmt.Printf("%s\n", out)
}
package main
import (
"encoding/json"
"fmt"
"log"
"os/exec"
)
func main() {
cmd := exec.Command("echo", "-n", `{"Name": "Bob", "Age": 32}`)
stdout, err := cmd.StdoutPipe()
if err != nil {
log.Fatal(err)
}
if err := cmd.Start(); err != nil {
log.Fatal(err)
}
var person struct {
Name string
Age int
}
if err := json.NewDecoder(stdout).Decode(&person); err != nil {
log.Fatal(err)
}
if err := cmd.Wait(); err != nil {
log.Fatal(err)
}
fmt.Printf("%s is %d years old\n", person.Name, person.Age)
}
package main
import (
"bytes"
"fmt"
"log"
"os/exec"
"strings"
)
func main() {
cmd := exec.Command("tr", "a-z", "A-Z")
cmd.Stdin = strings.NewReader("some input")
var out bytes.Buffer
cmd.Stdout = &out
err := cmd.Run()
if err != nil {
log.Fatal(err)
}
fmt.Printf("in all caps: %q\n", out.String())
}
package main
import (
"context"
"os/exec"
"time"
)
func main() {
ctx, cancel := context.WithTimeout(context.Background(), 100*time.Millisecond)
defer cancel()
if err := exec.CommandContext(ctx, "sleep", "5").Run(); err != nil {
// This will fail after 100 milliseconds. The 5 second sleep
// will be interrupted.
}
}
package main
import (
"log"
"os"
"os/exec"
)
func main() {
cmd := exec.Command("prog")
cmd.Env = append(os.Environ(),
"FOO=duplicate_value", // ignored
"FOO=actual_value", // this value is used
)
if err := cmd.Run(); err != nil {
log.Fatal(err)
}
}
package main
import (
"fmt"
"log"
"os/exec"
)
func main() {
path, err := exec.LookPath("fortune")
if err != nil {
log.Fatal("installing fortune is in your future")
}
fmt.Printf("fortune is available at %s\n", path)
}
Package-Level Type Names (total 5, in which 3 are exported)
/* sort exporteds by: | */
Cmd represents an external command being prepared or run.
A Cmd cannot be reused after calling its Run, Output or CombinedOutput
methods.
Args holds command line arguments, including the command as Args[0].
If the Args field is empty or nil, Run uses {Path}.
In typical use, both Path and Args are set by calling Command.
Dir specifies the working directory of the command.
If Dir is the empty string, Run runs the command in the
calling process's current directory.
Env specifies the environment of the process.
Each entry is of the form "key=value".
If Env is nil, the new process uses the current process's
environment.
If Env contains duplicate environment keys, only the last
value in the slice for each duplicate key is used.
As a special case on Windows, SYSTEMROOT is always added if
missing and not explicitly set to the empty string.
ExtraFiles specifies additional open files to be inherited by the
new process. It does not include standard input, standard output, or
standard error. If non-nil, entry i becomes file descriptor 3+i.
ExtraFiles is not supported on Windows.
Path is the path of the command to run.
This is the only field that must be set to a non-zero
value. If Path is relative, it is evaluated relative
to Dir.
Process is the underlying process, once started.
ProcessState contains information about an exited process,
available after a call to Wait or Run.
Stderrio.Writer
Stdin specifies the process's standard input.
If Stdin is nil, the process reads from the null device (os.DevNull).
If Stdin is an *os.File, the process's standard input is connected
directly to that file.
Otherwise, during the execution of the command a separate
goroutine reads from Stdin and delivers that data to the command
over a pipe. In this case, Wait does not complete until the goroutine
stops copying, either because it has reached the end of Stdin
(EOF or a read error) or because writing to the pipe returned an error.
Stdout and Stderr specify the process's standard output and error.
If either is nil, Run connects the corresponding file descriptor
to the null device (os.DevNull).
If either is an *os.File, the corresponding output from the process
is connected directly to that file.
Otherwise, during the execution of the command a separate goroutine
reads from the process over a pipe and delivers that data to the
corresponding Writer. In this case, Wait does not complete until the
goroutine reaches EOF or encounters an error.
If Stdout and Stderr are the same writer, and have a type that can
be compared with ==, at most one goroutine at a time will call Write.
SysProcAttr holds optional, operating system-specific attributes.
Run passes it to os.StartProcess as the os.ProcAttr's Sys field.
childFiles[]*os.FilecloseAfterStart[]io.ClosercloseAfterWait[]io.Closer
// nil means none
// one send per goroutine
// when Wait was called
goroutine[]func() error
// LookPath error, if any.
waitDonechan struct{}
CombinedOutput runs the command and returns its combined standard
output and standard error.
Output runs the command and returns its standard output.
Any returned error will usually be of type *ExitError.
If c.Stderr was nil, Output populates ExitError.Stderr.
Run starts the specified command and waits for it to complete.
The returned error is nil if the command runs, has no problems
copying stdin, stdout, and stderr, and exits with a zero exit
status.
If the command starts but does not complete successfully, the error is of
type *ExitError. Other error types may be returned for other situations.
If the calling goroutine has locked the operating system thread
with runtime.LockOSThread and modified any inheritable OS-level
thread state (for example, Linux or Plan 9 name spaces), the new
process will inherit the caller's thread state.
Start starts the specified command but does not wait for it to complete.
If Start returns successfully, the c.Process field will be set.
The Wait method will return the exit code and release associated resources
once the command exits.
StderrPipe returns a pipe that will be connected to the command's
standard error when the command starts.
Wait will close the pipe after seeing the command exit, so most callers
need not close the pipe themselves. It is thus incorrect to call Wait
before all reads from the pipe have completed.
For the same reason, it is incorrect to use Run when using StderrPipe.
See the StdoutPipe example for idiomatic usage.
StdinPipe returns a pipe that will be connected to the command's
standard input when the command starts.
The pipe will be closed automatically after Wait sees the command exit.
A caller need only call Close to force the pipe to close sooner.
For example, if the command being run will not exit until standard input
is closed, the caller must close the pipe.
StdoutPipe returns a pipe that will be connected to the command's
standard output when the command starts.
Wait will close the pipe after seeing the command exit, so most callers
need not close the pipe themselves. It is thus incorrect to call Wait
before all reads from the pipe have completed.
For the same reason, it is incorrect to call Run when using StdoutPipe.
See the example for idiomatic usage.
String returns a human-readable description of c.
It is intended only for debugging.
In particular, it is not suitable for use as input to a shell.
The output of String may vary across Go releases.
Wait waits for the command to exit and waits for any copying to
stdin or copying from stdout or stderr to complete.
The command must have been started by Start.
The returned error is nil if the command runs, has no problems
copying stdin, stdout, and stderr, and exits with a zero exit
status.
If the command fails to run or doesn't complete successfully, the
error is of type *ExitError. Other error types may be
returned for I/O problems.
If any of c.Stdin, c.Stdout or c.Stderr are not an *os.File, Wait also waits
for the respective I/O loop copying to or from the process to complete.
Wait releases any resources associated with the Cmd.
(*Cmd) argv() []string(*Cmd) closeDescriptors(closers []io.Closer)(*Cmd) envv() ([]string, error)(*Cmd) stderr() (f *os.File, err error)(*Cmd) stdin() (f *os.File, err error)(*Cmd) stdout() (f *os.File, err error)(*Cmd) writerDescriptor(w io.Writer) (f *os.File, err error)
*Cmd : expvar.Var
*Cmd : fmt.Stringer
*Cmd : context.stringer
*Cmd : github.com/aws/smithy-go/middleware.stringer
*Cmd : runtime.stringer
func Command(name string, arg ...string) *Cmd
func CommandContext(ctx context.Context, name string, arg ...string) *Cmd
func golang.org/x/sys/execabs.Command(name string, arg ...string) *Cmd
func golang.org/x/sys/execabs.CommandContext(ctx context.Context, name string, arg ...string) *Cmd
func internal/execabs.Command(name string, arg ...string) *Cmd
func internal/execabs.CommandContext(ctx context.Context, name string, arg ...string) *Cmd
func golang.org/x/sys/execabs.fixCmd(name string, cmd *Cmd)
func golang.org/x/tools/go/packages.cmdDebugStr(cmd *exec.Cmd) string
func golang.org/x/tools/internal/gocommand.cmdDebugStr(cmd *exec.Cmd) string
func golang.org/x/tools/internal/gocommand.runCmdContext(ctx context.Context, cmd *exec.Cmd) error
func internal/execabs.fixCmd(name string, cmd *Cmd)
Error is returned by LookPath when it fails to classify a file as an
executable.
Err is the underlying error.
Name is the file name for which the error occurred.
(*Error) Error() string(*Error) Unwrap() error
*Error : error
An ExitError reports an unsuccessful exit by a command.
ProcessState*os.ProcessState
Stderr holds a subset of the standard error output from the
Cmd.Output method if standard error was not otherwise being
collected.
If the error output is long, Stderr may contain only a prefix
and suffix of the output, with the middle replaced with
text about the number of omitted bytes.
Stderr is provided for debugging, for inclusion in error messages.
Users with other needs should redirect Cmd.Stderr as needed.
// The process's id.
ProcessState.rusage*syscall.Rusage
// System-dependent status info.
(*ExitError) Error() string
ExitCode returns the exit code of the exited process, or -1
if the process hasn't exited or was terminated by a signal.
Exited reports whether the program has exited.
On Unix systems this reports true if the program exited due to calling exit,
but false if the program terminated due to a signal.
Pid returns the process id of the exited process.
( ExitError) String() string
Success reports whether the program exited successfully,
such as with exit status 0 on Unix.
Sys returns system-dependent exit information about
the process. Convert it to the appropriate underlying
type, such as syscall.WaitStatus on Unix, to access its contents.
SysUsage returns system-dependent resource usage information about
the exited process. Convert it to the appropriate underlying
type, such as *syscall.Rusage on Unix, to access its contents.
(On Unix, *syscall.Rusage matches struct rusage as defined in the
getrusage(2) manual page.)
SystemTime returns the system CPU time of the exited process and its children.
UserTime returns the user CPU time of the exited process and its children.
( ExitError) exited() bool( ExitError) success() bool( ExitError) sys() any( ExitError) sysUsage() any( ExitError) systemTime() time.Duration( ExitError) userTime() time.Duration
*ExitError : error
ExitError : expvar.Var
ExitError : fmt.Stringer
ExitError : gotest.tools/v3/assert/cmp.Result
ExitError : context.stringer
ExitError : github.com/aws/smithy-go/middleware.stringer
ExitError : runtime.stringer
File*os.Fileerrerror
// os specific
// whether file is opened for appending
// nil unless directory being read
File.file.namestring
// whether we set nonblocking mode
File.file.pfdpoll.FD
// whether this is stdout or stderr
oncesync.Once
Chdir changes the current working directory to the file,
which must be a directory.
If there is an error, it will be of type *PathError.
Chmod changes the mode of the file to mode.
If there is an error, it will be of type *PathError.
Chown changes the numeric uid and gid of the named file.
If there is an error, it will be of type *PathError.
On Windows, it always returns the syscall.EWINDOWS error, wrapped
in *PathError.
(*closeOnce) Close() error
Fd returns the integer Unix file descriptor referencing the open file.
If f is closed, the file descriptor becomes invalid.
If f is garbage collected, a finalizer may close the file descriptor,
making it invalid; see runtime.SetFinalizer for more information on when
a finalizer might be run. On Unix systems this will cause the SetDeadline
methods to stop working.
Because file descriptors can be reused, the returned file descriptor may
only be closed through the Close method of f, or by its finalizer during
garbage collection. Otherwise, during garbage collection the finalizer
may close an unrelated file descriptor with the same (reused) number.
As an alternative, see the f.SyscallConn method.
Name returns the name of the file as presented to Open.
Read reads up to len(b) bytes from the File and stores them in b.
It returns the number of bytes read and any error encountered.
At end of file, Read returns 0, io.EOF.
ReadAt reads len(b) bytes from the File starting at byte offset off.
It returns the number of bytes read and the error, if any.
ReadAt always returns a non-nil error when n < len(b).
At end of file, that error is io.EOF.
ReadDir reads the contents of the directory associated with the file f
and returns a slice of DirEntry values in directory order.
Subsequent calls on the same file will yield later DirEntry records in the directory.
If n > 0, ReadDir returns at most n DirEntry records.
In this case, if ReadDir returns an empty slice, it will return an error explaining why.
At the end of a directory, the error is io.EOF.
If n <= 0, ReadDir returns all the DirEntry records remaining in the directory.
When it succeeds, it returns a nil error (not io.EOF).
ReadFrom implements io.ReaderFrom.
Readdir reads the contents of the directory associated with file and
returns a slice of up to n FileInfo values, as would be returned
by Lstat, in directory order. Subsequent calls on the same file will yield
further FileInfos.
If n > 0, Readdir returns at most n FileInfo structures. In this case, if
Readdir returns an empty slice, it will return a non-nil error
explaining why. At the end of a directory, the error is io.EOF.
If n <= 0, Readdir returns all the FileInfo from the directory in
a single slice. In this case, if Readdir succeeds (reads all
the way to the end of the directory), it returns the slice and a
nil error. If it encounters an error before the end of the
directory, Readdir returns the FileInfo read until that point
and a non-nil error.
Most clients are better served by the more efficient ReadDir method.
Readdirnames reads the contents of the directory associated with file
and returns a slice of up to n names of files in the directory,
in directory order. Subsequent calls on the same file will yield
further names.
If n > 0, Readdirnames returns at most n names. In this case, if
Readdirnames returns an empty slice, it will return a non-nil error
explaining why. At the end of a directory, the error is io.EOF.
If n <= 0, Readdirnames returns all the names from the directory in
a single slice. In this case, if Readdirnames succeeds (reads all
the way to the end of the directory), it returns the slice and a
nil error. If it encounters an error before the end of the
directory, Readdirnames returns the names read until that point and
a non-nil error.
Seek sets the offset for the next Read or Write on file to offset, interpreted
according to whence: 0 means relative to the origin of the file, 1 means
relative to the current offset, and 2 means relative to the end.
It returns the new offset and an error, if any.
The behavior of Seek on a file opened with O_APPEND is not specified.
If f is a directory, the behavior of Seek varies by operating
system; you can seek to the beginning of the directory on Unix-like
operating systems, but not on Windows.
SetDeadline sets the read and write deadlines for a File.
It is equivalent to calling both SetReadDeadline and SetWriteDeadline.
Only some kinds of files support setting a deadline. Calls to SetDeadline
for files that do not support deadlines will return ErrNoDeadline.
On most systems ordinary files do not support deadlines, but pipes do.
A deadline is an absolute time after which I/O operations fail with an
error instead of blocking. The deadline applies to all future and pending
I/O, not just the immediately following call to Read or Write.
After a deadline has been exceeded, the connection can be refreshed
by setting a deadline in the future.
If the deadline is exceeded a call to Read or Write or to other I/O
methods will return an error that wraps ErrDeadlineExceeded.
This can be tested using errors.Is(err, os.ErrDeadlineExceeded).
That error implements the Timeout method, and calling the Timeout
method will return true, but there are other possible errors for which
the Timeout will return true even if the deadline has not been exceeded.
An idle timeout can be implemented by repeatedly extending
the deadline after successful Read or Write calls.
A zero value for t means I/O operations will not time out.
SetReadDeadline sets the deadline for future Read calls and any
currently-blocked Read call.
A zero value for t means Read will not time out.
Not all files support setting deadlines; see SetDeadline.
SetWriteDeadline sets the deadline for any future Write calls and any
currently-blocked Write call.
Even if Write times out, it may return n > 0, indicating that
some of the data was successfully written.
A zero value for t means Write will not time out.
Not all files support setting deadlines; see SetDeadline.
Stat returns the FileInfo structure describing file.
If there is an error, it will be of type *PathError.
Sync commits the current contents of the file to stable storage.
Typically, this means flushing the file system's in-memory copy
of recently written data to disk.
SyscallConn returns a raw file.
This implements the syscall.Conn interface.
Truncate changes the size of the file.
It does not change the I/O offset.
If there is an error, it will be of type *PathError.
Write writes len(b) bytes from b to the File.
It returns the number of bytes written and an error, if any.
Write returns a non-nil error when n != len(b).
WriteAt writes len(b) bytes to the File starting at byte offset off.
It returns the number of bytes written and an error, if any.
WriteAt returns a non-nil error when n != len(b).
If file was opened with the O_APPEND flag, WriteAt returns an error.
WriteString is like Write, but writes the contents of string s rather than
a slice of bytes.
checkValid checks whether f is valid for use.
If not, it returns an appropriate error, perhaps incorporating the operation name op.
See docs in file.go:(*File).Chmod.
(*closeOnce) close()( closeOnce) close() error
pread reads len(b) bytes from the File starting at byte offset off.
It returns the number of bytes read and the error, if any.
EOF is signaled by a zero count with err set to nil.
pwrite writes len(b) bytes to the File starting at byte offset off.
It returns the number of bytes written and an error, if any.
read reads up to len(b) bytes from the File.
It returns the number of bytes read and an error, if any.
( closeOnce) readFrom(r io.Reader) (written int64, handled bool, err error)( closeOnce) readdir(n int, mode os.readdirMode) (names []string, dirents []os.DirEntry, infos []os.FileInfo, err error)
seek sets the offset for the next Read or Write on file to offset, interpreted
according to whence: 0 means relative to the origin of the file, 1 means
relative to the current offset, and 2 means relative to the end.
It returns the new offset and an error, if any.
setDeadline sets the read and write deadline.
setReadDeadline sets the read deadline.
setWriteDeadline sets the write deadline.
wrapErr wraps an error that occurred during an operation on an open file.
It passes io.EOF through unchanged, otherwise converts
poll.ErrFileClosing to ErrClosed and wraps the error in a PathError.
write writes len(b) bytes to the File.
It returns the number of bytes written and an error, if any.
*closeOnce : go.uber.org/zap.Sink
closeOnce : go.uber.org/zap/zapcore.WriteSyncer
*closeOnce : io.Closer
*closeOnce : io.ReadCloser
closeOnce : io.Reader
closeOnce : io.ReaderAt
closeOnce : io.ReaderFrom
*closeOnce : io.ReadSeekCloser
closeOnce : io.ReadSeeker
*closeOnce : io.ReadWriteCloser
closeOnce : io.ReadWriter
closeOnce : io.ReadWriteSeeker
closeOnce : io.Seeker
closeOnce : io.StringWriter
*closeOnce : io.WriteCloser
closeOnce : io.Writer
closeOnce : io.WriterAt
closeOnce : io.WriteSeeker
*closeOnce : io/fs.File
*closeOnce : io/fs.ReadDirFile
*closeOnce : mime/multipart.File
*closeOnce : net/http.File
closeOnce : syscall.Conn
closeOnce : golang.org/x/net/http2.stringWriter
closeOnce : net/http.http2stringWriter
prefixSuffixSaver is an io.Writer which retains the first N bytes
and the last N bytes written to it. The Bytes() methods reconstructs
it with a pretty error message.
// max size of prefix or suffix
prefix[]byteskippedint64
// ring buffer once len(suffix) == N
// offset to write into suffix
(*prefixSuffixSaver) Bytes() []byte(*prefixSuffixSaver) Write(p []byte) (n int, err error)
fill appends up to len(p) bytes of p to *dst, such that *dst does not
grow larger than w.N. It returns the un-appended suffix of p.
*prefixSuffixSaver : io.Writer
Package-Level Functions (total 11, in which 3 are exported)
Command returns the Cmd struct to execute the named program with
the given arguments.
It sets only the Path and Args in the returned structure.
If name contains no path separators, Command uses LookPath to
resolve name to a complete path if possible. Otherwise it uses name
directly as Path.
The returned Cmd's Args field is constructed from the command name
followed by the elements of arg, so arg should not include the
command name itself. For example, Command("echo", "hello").
Args[0] is always name, not the possibly resolved Path.
On Windows, processes receive the whole command line as a single string
and do their own parsing. Command combines and quotes Args into a command
line string with an algorithm compatible with applications using
CommandLineToArgvW (which is the most common way). Notable exceptions are
msiexec.exe and cmd.exe (and thus, all batch files), which have a different
unquoting algorithm. In these or other similar cases, you can do the
quoting yourself and provide the full command line in SysProcAttr.CmdLine,
leaving Args empty.
CommandContext is like Command but includes a context.
The provided context is used to kill the process (by calling
os.Process.Kill) if the context becomes done before the command
completes on its own.
LookPath searches for an executable named file in the
directories named by the PATH environment variable.
If file contains a slash, it is tried directly and the PATH is not consulted.
The result may be an absolute path or a path relative to the current directory.
addCriticalEnv adds any critical environment variables that are required
(or at least almost always required) on the operating system.
Currently this is only used for Windows.
dedupEnv returns a copy of env with any duplicates removed, in favor of
later values.
Items not of the normal environment "key=value" form are preserved unchanged.
dedupEnvCase is dedupEnv with a case option for testing.
If caseInsensitive is true, the case of keys is ignored.
interfaceEqual protects against panics from doing equality tests on
two interfaces with non-comparable underlying types.
lookExtensions finds windows executable by its dir and path.
It uses LookPath to try appropriate extensions.
lookExtensions does not search PATH, instead it converts `prog` into `.\prog`.