Go 标准库之 os

https://pkg.go.dev/os

1、介绍

os包中提供了操作系统函数的接口,是一个比较重要的包。它的作用主要是在服务器上进行系统的基本操作,如文件操作、目录操作、执行命令、信号与中断、进程、系统状态等等。下面分模块归纳一些常用函数。

2、系统信息

2.1、函数列表

函数 功能
Hostname() 获取当前主机名
Getpid() 返回调用者所在进程的进程ID
Getppid() 返回调用者所在进程的父进程的进程ID
Exit() 让程序以状态码code退出。状态码0表示成功,非0表示出错。
code取值范围: [0,125]

2.2、代码示例

1
2
3
4
5
6
7
8
9
10
// 系统相关
func TestSystemInfo(t *testing.T) {
hostname, _ := os.Hostname()
// 主机名: huideMacBook-Pro.local
fmt.Printf("主机名:%v \n", hostname)
// 调用者所在进程的进程ID: 42862
fmt.Printf("调用者所在进程的进程ID: %v \n", os.Getpid())
// 调用者所在进程的进程的父进程ID: 42861
fmt.Printf("调用者所在进程的进程的父进程ID: %v \n", os.Getppid())
}

3、环境变量

3.1、函数列表

函数 功能
Environ() 获取所有环境变量
Setenv(key, value string) 设置环境变量
Getenv(key string) 获取环境变量
Clearenv() 清空所有环境变量

3.2、代码示例

1
2
3
4
5
6
7
8
9
10
11
12
// 环境变量相关
func TestEnv(t *testing.T) {
// 所有环境变量
fmt.Printf("所有环境变量:%+v \n", os.Environ())
// 设置环境变量
_ = os.Setenv("my-name", "张三")
// 获取环境变量
fmt.Printf("获取环境变量: %v \n", os.Getenv("my-name"))
// 清空所有环境变量
os.Clearenv()
fmt.Printf("清空环境变量后:%+v \n", os.Environ())
}

**输出: **

1
2
3
4
5
所有环境变量:[PATH=/usr/bin:/bin:/usr/sbin:/sbin:/usr/local/go/bin __CFBundleIdentifier=com.jetbrains.goland SHELL=/bin/zsh SECURITYSESSIONID=186a6 GOPATH=/Users/hui/go TERM=xterm-256color USER=hui GOROOT=/usr/local/go TMPDIR=/var/folders/8f/vnx2y1h57nzbd2p4vtcl6hv80000gn/T/ LaunchInstanceID=D9F74359-45B7-45F3-B74C-67CEA4DB8D9D COMMAND_MODE=unix2003 GO111MODULE=on SSH_AUTH_SOCK=/private/tmp/com.apple.launchd.5K5WgUh7Hh/Listeners GOPROXY=https://goproxy.cn,direct XPC_FLAGS=0x0 __CF_USER_TEXT_ENCODING=0x1F5:0x19:0x34 LOGNAME=hui XPC_SERVICE_NAME=application.com.jetbrains.goland.15834002.15834933 PWD=/Users/hui/Project/Go/gin-learn/test HOME=/Users/hui GOARCH=amd64 GOBIN=/Users/hui/Project/Go/gopath/bin GOCACHE=/Users/hui/Library/Caches/go-build GOENV=/Users/hui/Library/Application Support/go/env GOHOSTARCH=amd64 GOHOSTOS=darwin GOMODCACHE=/Users/hui/go/pkg/mod GOOS=darwin GOSUMDB=sum.golang.org GOTOOLDIR=/usr/local/go/pkg/tool/darwin_amd64 GCCGO=gccgo AR=ar CC=clang CXX=clang++ CGO_ENABLED=1] 
获取环境变量: 张三
清空环境变量后:[]
--- PASS: TestEnv (0.00s)
PASS

4、文件相关

请看另一片博文

5、进程相关

5.1、方法列表

函数名 功能
os.StartProcess(..) (*Process, error) 根据提供的参数创建一个新进程
p.Signal(sig Signal) 向进程发送一个信号
p.Wait() 阻塞到进程退出,返回类型*os.ProcessState
ps.Pid() 返回一个已退出进程的id
ps.Exited() 报告进程是否已退出
ps.Success() 报告进程是否成功退出,在Unix中状态码0代表退出。
ps.SystemTime() 退出进程及子进程耗费的系统CPU时间
ps.UserTime() 退出进程及子进程耗费的用户CPU时间
ps.String() 退出进程的状态信息

上表中p代表: *os.Process,  ps代表: *os.ProcessState

5.2、代码示例

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
func TestCreateProcess(t *testing.T) {
// 创建一个新进程执行; ls /
args := []string{"/"}
process, err := os.StartProcess("/bin/ls", args, &os.ProcAttr{})
if err != nil {
t.Error("创建新进程失败: " + err.Error())
return
}
fmt.Printf("当前新线程信息: %+v \n", process)

// 2秒后向进程发送信号
time.AfterFunc(2 * time.Second, func() {
fmt.Println("发送进程退出信号...")
_ = process.Signal(os.Kill)
})
// 手动阻塞看是否执行:发送信号
time.Sleep(3 * time.Second)

// 等待进程退出,返回ProcessState类型
processState, _ := process.Wait()
// 返回一个已退出进程的id
fmt.Printf("当前进程Id: %v \n", processState.Pid())
// 报告进程是否已退出
fmt.Printf("进程是否已退出: %v \n", processState.Exited())
// 报告进程是否成功退出,如在Unix里以状态码0退出。
fmt.Printf("进程是否成功退出: %v \n", processState.Success())
// 返回已退出进程及其子进程耗费的系统CPU时间。
fmt.Printf("进程及子进程耗费系统CPU时间: %v \n", processState.SystemTime())
// 返回已退出进程及其子进程耗费的用户CPU时间。
fmt.Printf("进程及子进程耗费用户CPU时间: %v \n", processState.UserTime())
fmt.Printf("进程状态: %s \n",processState.String())
}

输出:

1
2
3
4
5
6
7
8
9
10
11
=== RUN   TestCreateProcess
当前新线程信息: &{Pid:46859 handle:0 isdone:0 sigMu:{w:{state:0 sema:0} writerSem:0 readerSem:0 readerCount:0 readerWait:0}}
当前进程Id: 46859
进程是否已退出: true
进程是否成功退出: true
进程及子进程耗费系统CPU时间: 1.563ms
进程及子进程耗费用户CPU时间: 503µs
发送进程退出信号...
进程状态: exit status 0
--- PASS: TestCreateProcess (3.00s)
PASS

6、执行命令

os/exec包执行外部命令。它包装了os.StartProcess函数以便更容易的修正输入和输出,使用管道连接I/O,以及其它的一些优化。

6.1、方法列表

方法 功能
LookPath(file string) (string, error) 在环境变量PATH中搜索可执行文件
(c *Cmd) Run() error 执行c包含的命令,并阻塞直到完成
(c *Cmd) Start() error 执行c包含的命令即刻返回,但不会等待该命令完成。
(c *Cmd) Wait() error 会阻塞直到该命令执行完成,和Start()结合使用
(c *Cmd) Output() ([]byte, error) 执行命令并返回标准输出的切片
(c *Cmd) CombinedOutput() ([]byte, error) 执行命令并返回标准输出和错误输出合并的切片。

6.2、使用示例

1. LookPath

1
2
3
4
5
6
7
8
9
10
11
12
13
14
// 在环境变量PATH中搜索可执行文件
func TestLookPath(t *testing.T) {
path, err := exec.LookPath("go")
if err != nil {
t.Error(err)
}
fmt.Println(path)
}
/** 输出
=== RUN TestLookPath
/usr/local/go/bin/go
--- PASS: TestLookPath (0.00s)
PASS
*/

2.Run

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
// 使用Run()执行命令
func TestRun(t *testing.T) {
// 执行: go version
cmd := exec.Command("sleep", "3s")
// 具体执行
err := cmd.Run()
if err != nil {
t.Errorf("执行失败:%v\n",err)
}
fmt.Printf("cmd.Path: %v \n",cmd.Path)
fmt.Printf("cmd.Args: %v \n",cmd.Args)
}
/** 输出
=== RUN TestRun
cmd.Path: /bin/sleep
cmd.Args: [sleep 3s]
--- PASS: TestRun (3.01s)
PASS
*/

3. Start

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
// 使用Start执行命令
func TestStart(t *testing.T) {
// 执行: go version
cmd := exec.Command("sleep", "3s")
// Start开始执行c包含的命令,但并不会等待该命令完成即返回
err := cmd.Start()
if err != nil {
t.Errorf("执行失败:%v\n",err)
}
//Wait会阻塞直到该命令执行完成
err = cmd.Wait()
fmt.Printf("执行完成: %v \n",err)
fmt.Printf("cmd.Path: %v \n",cmd.Path)
fmt.Printf("cmd.Args: %v \n",cmd.Args)
}

/** 输出
=== RUN TestStart
执行完成: <nil>
cmd.Path: /bin/sleep
cmd.Args: [sleep 3s]
--- PASS: TestStart (3.00s)
PASS
*/

4.Output

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
// 执行命令并获取输出结果
func TestOutput(t *testing.T) {
// 执行: go version
output, _ := exec.Command("go", "version").Output()
fmt.Printf("结果: %s \n",output)
// 执行: du -sh .
output2, _ := exec.Command("du", "-sh",".").Output()
fmt.Printf("结果: %s \n",output2)
}

/** 输出
=== RUN TestOutput
结果: go version go1.15.5 darwin/amd64

结果: 36K .

--- PASS: TestOutput (0.02s)
PASS
*/

5.CombinedOutput

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
// 执行命令并返回标准输出和错误输出合并的切片
func TestCombinedOutput(t *testing.T) {
// 执行: go version-1 故意写错
output, _ := exec.Command("go", "version-1").CombinedOutput()
fmt.Printf("结果: %s \n",output)
}

/** 输出
=== RUN TestCombinedOutput
结果: go version-1: unknown command
Run 'go help' for usage.

--- PASS: TestCombinedOutput (0.01s)
PASS
*/

7、进程相关

7.1、方法列表

1
2
3
4
5
6
7
8
func Exit(code int)     // 让当前程序以给出的状态码(code)退出。一般来说,状态码0表示成功,非0表示出错。程序会立刻终止,defer的函数不会被执行。
func Getuid() int // 获取调用者的用户id
func Geteuid() int // 获取调用者的有效用户id
func Getgid() int // 获取调用者的组id
func Getegid() int // 获取调用者的有效组id
func Getgroups() ([]int, error) // 获取调用者所在的所有组的组id
func Getpid() int // 获取调用者所在进程的进程id
func Getppid() int // 获取调用者所在进程的父进程的进程id

7.2、使用示例

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
func osInfo() {
// 获得当前正在运行的进程id
fmt.Println("---------")
fmt.Printf("os.Getpid(): %v\n", os.Getpid())
// 父id
fmt.Printf("os.Getppid(): %v\n", os.Getppid())

// 设置新进程的属性
attr := &os.ProcAttr{
// files指定新进程继承的活动文件对象
// 前三个分别为,标准输入、标准输出、标准错误输出
Files: []*os.File{os.Stdin, os.Stdout, os.Stderr},
// 新进程的环境变量
Env: os.Environ(),
}

// 开始一个新进程
p, err := os.StartProcess("c:\\windows\\system32\\notepad.exe", []string{"c:\\windows\\system32\\notepad.exe", "d:\\test.txt"}, attr)
if err != nil {
fmt.Println(err)
}
fmt.Println(p)
fmt.Println("进程ID:", p.Pid)

// 通过进程ID查找进程
p2, _ := os.FindProcess(p.Pid)
fmt.Println(p2)

// 等待10秒,执行函数
time.AfterFunc(time.Second*10, func() {
// 向p进程发出退出信号
p.Signal(os.Kill)
})

// 等待进程p的退出,返回进程状态
ps, _ := p.Wait()
fmt.Println(ps.String())
}

8、环境相关

8.1、方法列表

1
2
3
4
func Hostname() (name string, err error)    // 获取主机名
func Getenv(key string) string // 获取某个环境变
func Setenv(key, value string) error // 设置一个环境变量,失败返回错误,经测试当前设置的环境变量只在 当前进程有效(当前进程衍生的所有的go程都可以拿到,子go程与父go程的环境变量可以互相获取);进程退出消失
func Clearenv() // 删除当前程序已有的所有环境变量。不会影响当前电脑系统的环境变量,这些环境变量都是对当前go程序而言的

8.2、使用示例

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22

func osEnv() {
// 获得所有环境变量
s := os.Environ()
fmt.Printf("s: %v\n", s)
// 获得某个环境变量
s2 := os.Getenv("GOPATH")
fmt.Printf("s2: %v\n", s2)
// 设置环境变量
os.Setenv("env1", "env1")
s2 = os.Getenv("aaa")
fmt.Printf("s2: %v\n", s2)
fmt.Println("--------------")

// 查找
s3, b := os.LookupEnv("env1")
fmt.Printf("b: %v\n", b)
fmt.Printf("s3: %v\n", s3)

// 清空环境变量
// os.Clearenv()
}

Go 标准库之 os
https://flepeng.github.io/021-Go-32-Go-标准库-Go-标准库之-os/
作者
Lepeng
发布于
2024年12月3日
许可协议