
标准库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