应用场景

场景一

服务器正在运行 Mindustry 或 Minecraft 的服务端程序,而正在游戏内游玩的我发现游戏延迟突然增高,合理怀疑是系统进程占用过高,第一反应是使用 ps 命令实时查看一下系统资源的占用情况。但 Mindustry 或 Minecraft 的服务端程序都是 Java 语言写的 .jar 程序,运行的时候需要占用控制台,怎么办,难道要中断服务器程序?

场景二

过年回到家发现一年没碰的 Ubuntu 服务器上的 Python 还是 3.6 版本,而我现在习惯使用 3.7 或 3.8 版本,那就顺便用 apt-get -y update && apt-get -y upgrade 命令给服务器上所有程序全部升个级,说干就干,但 5min 过去了进度条还在不停地跑,正在另一台 PC 上用浏览器向 BT 下载器 Transmission 中添加种子文件的我突然发现有个种子怎么也加不进去,我的 Transmission 是安装在服务器上的,于是立马想去服务器上看看日志,但控制台被升级命令占用,需要等它先结束才能使用,急性子的我却一秒也等不下去了,怎么办,中断更新吗?

应用方案

写个循环计算 100 以内所有奇数之和的例子 loop.sh 以备下面举例使用。

1
2
3
4
5
6
7
8
9
#!/bin/bash
declare -i i=1
declare -i sum=0
while [$i -le 100 ]
do
sum=sum+$i
i+=1
sleep 1 # 为了让程序运行时间更久,每次循环睡眠 1 秒
done

方案一

1
2
# 后台运行,但关闭终端会停止运行
command &

Linux/Unix 为了实线多用户、多任务,提供了 fgbg 命令,可以方便地调度正在运行的程序。当前台运行的某个程序需要一段时间才能结束,但现在需要做其他事,就可以使用 Ctrl + Z 组合键挂起这个程序。

执行 ./loop.sh 命令运行它,再使用 Ctrl + Z 组合键挂起这个程序,这时控制台提示:

1
[1]+ Stopped ./loop.sh

这时该程序就暂停了,此时利用 bg 命令可以使停止的程序放在后台继续运行。执行命令 bg 1,这时控制台提示:

1
[1]+ ./loop.sh &

然后就可以先去做别的事情了。如果事情做完回来该程序还没有结束,可以使用 jobs 命令显示当前 shell 环境中后台正在运行或者被挂起的任务信息,这时控制台提示:

1
[1]+ Running ./loop.sh &

如果想把它调回前端继续执行,可以使用 fg 1 命令,这时控制台提示:

1
\./loop.sh

这样就可以继续等着它执行完毕了。

注意:

  • 不要后台运行需要用户交互的程序,因为用户不输入的话,程序就会一直等。
  • 即使后台运行,带输出的程序一样会把结果输出到控制台,干扰做其它事情。那么将执行命令换成 command >out.file 2>&1 & 可以将全部输出结果(含标准输出和错误输出)重定向到同目录下的 out.file 文件中。

方案二

1
2
# 后台运行,即使关闭终端也会继续运行
nohup command &

如果我正在运行一个程序,并且预见即使在我退出控制台也还不会执行完毕,那么可以使用 nohup 命令,意思是 no hang up (不要挂起)。

还用上面 loop.sh 做例子,具体命令:

1
# nohup ./loop.sh &

注意:

  • 跟方案一不同的是,使用此命令在后台运行程序时,默认情况下所有输出结果(含标准输出和错误输出)会被重定向到同目录下的 nohup.out 文件中。当然也可主动指定输出文件,命令:nohup command > custom.file 2>&1