命令记不住

登陆

标准库 os

标准库OS包

1.启动外部命令和程序

标准库的os包是一个比较重要的包,主要用在服务器上进行系统的基本操作,如文件操作、目录操作、执行命令、信号与中断、进程、系统状态等等,在os包下,有exec、signal、user三个子包

在os包中,有很多非常实用的功能,例如可以通过变量Args来获取命令参数,os.Args返回一个字符串组

fmt.Println(os.Args)

在os包中,相关函数的名字和作用有明显的UNIX风格,例如:

//chdir将当前工作目录更改为dir目录
func Chdir(dir string)error

//获取当前目录
func Getwd()(dir string,err error)

//更改文件的权限
func Chmod(name string,mode FileMode)error

//更改文件拥有者owner
func Chown(name string,uid,gid int)error

func Chtimes(name string,atime time.Time,mtime time.Time)error

//清除所有环境变量
func Clearenv()

//返回所有环境变量
func Environ()[]string

//系统退出,并返回code
//其中0表示执行成功并退出,非0表示错误并退出
func Exit(code int)

在os包中,有关文件的处理也有很多方法,如:

//Create采用模式0666创建一个名为name的文件
//如果文件已存在会截断它(为空文件)
func Create(name string)(file *File,err error)

//Open打开一个文件用于读取
func Open(name string)(file *File,err  error)

//Stat返回描述文件f的FileInfo类型值
func (f *File)Stat()(fi FileInfo,err error)

//Readdir读取目录f的内容,返回一个有n个成员的[]FileInfo
func (f *File)Readdir(n int)(fi []FileInfo,err error)

//Read方法从f中读取最多len(b)字节数据并写入b
func (f *File)Read(b []byte)(n int,err error)

//向文件中写入字符串
func (f *File) WriteString(s string)(ret int,err error)

//Sync递交文件的当前内容进行稳定的存储
func (f *File)Sync()(err error)

//Close关闭文件f

func (f *File)Close() error

在Go语言中对文件I/O的操作有多种方法

在os包中有一个StartProcess函数可以调用或启动外部系统命令和二进制可执行文件,它的第一个参数是要运行的进程,第二个参数用来传递选项或参数,第三个参数是含有系统环境基本信息的结构体

这个函数返回被启动进程的id(pid),或者在启动失败时返回错误,例如:


2.信号处理os/signal

一个运行良好的程序在推出(正常退出或者强制退出,如Ctrl+C,kill等)时会执行一段清理代码,将收尾工作做完后再真正退出。一般采用系统信号来通知系统退出,如kill pid。在程序中针对一些系统信号设置了处理函数,当收到信号后,会执行相关清理程序或通知各个子进程做自清理

Go的系统信号处理主要涉及os包、os.signal包以及syscall包。其中最主要的函数是signal包中的Notify函数

package main

import (
    "fmt"
    "os"
)

func main() {
    /* Linux: */
    env := os.Environ()
    procAttr := &os.ProcAttr{
        Env: env,
        Files: []*os.File{
            os.Stdin,
            os.Stdout,
            os.Stderr,
        },
    }
    // Linux文件列表命令
    Pid, err := os.StartProcess("/bin/ls", []string{"ls", "-l"}, procAttr)
    if err != nil {
        fmt.Printf("Error %v starting process!", err) //
        os.Exit(1)
    }
    fmt.Printf("The process id is %v", Pid)
}

该函数会将进程受到的系统信号转发给通道,如果没有传入sig参数,那么Notify会将系统收到的所有信号转发给通道。

Notify会根据传入的os.Signal,监听对应的信号,Notify()方法会将接收到的对应os.Signal向一个通道中 发送

下面的代码以syscall.SIGUSRR2信号为例,说明具体实现方法

package main

import (
    "fmt"
    "os"
    "os/signal"
    "syscall"
)

var ss = make(chan int)

func main() {
    go signalListen()
    select {
    case <-ss:
        break
    }
}

func signalListen() {
    c := make(chan os.Signal)
    signal.Notify(c, syscall.SIGINT, syscall.SIGQUIT)
    for {
        s := <-c
        //收到信号后的处理,这里只是输出信号内容,可以做一些更有意思的事
        fmt.Println("get signal:", s)
        ss <- 9
        break
    }
}

这里可以接收Ctrl+c中断信号,在主程序中的通道会阻塞直到协程发来中断信号,可以在收到中断信号后处理,例如关闭网络连接、保存状态信息等,然后优雅退出。

3.os.Args

g

g

g

g

4.os.Stdin

g

g

g

g

5.os.OPen

func main(){
	counts :=make(map[string]int)

	files :=os.Args[1:]
	if len(files) == 0{
		countLines(os.Stdin,counts)
	}else{
		for _,arg := range files{
			f,err := os.Open(arg)
			if err !=nil{
				fmt.Fprintf(os.Stderr,"dup2: %v\n",err)
			}
			countLines(f,counts)
			f.Close()
		}
	}

	for line,n:=range counts{
		if n>1 {
			fmt.Printf("%d\t%s\n",n,line)
		}
	}
}

func countLines(f *os.File,counts map[string]int){
	input :=bufio.NewScanner(f)
	for input.Scan(){
		counts[input.Text()]++
	/*
		if input.Text() == "EOF"{
			break
		}
	 */
	}
}

g

gg

6.os.MkdirAll

go

7.os.RemoveAll

go

8.os.Create

go

func fetch(url string) (filename string, n int64, err error) {
	resp, err := http.Get(url)
	if err != nil {
		return "", 0, err
	}
	defer resp.Body.Close()

	local := path.Base(resp.Request.URL.Path)
	if local == "/" {
		local = "index.html"
	}
	f, err := os.Create(local)
	if err != nil {
		return "", 0, err
	}
	n, err = io.Copy(f, resp.Body)
	// Close file, but prefer error from Copy, if any.
	if closeErr := f.Close(); err == nil {
		err = closeErr
	}
	return local, n, err
}

//!-

func main() {
	for _, url := range os.Args[1:] {
		local, n, err := fetch(url)
		if err != nil {
			fmt.Fprintf(os.Stderr, "fetch %s: %v\n", url, err)
			continue
		}
		fmt.Fprintf(os.Stderr, "%s => %s (%d bytes).\n", url, local, n)
	}
}

go