如何在 Linux 中使用 nohup 命令
已发表: 2022-06-25
Linux nohup命令可以让重要进程在启动它们的终端窗口关闭时继续运行。 我们将向您展示如何在当今的 Linux 上使用这个古老的命令。
HUP 和 SIGHUP
Linux 的祖先 Unix 是在 PC 发明之前创建的。 计算机是大型、昂贵的设备。 人们通过串行线路在同一建筑物内本地或通过慢速调制解调器连接与他们进行远程交互。 最初,他们在逐渐被哑终端取代的电传打字机上输入指令。
他们被称为哑巴,因为处理能力在你连接的计算机上,而不是你正在打字的终端上。 这些程序是在计算机上运行的——它可能在哪里——而不是在你桌面上的设备上。
如果发生什么中断了您的终端和计算机之间的连接,计算机会检测到线路掉线并向您正在运行的程序发送HUP或挂断信号。 程序收到信号后停止执行。
该功能在今天的 Linux 中仍然存在。 在您的 PC 上,终端窗口是物理终端的模拟。 如果您正在运行从该终端窗口启动的进程并关闭该窗口,则SIGHUP信号将发送到程序,以便它们被告知HUP并知道它们应该终止。
发生了级联效应。 如果进程启动了任何子进程,则 SIGHUP 也会向下传递给它们,以便它们知道应该终止。
nohup命令启动子进程,但拒绝将SIGHUP信号传递给它们。 这听起来像是一个问题,但它实际上是一个有用的功能。
nohup 命令
如果你想让一个进程在启动它的终端窗口关闭的情况下继续,你需要一种拦截SIGHUP的方法,这样程序就永远不会收到它。 (实际上,终端窗口不会启动进程,它们是由终端窗口内的 shell 会话启动的。)该问题的简单而优雅的解决方案是在 shell 会话和程序之间放置另一个进程,并拥有它中间层程序从不传递SIGHUP信号。
这就是nohup所做的。 它为您启动程序,使它们成为nohup的子进程,而不是 shell 的子进程。 因为它们不是 shell 的子进程,所以它们不会直接从 shell 接收SIGHUP 。 如果nohup不将SIGHUP传递给它的孩子,程序将根本不会收到SIGHUP 。
例如,当您需要让运行完成的长时间运行的进程时,这很有用。 如果您不小心关闭了终端窗口及其外壳,您也将终止该进程。 使用nohup启动进程将进程与nohup信号隔离开来。 如果您通过 SSH 在计算机上远程工作,并且您不希望敏感进程在远程连接失败时终止,则可以使用nohup在远程计算机上启动该进程。
使用 nohup
我们创建了一个程序,它没有做任何有用的事情,但它会运行并运行直到它被终止。 它每三秒将时间打印到终端窗口。 它被称为“长过程”的long-proc 。
./long-proc

如果这是一个做了一些有用的程序并且我们希望它在终端窗口和 shell 关闭的情况下继续运行,我们将使用nohup启动它。
nohup ./long-proc

该进程与stdin和stdout分离,因此它既不能接收任何输入也不能写入终端窗口。 此外,由于它仍在运行,您不会返回到命令提示符。 nohup所做的只是使进程不受终端关闭的影响。 它不会将进程变成后台任务。
您现在是否必须重新启动才能终止该过程? 否。要停止您尚未作为后台进程启动的nohup进程,请按 Ctrl+C 组合键。

该程序的输出已为我们捕获在一个名为“nohup.out”的文件中。 我们可以用更少的东西来审查它。
少 nohup.out

通常发送到终端窗口的任何内容都会被捕获在文件中。 nohup的后续运行将附加到现有的“nohup.out”文件中。

运行该进程的一种更有用的方法是使用nohup启动它,以便它能够承受终端窗口的关闭,同时使其成为后台任务。 为此,我们在命令行末尾添加一个&符号。
nohup ./long-proc &


您需要再次按“Enter”以返回命令提示符。 我们被告知进程的作业编号是 1——括号“ [] ”中的数字——并且进程 ID 是 13115。
我们可以使用其中任何一个来终止进程。 “Ctrl+C”现在不起作用,因为程序与终端窗口或 shell 没有任何关联。
如果您忘记了作业编号,您可以使用jobs命令列出已从该终端窗口启动的后台任务。
工作

要终止我们的任务,我们可以使用kill命令和作业编号,前面有一个百分号“ % ”,如下所示:
杀死 %1
如果您关闭了终端窗口,您需要找到进程 ID 并将其与kill命令一起使用。 pgrep命令将查找与您提供的搜索线索匹配的进程的进程 ID。 我们将搜索进程名称。
pgrep 长过程

现在我们可以使用进程 ID 来终止进程。
杀死13115

下次您按“Enter”时,系统会通知您该过程已终止。
现在让我们看看什么不会终止进程。 我们将重新启动它,然后关闭终端窗口。
nohup ./long-proc

如果我们打开一个新的终端窗口并使用pgrep搜索我们的进程,我们会看到它仍在运行。 关闭启动进程的终端窗口没有任何效果。
pgrep 长过程

可以将多个命令传递给nohup ,但通常最好单独启动它们。 它使将它们作为后台作业进行操作变得更加容易。 这些命令不会同时运行,它们将一个接一个地执行。 执行不是并发的,它是顺序的。 要让它们同时运行,您需要单独启动它们。
话虽如此,要一次启动多个进程,请使用nohup启动 Bash shell 并将-c (命令)选项与命令字符串一起使用。 使用单引号“ ' ”将命令列表括起来,使用双与号“ && ”分隔命令。
nohup bash -c 'ls /bin && ls /sbin'

如果您使用less查看“nohup.out”文件,您将看到第一个进程的输出,然后是第二个进程的输出。
少 nohup.out

两个命令的输出都被捕获在“nohup.out”文件中。 它没有交织在一起,第二个进程的输出仅在第一个进程终止后才开始。

如果您想使用您自己的文件而不是“nohup.out”,您可以将命令重定向到您选择的文件中。
nohup bash -c 'ls /bin && ls /sbin' > myfile.txt

请注意,消息不再说“将输出附加到 nohupo.out”,而是说“将 stderr 重定向到 stdout”,我们正在将 stdout 重定向到“myfile.txt”文件。
我们可以用 less 查看“myfile.txt”文件。
少 myfile.txt

和以前一样,它包含两个命令的输出。

有趣的是,公用事业的历史有时会让人觉得它与现代无关。 nohup命令就是其中之一。 为处理串行线路上的断开而创建的东西对于今天在功能非常强大的机器上的 Linux 用户仍然有用。
相关:你应该知道的 37 个重要的 Linux 命令

