golang中的shell
api
func (*Cmd) Run
func (c *Cmd) Run() errorRun执行c包含的命令,并阻塞直到完成。
如果命令成功执行,stdin、stdout、stderr的转交没有问题,并且返回状态码为0,方法的返回值为nil;如果命令没有执行或者执行失败,会返回*ExitError类型的错误;否则返回的error可能是表示I/O问题。
func (*Cmd) Start
func (c *Cmd) Start() errorStart开始执行c包含的命令,但并不会等待该命令完成即返回。Wait方法会返回命令的返回状态码并在命令返回后释放相关的资源。
func (*Cmd) Wait
func (c *Cmd) Wait() error
Wait会阻塞直到该命令执行完成,该命令必须是被Start方法开始执行的。如果命令成功执行,stdin、stdout、stderr的转交没有问题,并且返回状态码为0,方法的返回值为nil;如果命令没有执行或者执行失败,会返回*ExitError类型的错误;否则返回的error可能是表示I/O问题。Wait方法会在命令返回后释放相关的资源。
func (*Cmd) Output
func (c *Cmd) Output() ([]byte, error)
执行命令并返回标准输出的切片。
func (*Cmd) StderrPipe
func (c *Cmd) StderrPipe() (io.ReadCloser, error)
StderrPipe方法返回一个在命令Start后与命令标准错误输出关联的管道。Wait方法获知命令结束后会关闭这个管道,一般不需要显式的关闭该管道。但是在从管道读取完全部数据之前调用Wait是错误的;同样使用StderrPipe方法时调用Run函数也是错误的。
阻塞方式(需要执行结果)
主要用于执行shell命令,并且返回shell的标准输出
适用于执行普通非阻塞shell命令,且需要shell标准输出的
//阻塞式的执行外部shell命令的函数,等待执行完毕并返回标准输出
func exec_shell(s string) (string, error){//函数返回一个*Cmd,用于使用给出的参数执行name指定的程序cmd := exec.Command("/bin/bash", "-c", s)//读取io.Writer类型的cmd.Stdout,再通过bytes.Buffer(缓冲byte类型的缓冲器)将byte类型转化为string类型(out.String():这是bytes类型提供的接口)var out bytes.Buffercmd.Stdout = &out//Run执行c包含的命令,并阻塞直到完成。 这里stdout被取出,cmd.Wait()无法正确获取stdin,stdout,stderr,则阻塞在那了err := cmd.Run()checkErr(err)return out.String(), err
}
需要对shell标准输出的逐行实时进行处理的
func execCommand(commandName string, params []string) bool {//函数返回一个*Cmd,用于使用给出的参数执行name指定的程序cmd := exec.Command(commandName, params...)//显示运行的命令fmt.Println(cmd.Args)//StdoutPipe方法返回一个在命令Start后与命令标准输出关联的管道。Wait方法获知命令结束后会关闭这个管道,一般不需要显式的关闭该管道。stdout, err := cmd.StdoutPipe()if err != nil {fmt.Println(err)return false}cmd.Start()//创建一个流来读取管道内内容,这里逻辑是通过一行一行的读取的reader := bufio.NewReader(stdout)//实时循环读取输出流中的一行内容for {line, err2 := reader.ReadString('\n')if err2 != nil || io.EOF == err2 {break}fmt.Println(line)}//阻塞直到该命令执行完成,该命令必须是被Start方法开始执行的cmd.Wait()return true
}
非阻塞方式(不需要执行结果)
通过shell调用自己的程序,并且程序是死循环,此时无法获取返回结果(否则程序会一直阻塞直至调用的 程序结束)
适用于调用自己写的程序(服务器死循环,且不需要返回结果的)
//不需要执行命令的结果与成功与否,执行命令马上就返回
func exec_shell_no_result(command string) {//处理启动参数,通过空格分离 如:setsid /home/luojing/gotest/src/test_main/iwatch/test/while_little &command_name_and_args := strings.FieldsFunc(command, splite_command)//开始执行c包含的命令,但并不会等待该命令完成即返回cmd.Start()if err != nil {fmt.Printf("%v: exec command:%v error:%v\n", get_time(), command, err)}fmt.Printf("Waiting for command:%v to finish...\n", command)//阻塞等待fork出的子进程执行的结果,和cmd.Start()配合使用[不等待回收资源,会导致fork出执行shell命令的子进程变为僵尸进程]err = cmd.Wait()if err != nil {fmt.Printf("%v: Command finished with error: %v\n", get_time(), err)}return
}
/错误处理函数
func checkErr(err error) {if err != nil {fmt.Println(err)panic(err) }
}
ssh
go get golang.org/x/crypto/ssh
ssh执行命令
这个方法需要有一个环境的准备:与目标服务器建立免密码登陆],并且执行程序的用户与执行用户一致
import ("net""log""fmt""bytes""os/exec""strconv"str "strings""golang.org/x/crypto/ssh"
)func runCmd(){var stdOut, stdErr bytes.Buffercmd := exec.Command( "ssh", "username@192.168.1.4", "if [ -d liujx/project ];then echo 0;else echo 1;fi" )cmd.Stdout = &stdOutcmd.Stderr = &stdErrif err := cmd.Run(); err != nil {fmt.Printf( "cmd exec failed: %s : %s", fmt.Sprint( err ), stdErr.String() )}fmt.Print( stdOut.String() )ret, err := strconv.Atoi( str.Replace( stdOut.String(), "\n", "", -1 ) )if err != nil {panic(err)}fmt.Printf("%d, %s\n", ret, stdErr.String() )
}
ssh客户端连接
这种方法可以不用搭建免密码登陆环境,连接时可指定用户和密码的
func SSHConnect( user, password, host string, port int ) ( *ssh.Session, error ) {var (auth []ssh.AuthMethodaddr stringclientConfig *ssh.ClientConfigclient *ssh.Clientsession *ssh.Sessionerr error)// get auth methodauth = make([]ssh.AuthMethod, 0)auth = append(auth, ssh.Password(password))hostKeyCallbk := func(hostname string, remote net.Addr, key ssh.PublicKey) error {return nil}clientConfig = &ssh.ClientConfig{User: user,Auth: auth,// Timeout: 30 * time.Second,HostKeyCallback: hostKeyCallbk, }// connet to sshaddr = fmt.Sprintf( "%s:%d", host, port )if client, err = ssh.Dial( "tcp", addr, clientConfig ); err != nil {return nil, err}// create sessionif session, err = client.NewSession(); err != nil {return nil, err}return session, nil
}func runSsh(){var stdOut, stdErr bytes.Buffersession, err := SSHConnect( "username", "passworld", "192.168.1.4", 22 )if err != nil {log.Fatal(err)}defer session.Close()session.Stdout = &stdOutsession.Stderr = &stdErrsession.Run("if [ -d liujx/project ]; then echo 0; else echo 1; fi")ret, err := strconv.Atoi( str.Replace( stdOut.String(), "\n", "", -1 ) )if err != nil {panic(err)}fmt.Printf("%d, %s\n", ret, stdErr.String() )}
os.Args
func main() {osArg := os.Args //[]string/**o 开始,第一个是文件路径*/for i, data := range osArg {fmt.Println(i, data)}
}
flag命令行参数
每个处理一行
func main() {var recusive boolvar test stringvar level intflag.BoolVar(&recusive, "r", false, "recusive xxx")flag.StringVar(&test, "t","default string", "string option")flag.IntVar(&level, "l", 1, "level of xxx")flag.Parse()fmt.Println(recusive)fmt.Println(test)fmt.Println(level)
}
不传就给默认值
➜ studygo ./studygo
false
default string
1
传递就按照传递的来
➜ studygo ./studygo -r -t hello -l 11
true
hello
11
urfave/cli框架
可以通过-h查看帮助
import ("fmt""github.com/urfave/cli""os"
)func main() {var language stringvar recusive boolapp := cli.NewApp()//指定名字app.Name = "greet"app.Usage = "用法"app.Flags = []cli.Flag{cli.StringFlag{Name: "lang, l",Value: "english",Usage: "select language",Destination: &language,},cli.BoolFlag{Name: "recusive, r",Usage: "recusive for the greeting",Destination: &recusive,},}app.Action = func(c *cli.Context) error {var cmd string//如果用户传过来 >0if c.NArg() > 0 {cmd = c.Args()[0]fmt.Println("cmd is ", cmd)}fmt.Println("recusive is: ", recusive)fmt.Println("language is: ", language)return nil}app.Run(os.Args)
}
启动外部命令和程序
os 包有一个StartProcess
函数可以调用或启动外部系统命令和二进制可执行文件;它的第一个参数是要运行的进程,第二个参数用来传递选项或参数,第三个参数是含有系统环境基本信息的结构体。
这个函数返回被启动进程的 id(pid),或者启动失败返回错误。
exec 包中也有同样功能的更简单的结构体和函数;主要是exec.Command(name string, arg ...string)
和Run()
。首先需要用系统命令或可执行文件的名字创建一个Command
对象,然后用这个对象作为接收者调用Run()
。下面的程序(因为是执行 Linux 命令,只能在 Linux 下面运行)演示了它们的使用:
// exec.go
package main
import ("fmt""os/exec""os"
)func main() {
// 1) os.StartProcess //
/*********************/
/* Linux: */
env := os.Environ()
procAttr := &os.ProcAttr{Env: env,Files: []*os.File{os.Stdin,os.Stdout,os.Stderr,},}
// 1st example: list files
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)
输出:
The process id is &{2054 0}total 2056
-rwxr-xr-x 1 ivo ivo 1157555 2011-07-04 16:48 Mieken_exec
-rw-r--r-- 1 ivo ivo 2124 2011-07-04 16:48 Mieken_exec.go
-rw-r--r-- 1 ivo ivo 18528 2011-07-04 16:48 Mieken_exec_go_.6
-rwxr-xr-x 1 ivo ivo 913920 2011-06-03 16:13 panic.exe
-rw-r--r-- 1 ivo ivo 180 2011-04-11 20:39 panic.go
// 2nd example: show all processes
pid, err = os.StartProcess("/bin/ps", []string{"-e", "-opid,ppid,comm"}, procAttr) if err != nil {fmt.Printf("Error %v starting process!", err) //os.Exit(1)
}fmt.Printf("The process id is %v", pid)
// 2) exec.Run //
/***************/
// Linux: OK, but not for ls ?
// cmd := exec.Command("ls", "-l") // no error, but doesn't show anything ?
// cmd := exec.Command("ls") // no error, but doesn't show anything ?cmd := exec.Command("gedit") // this opens a gedit-windowerr = cmd.Run()if err != nil {fmt.Printf("Error %v executing command!", err)os.Exit(1)}fmt.Printf("The command is %v", cmd)
// The command is &{/bin/ls [ls -l] [] <nil> <nil> <nil> 0xf840000210 <nil> true [0xf84000ea50 0xf84000e9f0 0xf84000e9c0] [0xf84000ea50 0xf84000e9f0 0xf84000e9c0] [] [] 0xf8400128c0}
}
// in Windows: uitvoering: Error fork/exec /bin/ls: The system cannot find the path specified. starting process!
golang中的shell相关推荐
- linux 脚本 lang,golang可以编写shell脚本吗
golang可以编写shell脚本吗 golang是可以编写shell脚本,首先可以通过创建一个阅读器去访问键盘,每当按下回车键时,任何的写入都会被存储到输入变量中:然后根据出入的数据来执行逻辑运算: ...
- Golang中Buffer高效拼接字符串以及自定义线程安全Buffer
本文原创文章,转载注明出处,博客地址 https://segmentfault.com/u/to... 第一时间看后续精彩文章.觉得好的话,顺手分享到朋友圈吧,感谢支持. Go中可以使用"+ ...
- 如何在golang中关闭bufio.reader_Golang 并发模型系列:1. 轻松入门流水线模型
Go语言中文网,致力于每日分享编码.开源等知识,欢迎关注我,会有意想不到的收获! Golang作为一个实用主义的编程语言,非常注重性能,在语言特性上天然支持并发,它有多种并发模型,通过流水线模型系列文 ...
- Linux中执行shell脚本的4种方法
这篇文章主要介绍了Linux中执行shell脚本的4种方法总结,即在Linux中运行shell脚本的4种方法,需要的朋友可以参考下. bash shell 脚本的方法有多种,现在作个小结.假设我们编写 ...
- linux默认csh修改命令,Solaris中默认Shell的修改以及命令行补全的设置
Solaris中默认Shell的修改以及命令行补全的设置 发布时间:2008-02-18 00:01:41来源:红联作者:qtsmy Solaris10 x86虽然可以跑起来,但有很多方面都用这和以前 ...
- go语言的iota是什么意思_关于Golang中的iota
快速一览 iota是Golang中提供的一个简化常量和枚举编程的标识符,合理的使用这个标识符可以让代码变得更简洁,省去大量的不必要的代码. 比如下面的这个常量定义 const ( a = 1 b = ...
- Golang中的panic和recover(捕获异常)
Golang中的panic和recover(捕获异常) 参考文章: (1)Golang中的panic和recover(捕获异常) (2)https://www.cnblogs.com/zhzhlong ...
- golang 中string和int类型相互转换
总结了golang中字符串和各种int类型之间的相互转换方式: string转成int: test_int, err := strconv.Atoi(test_string) if err != ni ...
- vim中执行shell命令小结
vim中执行shell命令,有以下几种形式 1):!command 不退出vim,并执行shell命令command,将命令输出显示在vim的命令区域,不会改变当前编辑的文件的内容 例如 :!ls - ...
最新文章
- sqlserver中索引优化
- POJ 3040 Allowance【贪心】
- VC使用HTTP协议下载文件
- 金额转换,阿拉伯数字的金额转换成中国传统的形式如:(¥1011)-(一千零一拾一元整)输出。...
- GB/T 17710-1999 PHP生成校验码
- 一个@Transaction哪里来这么多坑?
- kafka 集群_kafka 集群及原理
- ubuntu系统安装python hello_ubuntu 下python安装及hello world
- shell字符串长度
- iOS中滤镜处理及相关内存泄漏问题的解决
- Oracle全备增量备份脚本,ORACLE-RMAN:备份脚本(全库,增量)
- android 8.1闪退,宁波市民卡app在Android 8.1闪退_宁波民生e点通
- [转载] Python进程——multiprocessing.Event()|Barrier()
- python 生成器_彻底理解 Python 生成器
- 推荐一个好用的百度文库在线免费下载文档网站
- Java实现智能对话机器人自动聊天+语音秒回
- word怎么转pdf,word批量转pdf方法
- 种子软件下载种子慢怎么解决
- python飞机大战实验报告心得_飞机大战实训报告
- 2021年软考考试时间确定
热门文章
- 【MATLAB】matlab 文档使用 ( 文档查询 | 文档层次 | 自带搜索工具 | 帮助命令 | 学习导引 )
- 【Flutter】Image 组件 ( 加载网络图片 | 加载静态图片 | 加载本地图片 | path_provider 插件 )
- 【Android 安全】DEX 加密 ( 阶段总结 | 主应用 | 代理 Application | Java 工具 | 代码示例 ) ★
- 【Android RTMP】安卓直播推流总结 ( 直播服务器搭建 | NV21 图像采集 | H.264 视频编码 | PCM 音频采集 | AAC 音频编码 | RTMP 包封装推流 )
- 【问题解决方案】ImportError: No module named 'openpyxl'/‘xlrd’
- 实时机器学习是什么,面临哪些挑战?
- 用 Python 实现文件查找
- 自己动手实现一个MVVM库
- 织梦dedecms dede plus文件作用介绍及安全设置
- 微信公众平台入门开发教程.Net(C#)框架