前言

首先,相信大家都或多或少了解过linux和云服务器。linux作为一个开源的操作系统内核,在开发者人群和服务器领域中有着很高的使用率。而现在在以阿里云为代表的云服务器商中,可以以很低的价格买入入门级别的云服务器。这些服务器虽然性能不强,但胜在持久。若是自己要进行一些运行时间比较长的任务时,用自己的电脑进行不仅不方便也不划算。这时候把任务交给云服务器就是个不错的选择。
要在linux服务器上运行程序,要用命令行的方式。比如,张三编写了一个名为test.py的脚本,要运行它,只需在连接上服务器后键入:

1
python test.py

即可运行脚本。
但事情总不会是一帆风顺的。比如自己若是在连接后长时间未操作,或是电脑突然故障关机,就会导致ssh断开。这个时候再去重新连接,就会进入一个新的终端,原本运行的脚本不见踪影。怎样避免这种情况呢?
下面就要引出本文的主题了。

Part II

只要通过下面的命令就可以让程序在后台运行啦:

1
nohup python test.py > test.log 2>&1 &

下面我们就来详细地看看这行命令。

首先,最显眼的就是前面的nohup命令了。

nohup指不断地运行,是no hang up的缩写,指不间断,不挂断。具体是什么意思呢?就是指如果你运行nohup xxx的命令的话,当你断开和服务器的连接后,任务依旧会运行,不会因用户的离开而终止。但命令仍是运行在前台的。

之后我们再来看看最后面的&

这个符号就是让程序运行在后台的命令了。当你输入xxx &后,就会让程序在后台运行。你不用开启一个新的终端就可以去干其他的事。

最后我们再来看看中间的python test.py > test.log 2>&1

python test.py很简单,就像前文所言,这是最基本的运行脚本的命令。test.py作为参数递交给pythonpython随后读取脚本文件的内容并运行。
之后是> test.log
>为管道命令(?),以为将前面的输出写入后面的文件。
比如a.exe中有:printf("xxx");之后输入a.exe > test.txt,运行完成后打开test.txt,就可以看见刚才a.exe输出的xxx了。
同理的命令还有>>。他们的不同是:>>为追加模式,写入新内容的同时不会影响前面的内容。而>则会在写入新内容前清空文件的内容,当作新文件来写入。
最后就是2>&1了。
要理解这段命令,首先要理解在Linux环境下的123 。在Linux下:

  • 0 表示stdin标准输入,用户键盘输入的内容
  • 1 表示stdout标准输出,输出到显示屏的内容
  • 2 表示stderr标准错误,报错内容
    而后面的>&则是重定向的意思。其中的&是为了区别文件1和1(标准输出),假如为2>1,那么不就成了将错误内容输出到文件1中。
    连在一起的2>&1即为将错误内容重定向输入到标准输出中去的意思。

Part III

好了,现在我们有了理论知识,就可以实践啦。我们接下来就可以找个服务器输入代码试试效果了。
在实验前我们先准备个脚本:

1
2
3
4
5
6
# test.py
import time

for i in range(10):
print('test')
time.sleep(10)

好!保存运行。

1
2
[ame@RaMizy ws]$ nohup python test.py > test.log 2>&1 &
[1] 32270

好了,现在程序就已经在后台运行了,输入ls命令,就可以看到输出的test.log文件了。我们cat进去。

1
2
3
4
[ame@RaMizy ws]$ ls
xxx[省略其他文件] test.log test.py
[ame@RaMizy ws]$ cat test.log
nohup: ignoring input

这就奇怪了,按照之前的代码,程序应该一运行就立刻输出第一个test才对。但现在的文件却什么内容都没有。
其实答案很简单,我们在使用python时默认启用了缓冲模式,要等程序结束后才会一次性将输出写入文件。要想让python实时输出也很简单,只要加上-u参数即可。我们再来一次。

1
2
3
4
5
[ame@RaMizy ws]$ nohup python -u test.py > test.log 2>&1 &
[1] 32674
[ame@RaMizy ws]$ cat test.log
nohup: ignoring input
test

即使我们把SSH窗口关掉也不会影响到他。现在,我们重启了一次SSH窗口之后,怎么确定他还活着呢?
最简单的方法当然是等待一段时间,再cat test.log。这个时候我们便可以看见完整的输出了。
当然也有其他的方法,比如在我们让程序运行起来后,我们能看到这样的回显:[1] 32674。这其实就是程序的PID了。通过ps -A命令,我们能看到目前所有正在运行的程序。

1
2
3
4
5
[ame@RaMizy ws]$ ps -A
PID TTY TIME CMD
......[省略其他的程序]
32764 pts/0 00:00:00 python
......[省略其他的程序]

只要能看到它,就能确认程序是否存活。当然,你也可以使用kill [pid]来提前结束他的存在。

Reference

这里就把一连串的引用链都放着了,终于又可以归档一个收藏夹的链接了(
阿里云后台运行python程序(后台运行scrapy爬虫)的方法
python nohup linux 后台运行输出
Python后台运行—nohup及2>&1详解