SoFunction
Updated on 2025-03-04

Detailed explanation of how to use golang in the complete scenario of executing Linux shell commands

1. Execute the command and get the output result

CombinedOutput()

Executing the program returns standard output and standard error

func main() {
    cmd := ("ls", "-lah")
    out, err := ()
    if err != nil {
        ("() failed with %s\n", err)
    }
    ("combined out:\n%s\n", string(out))
}

Output()

Execute the program returns standard output

func main() {
    out, err := ("date").Output()
    if err != nil {
        (err)
    }
    ("The date is %s\n", out)
}

2. Process stdout and stderr separately

Use buffer to accept output

func main() {
    cmd := ("ls", "-lah")
    var stdin, stdout, stderr 
     = &stdin
     = &stdout
     = &stderr
    err := ()
    if err != nil {
        ("() failed with %s\n", err)
    }
    outStr, errStr := string(()), string(())
    ("out:\n%s\nerr:\n%s\n", outStr, errStr)
}

Print directly to the screen

func main() {
    cmd := ("ls", "-lah")
     = 
     = 
    err := ()
    if err != nil {
        ("() failed with %s\n", err)
    }
}

3. Execute commands asynchronously

() Blocking and waiting for the command execution to end
() will not wait for the command to complete

package main

import (
    "bytes"
    "fmt"
    "io"
    "log"
    "os"
    "os/exec"
)

func main() {
    var stdoutBuf, stderrBuf 
    cmd := ("bash", "-c", "for i in 1 2 3 4;do echo $i;sleep 2;done")
    stdoutIn, _ := ()
    stderrIn, _ := ()
    var errStdout, errStderr error
    stdout := (, &stdoutBuf)
    stderr := (, &stderrBuf)
    err := ()
    if err != nil {
        ("() failed with '%s'\n", err)
    }
    go func() {
        _, errStdout = (stdout, stdoutIn)
    }()
    go func() {
        _, errStderr = (stderr, stderrIn)
    }()
    err = ()
    if err != nil {
        ("() failed with %s\n", err)
    }
    if errStdout != nil || errStderr != nil {
        ("failed to capture stdout or stderr\n")
    }
    outStr, errStr := string(()), string(())
    ("\nout:\n%s\nerr:\n%s\n", outStr, errStr)
}

4. With environment variables when executing

func main() {
    cmd := ("bash", "-c", "programToExecute")
    additionalEnv := "programToExecute=ls"
    newEnv := append((), additionalEnv)
     = newEnv
    out, err := ()
    if err != nil {
        ("() failed with %s\n", err)
    }
    ("%s", out)
}

5. Pre-check whether the command exists

func checkLsExists() {
    path, err := ("ls")
    if err != nil {
        ("didn't find 'ls' executable\n")
    } else {
        ("'ls' executable is in '%s'\n", path)
    }
}

6. Two commands are executed in turn, and the pipeline communication is

func main() {
    c1 := ("ls")
    c2 := ("wc", "-l")
    r, w := () 
     = w
     = r
    var b2 
     = &b2
    ()
    ()
    ()
    ()
    ()
    (, &b2)
}

or

func main() {
    c1 := ("ls")
    c2 := ("wc", "-l")
    , _ = ()
     = 
    _ = ()
    _ = ()
    _ = ()
}

Anyway, this is not possible

func main() {
    c := ("ls", "|", "wc", "-l")
     = 
    _ = ()
}

You can use bash -c

func main() {
    cmd := "cat /proc/cpuinfo | egrep '^model name' | uniq | awk '{print substr($0, index($0,$4))}'"
    out, err := ("bash", "-c", cmd).Output()
    if err != nil {
        ("Failed to execute command: %s", cmd)
    }
    (string(out))
}

7. Read the output content by line

func main() {
    cmd := ("ls", "-la")
    stdout, _ := ()
    ()
    reader := (stdout)
    for {
        line, err := ('\n')
        line = (line)
        if err != nil ||  == err {
            break
        }
        (line)
    }
    ()
}

8. Obtain exit code

func RunCommand(name string, args ...string) (stdout string, stderr string, exitCode int) {
    ("run command:", name, args)
    var outbuf, errbuf 
    cmd := (name, args...)
     = &outbuf
     = &errbuf

    err := ()
    stdout = ()
    stderr = ()

    if err != nil {
        // try to get the exit code
        if exitError, ok := err.(*); ok {
            ws := ().()
            exitCode = ()
        } else {
            // This will happen (in OSX) if `name` is not available in $PATH,
            // in this situation, exit code could not be get, and stderr will be
            // empty string very likely, so we use the default fail code, and format err
            // to string and set to stderr
            ("Could not get exit code for failed program: %v, %v", name, args)
            exitCode = defaultFailedCode
            if stderr == "" {
                stderr = ()
            }
        }
    } else {
        // success, exitCode should be 0 if go is ok
        ws := ().()
        exitCode = ()
    }
    ("command result, stdout: %v, stderr: %v, exitCode: %v", stdout, stderr, exitCode)
    return
}

Reference link:

/backend_development/

This is the article about how to use golang in the complete scenario of executing Linux shell commands. For more related content on the execution of the Linux shell, please search for my previous articles or continue browsing the related articles below. I hope everyone will support me in the future!