golang 执行系统命令ps aux|grep "xxxx",总是异常退出go语言关闭进程你这个是两个命令go语言关闭进程,不是一个命令 。
grep是查找命令 , go语言关闭进程你应该:
exec.Command("ps", "aux").Output()
出结果后再过虑 。
golang 的Command启动的进程如何关闭在用exec包调用go语言关闭进程的其他进程后如何关闭结束go语言关闭进程 , 可以使用context包go语言关闭进程的机制进行管理go语言关闭进程,context包的使用详见:
exec.CommandContext 方发实现了 context go语言关闭进程,通过 context 可以对exec启动的进程结束 。
隐藏程序自身黑窗口的方法: go build -ldflags="-H windows"
隐藏子进程黑窗口的方法:
cmd.SysProcAttr = syscall.SysProcAttr{HideWindow: true}
golang 进程创建,fork,以及热重启(无缝升级) 一般来说go语言关闭进程,进程go语言关闭进程的操作使用的是一些系统的命令,所以go内部使用os包,进行一些运行系统命令的操作
os 包及其子包 os/exec 提供了创建进程的方法 。
一般的,应该优先使用 os/exec 包 。因为 os/exec 包依赖 os 包中关键创建进程的 API,为了便于理解 , 我们先探讨 os 包中和进程相关的部分 。
Unix :fork创建一个进程,(及其一些变种,如 vfork、clone) 。
Go:Linux 下创建进程使用的系统调用是 clone 。
允许一进程(父进程)创建一新进程(子进程) 。具体做法是 , 新的子进程几近于对父进程的翻版:子进程获得父进程的栈、数据段、堆和执行文本段的拷贝 。可将此视为把父进程一分为二 。
终止一进程,将进程占用的所有资源(内存、文件描述符等)归还内核,交其进行再次分配 。参数 status 为一整型变量,表示进程的退出状态 。父进程可使用系统调用 wait() 来获取该状态 。
目的有二:其一,如果子进程尚未调用 exit() 终止,那么 wait 会挂起父进程直至子进程终止;其二 , 子进程的终止状态通过 wait 的 status 参数返回 。
加载一个新程序(路径名为 pathname,参数列表为 argv,环境变量列表为 envp)到当前进程的内存 。这将丢弃现存的程序文本段 , 并为新程序重新创建栈、数据段以及堆 。通常将这一动作称为执行一个新程序 。
没有直接提供 fork 系统调用的封装,而是将 fork 和 execve 合二为一,提供了 syscall.ForkExec 。如果想只调用 fork,得自己通过 syscall.Syscall(syscall.SYS_FORK, 0, 0, 0) 实现 。
os.Process 存储了通过 StartProcess 创建的进程的相关信息 。
一般通过 StartProcess 创建 Process 的实例,函数声明如下:
它使用提供的程序名、命令行参数、属性开始一个新进程 。StartProcess 是一个低级别的接口 。os/exec 包提供了高级别的接口,一般应该尽量使用 os/exec 包 。如果出错 , 错误的类型会是 *PathError 。
属性定义如下:
FindProcess 可以通过 pid 查找一个运行中的进程 。该函数返回的 Process 对象可以用于获取关于底层操作系统进程的信息 。在 Unix 系统中,此函数总是成功,即使 pid 对应的进程不存在 。
Process 提供了四个方法:Kill、Signal、Wait 和 Release 。其中 Kill 和 Signal 跟信号相关,而 Kill 实际上就是调用 Signal,发送了 SIGKILL 信号,强制进程退出,关于信号,后续章节会专门讲解 。
Release 方法用于释放 Process 对象相关的资源,以便将来可以被再使用 。该方法只有在确定没有调用 Wait 时才需要调用 。Unix 中,该方法的内部实现只是将 Process 的 pid 置为 -1 。
通过 os 包可以做到运行外部命令,如前面的例子 。不过,Go 标准库为我们封装了更好用的包: os/exec,运行外部命令,应该优先使用它 , 它包装了 os.StartProcess 函数以便更容易的重定向标准输入和输出 , 使用管道连接 I/O,以及作其它的一些调整 。
exec.LookPath 函数在 PATH 指定目录中搜索可执行程序,如 file 中有 /,则只在当前目录搜索 。该函数返回完整路径或相对于当前路径的一个相对路径 。
func LookPath(file string) (string, error)
如果在 PATH 中没有找到可执行文件,则返回 exec.ErrNotFound 。
Cmd 结构代表一个正在准备或者在执行中的外部命令,调用了 Run、Output 或 CombinedOutput 后,Cmd 实例不能被重用 。
一般的,应该通过exec.Command函数产生Cmd实例:
用法
得到 * Cmd实例后,接下来一般有两种写法:
前面讲到 , 通过Cmd实例后,有两种方式运行命令 。有时候,我们不只是简单的运行命令,还希望能控制命令的输入和输出 。通过上面的 API 介绍,控制输入输出有几种方法:
参考资料:
Go 语言的错误处理机制是一个优秀的设计吗这个问题说来话长,我先表达一下我的观点 , Go语言从语法层面提供区分错误和异常的机制是很好的做法,比自己用单个返回值做值判断要方便很多 。
上面看到很多知乎大牛把异常和错误混在一起说,有认为Go没有异常机制的,有认为Go纯粹只有异常机制的,我觉得这些观点都太片面了 。
具体对于错误和异常的讨论,我转发一下前阵子写的一篇日志抛砖引玉吧 。
============================
最近连续遇到朋友问我项目里错误和异常管理的事情,之前也多次跟团队强调过错误和异常管理的一些概念,所以趁今天有动力就赶紧写一篇Go语言项目错误和异常管理的经验分享 。
首先我们要理清:什么是错误、什么是异常、为什么需要管理 。然后才是怎样管理 。
错误和异常从语言机制上面讲,就是error和panic的区别 , 放到别的语言也一样,别的语言没有error类型,但是有错误码之类的,没有panic , 但是有throw之类的 。
在语言层面它们是两种概念,导致的是两种不同的结果 。如果程序遇到错误不处理,那么可能进一步的产生业务上的错误,比如给用户多扣钱了,或者进一步产生了异常;如果程序遇到异常不处理,那么结果就是进程异常退出 。
在项目里面是不是应该处理所有的错误情况和捕捉所有的异常呢?我只能说,你可以这么做,但是估计效果不会太好 。我的理由是:
如果所有东西都处理和记录,那么重要信息可能被淹没在信息的海洋里 。
不应该处理的错误被处理了,很容易导出BUG暴露不出来,直到出现更严重错误的时候才暴露出问题,到时候排查就很困难了,因为已经不是错误的第一现场 。
所以错误和异常最好能按一定的规则进行分类和管理,在第一时间能暴露错误和还原现场 。
对于错误处理,Erlang有一个很好的概念叫速错,就是有错误第一时间暴露它 。我们的项目从Erlang到Go一直是沿用这一设计原则 。但是应用这个原则的前提是先得区分错误和异常这两个概念 。
错误和异常上面已经提到了,从语言机制层面比较容易区分它们,但是语言取决于人为 , 什么情况下用错误表达 , 什么情况下用异常表达,就得有一套规则,否则很容易出现全部靠异常来做错误处理的情况,似乎Java项目特别容易出现这样的设计 。
这里我先假想有这样一个业务:游戏玩家通过购买按钮,用铜钱购买宝石 。
在实现这个业务的时候,程序逻辑会进一步分化成客户端逻辑和服务端逻辑,客户端逻辑又进一步因为设计方式的不同分化成两种结构:胖客户端结构、瘦客户端结构 。
胖客户端结构,有更多的本地数据和懂得更多的业务逻辑,所以在胖客户端结构的应用中,以上的业务会实现成这样:客户端检查缓存中的铜钱数量,铜钱数量足够的时候购买按钮为可用的亮起状态 , 用户点击购买按钮后客户端发送购买请求到服务端;服务端收到请求后校验用户的铜钱数量,如果铜钱数量不足就抛出异常,终止请求过程并断开客户端的连接 , 如果铜钱数量足够就进一步完成宝石购买过程,这里不继续描述正常过程 。
因为正常的客户端是有一步数据校验的过程的,所以当服务端收到不合理的请求(铜钱不足以购买宝石)时 , 抛出异常比返回错误更为合理,因为这个请求只可能来自两种客户端:外挂或者有BUG的客户端 。如果不通过抛出异常来终止业务过程和断开客户端连接,那么程序的错误就很难被第一时间发现 , 攻击行为也很难被发现 。
我们再回头看瘦客户端结构的设计,瘦客户端不会存有太多状态数据和用户数据也不清楚业务逻辑,所以客户端的设计会是这样:用户点击购买按钮,客户端发送购买请求;服务端收到请求后检查铜钱数量,数量不足就返回数量不足的错误码 , 数量足够就继续完成业务并返回成功信息;客户端收到服务端的处理结果后,在界面上做出反映 。
在这种结构下,铜钱不足就变成了业务逻辑范围内的一种失败情况,但不能提升为异常,否则铜钱不足的用户一点购买按钮都会出错掉线 。
所以,异常和错误在不同程序结构下是互相转换的,我们没办法一句话的给所有类型所有结构的程序一个统一的异常和错误分类规则 。
但是 , 异常和错误的分类是有迹可循的 。比如上面提到的痩客户端结构,铜钱不足是业务逻辑范围内的一种失败情况,它属于业务错误,再比如程序逻辑上尝试请求某个URL,最多三次,重试三次的过程中请求失败是错误,重试到第三次 , 失败就被提升为异常了 。
所以我们可以这样来归类异常和错误:不会终止程序逻辑运行的归类为错误,会终止程序逻辑运行的归类为异常 。
因为错误不会终止逻辑运行,所以错误是逻辑的一部分,比如上面提到的瘦客户端结构,铜钱不足的错误就是业务逻辑处理过程中需要考虑和处理的一个逻辑分支 。而异常就是那些不应该出现在业务逻辑中的东西,比如上面提到的胖客户端结构 , 铜钱不足已经不是业务逻辑需要考虑的一部分了,所以它应该是一个异常 。
错误和异常的分类需要通过一定的思维训练来强化分类能力,就类似于面向对象的设计方式一样的,技术实现就摆在那边,但是要用好需要不断的思维训练不断的归类和总结 , 以上提到的归类方式希望可以作为一个参考,期待大家能发现更多更有效的归类方式 。
接下来我们讲一下速错和Go语言里面怎么做到速错 。
速错我最早接触是在做的时候就体验到的,当然跟Erlang的速错不完全一致,那时候也没有那么高大上的一个名字,但是对待异常的理念是一样的 。
在.NET项目开发的时候,有经验的程序员都应该知道,不能随便re-throw,就是catch错误再抛出,原因是异常的第一现场会被破坏 , 堆栈跟踪信息会丢失,因为外部最后拿到异常的堆栈跟踪信息,是最后那次throw的异常的堆栈跟踪信息;其次,不能随便try catch,随便catch很容易导出异常暴露不出来,升级为更严重的业务漏洞 。
到了Erlang时期,大家学到了速错概念,简单来讲就是:让它挂 。只有挂了你才会第一时间知道错误,但是Erlang的挂,只是Erlang进程的异常退出,不会导致整个Erlang节点退出,所以它挂的影响层面比较低 。
在Go语言项目中,虽然有类似Erlang进程的Goroutine , 但是Goroutine如果panic了,并且没有recover , 那么整个Go进程就会异常退出 。所以我们在Go语言项目中要应用速错的设计理念,就要对Goroutine做一定的管理 。
在我们的游戏服务端项目中,我把Goroutine按挂掉后的结果分为两类:1、挂掉后不影响其他业务或功能的;2、挂掉后业务就无法正常进行的 。
第一类Goroutine典型的有:处理各个玩家请求的Goroutine , 因为每个玩家连接各自有一个Goroutine,所以挂掉了只会影响单个玩家,不会影响整体业务进行 。
第二类Goroutine典型的有:数据库同步用的Goroutine,如果它挂了,数据就无法同步到数据库,游戏如果继续运行下去只会导致数据回档,还不如让整个游戏都异常退出 。
这样一分类 , 就可以比较清楚哪些Goroutine该做recover处理,哪些不该做recover处理了 。
那么在做recover处理时 , 要怎样才能尽量保留第一现场来帮组开发者排查问题原因呢?我们项目中通常是会在最外层的recover中把错误和堆栈跟踪信息记进日志,同时把关键的业务信息,比如:用户ID、来源IP、请求数据等也一起记录进去 。
为此,我们还特地设计了一个库,用来格式化输出堆栈跟踪信息和对象信息,项目地址:funny/debug · GitHub
通篇写下来发现比我预期的长很多,所以这里我做一下归纳总结,帮组大家理解这篇文章所要表达的:
错误和异常需要分类和管理,不能一概而论
错误和异常的分类可以以是否终止业务过程作为标准
错误是业务过程的一部分,异常不是
不要随便捕获异常,更不要随便捕获再重新抛出异常
Go语言项目需要把Goroutine分为两类,区别处理异常
在捕获到异常时 , 需要尽可能的保留第一现场的关键数据
以上仅为一家之言,抛砖引玉 , 希望对大家有所帮助 。
Go语言文件操作本文主要介绍了Go语言中文件读写的相关操作 。
文件是什么?
计算机中的文件是存储在外部介质(通常是磁盘)上的数据集合,文件分为文本文件和二进制文件 。
os.Open() 函数能够打开一个文件,返回一个 *File 和一个 err。对得到的文件实例调用 close() 方法能够关闭文件 。
为了防止文件忘记关闭,我们通常使用defer注册文件关闭语句 。
Read方法定义如下:
它接收一个字节切片,返回读取的字节数和可能的具体错误,读到文件末尾时会返回 0 和 io.EOF。举个例子:
使用for循环读取文件中的所有数据 。
bufio是在file的基础上封装了一层API , 支持更多的功能 。
io/ioutil 包的 ReadFile 方法能够读取完整的文件,只需要将文件名作为参数传入 。
os.OpenFile() 函数能够以指定模式打开文件 , 从而实现文件写入相关功能 。
其中:
name :要打开的文件名flag :打开文件的模式 。模式有以下几种:
perm :文件权限,一个八进制数 。r(读)04 , w(写)02,x(执行)01 。
【go语言关闭进程 golang 关机】关于go语言关闭进程和golang 关机的介绍到此就结束了 , 不知道你从中找到你需要的信息了吗 ?如果你还想了解更多这方面的信息,记得收藏关注本站 。
推荐阅读
- 超级直播使用教程,超级直播调试模式怎么开
- 荣耀不支持鸿蒙系统了,荣耀手机不支持鸿蒙系统
- 视频号快速取消关注,怎样取消视频号里的关注
- thinkphp关联模型插入数据,tp6关联模型
- 卖oracle产品怎么说 oracle售价
- asp.net选择填空题,aspnet findcontrol
- win8虚拟机安装教程,windows8虚拟机教程
- 区域网单机游戏,可以区域网联机的低端电脑单机游戏
- 包含Windows系统10的词条