nohup详解
nohup介绍
nohup 是 no hang up 的缩写,就是不挂断的意思。
- 用途:不挂断地运行命令
- 语法:nohup Command [ Arg … ] [ & ]
- 描述:nohup 命令运行由 Command 参数和任何相关的 Arg 参数指定的命令,忽略所有挂断(SIGHUP)信号。在注销后使用 nohup 命令运行后台中的程序。要运行后台中的 nohup 命令,添加 & ( 表示“and”的符号)到命令的尾部。
nohup与&的区别
开始之前先介绍linux的两个signal信号
- sigup (hang up) 挂断信号,eg 关闭终端
- sigint (interrupt) 中断信号,eg 交互程序执行
ctrl+c
演示
编写个c文件,程序很简单,每隔1s输出一句hello
|
|
编译成文件名为a,运行$ gcc -o a a.c
,执行./a
使用 ./a& 后台运行程序,会是什么效果呢?
如上图,首先会在终端显示进程号45002,键入ctrl+c,发出sigint信号,程序会继续运行
此时如果关掉session,程序会收到一个SIGHUP信号,此时会怎么样呢?
|
|
可以看到关闭session之后,进程号是45002的a进程也关闭了。
使用nohup ./a.out 又会是什么效果呢?
使用nohup 运行程序a.out,会发现:有一个提示,hello的输出也没有出现在前台
手动ps看进程号,这次a的进程号是45160。
此时如果关掉session,程序会收到一个SIGHUP信号,程序会不会关闭呢?
关掉session后,再次ps看一下,ID为32437的a.out进程还在。
这时候只能通过kill把程序干掉了,killall之后,ps查看进程已经关闭。
killall之后,查看发现多了一个nohup.out文件,不过这个文件的大小是0,有点奇怪,启动程序的时候,明明提示了“appending output to nohup.out”呀,先把问题遗留在这,测试一下Ctrl +C。
使用nohup启动a.out,如果键入Ctrl+C ,程序收到SIGINT信号后,直接关闭了。
使用nohup ./a &
运行程序后,可以看到:
- 会在终端显示进程号是45352
- 也会有一个“输出至nohup.out”的提示
键入Ctrl + C,发送SIGINT信号,没反应 && 关闭session,发送SIGHUP信号,也没反应
ID为45352的进程依然存在,后续只能用kill来关闭它。
结论
使用&后台运行程序:
- 结果会输出到终端
- 使用Ctrl + C发送SIGINT信号,程序免疫
- 关闭session发送SIGHUP信号,程序关闭
使用nohup运行程序:
- 结果默认会输出到nohup.out
- 使用Ctrl + C发送SIGINT信号,程序关闭
- 关闭session发送SIGHUP信号,程序免疫
平日线上经常使用nohup和&配合来启动程序:
- 同时免疫SIGINT和SIGHUP信号
同时,还有一个最佳实践:
- 不要将信息输出到终端标准输出,标准错误输出,而要用日志组件将信息记录到日志里
扩展
上面的hello去哪了
c语言标准输出有缓冲区,比如printf就存在行缓冲,只有缓冲刷新时才会一次性写入到文件中,我们先使用maven命令来看看效果
|
|
重定向
linux中的输入输出文件
- /dev/null 表示空设备文件
- 0 表示stdin标准输入
- 1 表示stdout标准输出
- 2 表示stderr标准错误
解释
file
表示将标准输出输出到file中,也就相当于 1>file- 2> error 表示将错误输出到error文件中
- 2>&1 也就表示将错误重定向到标准输出上
2>&1 >file
:错误输出到终端,标准输出重定向到文件file,结果是输出到两个地方; > file 2>&1(标准输出重定向到文件,错误重定向到标准输出),结果是输出到同一个文件。一定要注意顺序,linux在执行shell命令之前,就会确定好所有的输入输出位置,并且从左到右依次执行重定向的命令。
最佳实践
nohup放在命令的开头,表示不挂起(no hang up),也即,关闭终端或者退出某个账号,进程也继续保持运行状态,一般配合&符号一起使用。如nohup command &。
& 放在命令到结尾,表示后台运行,防止终端一直被某个进程占用,这样终端可以执行别到任务,配合 >file 2>&1可以将log保存到某个文件中,但如果终端关闭,则进程也停止运行。如 command > file.log 2>&1 & 。
还以一开始的c程序为例,由于printf存在行缓存,我们使用fprintf将字符串格式化输出到错误输出流文件中,如下
|
|
输出结果
nohup的最佳写法:
|
|
先将标准输出重定向到a.out,再将错误输出重定向到标准输出,也就是a.out,这样标准输出和错误输出都重定向到a.out文件,末尾带个&,中断还是挂起都照样运行。
还有一种比较常见的写法nohup command >/dev/null 2>&1 &
/dev/null
表示一个空设备,上面的写法是标准输出重定向到空设备也就是丢弃,再将错误输出也定向到空设备,也就是丢弃所有输出。