Linux中的Nohup命令教程以及示例用法

时间:2020-03-21 11:46:27  来源:igfitidea点击:

我们在Linux中执行的任何命令都将具有与之关联的相应进程。
即使是通常寿命很短的命令(例如grep,cat,ls等),也会有与之关联的进程。
所有这些过程都有三点共同点。
我实际上必须说四点共同点。
第四件事是父进程。
没有父进程的唯一进程是Linux中的INIT进程。
这四件事在下面提到。

  • 标准输入
  • 标准输出
  • 标准错误
  • 父进程

上面提到的前三个使用数字(0、1和2)表示。
0用于输入,1用于输出,最后2用于错误。
默认情况下,当我们使用Shell启动进程时,stdin会添加到我们键入的任何内容上,并且1和2是我们可以看到输出(以及错误)的同一终端。

在Unix操作系统中,有一种流行的说法是:“一切都是文件”,甚至硬件设备,网络连接和任何其他外部设备都不过是操作系统的某种特殊文件。

在继续进行之前,请考虑以下内容。

0是在系统中被标识为键盘的文件的数字。

1和2是标识为计算机屏幕的文件的编号。

调用上述0、1和2的正确术语是文件描述符。
因此,基本上这些文件描述符指示输入,输出和错误。
实际上,如果我们导航到系统中的/proc,则应该能够在进程ID名称下看到很多目录。

例如,使用两个不同的终端登录到同一台计算机。
在一个终端中,找出在另一终端中使用的bash shell的进程ID号(我们可以简单地执行ps aux | grep bash)。
假设bash进程的ID号为1952.
在这种情况下,请进入/prod/1952/fd /并执行以下操作。

root@instance-1:~# cd /proc/1952/fd/
root@instance-1:/proc/1952/fd# ls
0  1  2  255
root@instance-1:/proc/1952/fd# echo testing > 1
root@instance-1:/proc/1952/fd#

请注意,在上面的示例中1952是另一个终端上bash shell的pid。
一旦执行了上面的echo命令,该内容就应该在另一个终端上可见。
因为它实际上将内容发送到文件描述符“ 1”,这是标准输出屏幕。
因此,我们可以在终端上看到内容。

需要注意的另一件有趣的事是,0、1和2实际上是到另一个名为tty文件的文件的符号链接。
基本上是终端文件。

在Linux中,执行命令tty,它应该告诉我们终端名称。
在我的情况下,另一端的名称为/dev/pts/2,因此如下所示。

root@instance-1:/proc/1952/fd# ls -l
total 0
lrwx------ 1 sarath sarath 64 Nov  9 05:01 0 -> /dev/pts/2
lrwx------ 1 sarath sarath 64 Nov  9 05:01 1 -> /dev/pts/2
lrwx------ 1 sarath sarath 64 Nov  9 05:01 2 -> /dev/pts/2
lrwx------ 1 sarath sarath 64 Nov  9 05:01 255 -> /dev/pts/2

如果使用shell运行进程,则该进程还将具有相同的0、1和2.
在大多数情况下,输出,错误和输入基本上与shell本身相同。
因此,我们可以在终端本身上看到过程输出。
如果从shell注销/退出,shell通常会收到一个称为SIGHUP的信号。

在大多数情况下,bash shell的默认设置是将SIGHUP信号发送到它启动的所有作业(基本上,父bash进程会将SIGHUP发送给它的所有子进程)。
这意味着,一旦退出shell,使用shell启动的作业在大多数情况下也将退出。

它不将SIGHUP发送到作业的唯一情况是是否打开了huponexit设置。
我们可以在bash shell中使用shopt -s huponexit命令来执行此操作。

我们可以使用另一种称为disown的bash shell内置功能来防止作业获取SIGHUP。
我们基本上是开始一个过程并将其置于后台。
要启动一个进程并将其置于后台,我们基本上要执行命令,后跟“&”。
(例如:我的命令&)。

同样在这种情况下,后台作业仍将使用shell程序的stdout和stderr(1&2)。
后台进程的输出没有变化(除非我们使用某种重定向方法,例如“>”,即:my-command> output.file)。
一旦工作进入后台,我们就可以执行disown -h%1.
请注意,%1代表作业编号(我们可以使用jobs命令找到它)。

使用上述方法,可以防止shell退出时作业接收到SIGHUP。
但是,该作业仍与终端关联。
基本上,一旦我们从shell中注销,就没有办法获取该进程的stdout和stderr(是的,该进程不会得到SIGHUP,它将继续运行)。

那么,为什么我要谈论所有这些问题,尤其是当主题是关于“ Nohup命令”的时候。
顾名思义,Nohup阻止作业接收SIGHUP信号。
换句话说,使用nohup开始的作业将忽略bash发送的SIGHUP信号。
除此之外,与不使用或者设置商店相比,nohup还具有其他一些独特之处。

#nohup somecommand

上面显示的是执行nohup的方法。
基本上在命令前加上nohup。
但是上面显示的执行nohup的方法实际上是没有用的。

这是因为nohup将结束该过程的标准输入。
这意味着我们不能将输入传递给使用nohup启动的进程,如上所示。
因此,使用nohup对进程基本上没有用,并将进程保持在前台(因为它不能接受输入)。
因此,人们通常要做的是在开始使用nohup时始终将进程置于后台。

#nohup somecommand &

关于nohup要注意的另一件事是,它将在当前目录中创建一个名为nohup.out的文件,并将所有stdout和stderr发送到该目录(即:1和2将指向nohup.out文件)。
让我们实际看一下。

root@instance-1:~# nohup sh script.sh &
[1] 3416
root@instance-1:~# nohup: ignoring input and appending output to ‘nohup.out’

输出清楚地表明它将忽略输入。
因此,使用nohup运行命令时,请不要考虑输入内容。
但是所有stdout和stderr都将转到当前目录中名为nohup.out的文件。

因此,基本上,我们之前看到的符号链接(链接到名为/dev/dev/pts2的终端ID)现在应该链接到nohup.out文件。
见下文。

root@instance-1:~# ls -l /proc/3416/fd/
total 0
l-wx------ 1 root root 64 Nov  9 06:55 0 -> /dev/null
l-wx------ 1 root root 64 Nov  9 06:55 1 -> /root/nohup.out
lr-x------ 1 root root 64 Nov  9 06:55 10 -> /root/script.sh
l-wx------ 1 root root 64 Nov  9 06:55 2 -> /root/nohup.out

请注意,1和2指向nohup.out文件。

关于nohup要注意的另一点重要事实是,它对shell的作业控制没有任何作用。
基本上,以nohup开头的作业仍将存在于Shell的作业列表中。
但是当shell退出时,它不会被杀死。

我们可以使用以下方法将stderr和stdout发送到两个不同的文件。
在这种情况下,它根本不会生成nohup.out文件。

root@instance-1:~# nohup ./script.sh > my-output 2> my-error &
[1] 4034
root@instance-1:/proc/4034/fd# ls -l
total 0
l-wx------ 1 root root 64 Nov  9 07:16 0 -> /dev/null
l-wx------ 1 root root 64 Nov  9 07:16 1 -> /root/my-output
l-wx------ 1 root root 64 Nov  9 07:16 2 -> /root/my-error
lr-x------ 1 root root 64 Nov  9 07:16 255 -> /root/script.s

我们也可以使用以下方法将stdout和stderr都发送到我们感兴趣的同一文件(nohup.out除外)。

root@instance-1:~# nohup ./script.sh > my-output 2>&1 &
[1] 4178
root@instance-1:~#
root@instance-1:~#
root@instance-1:~# cd /proc/4178/fd
root@instance-1:/proc/4178/fd# ls -l
total 0
l-wx------ 1 root root 64 Nov  9 07:19 0 -> /dev/null
l-wx------ 1 root root 64 Nov  9 07:19 1 -> /root/my-output
l-wx------ 1 root root 64 Nov  9 07:19 2 -> /root/my-output
lr-x------ 1 root root 64 Nov  9 07:19 255 -> /root/script.sh

在上面的命令中,2>&1表示stdout和stderr都应转到该文件。

有关nohup的一些注意事项如下:

  • Nohup不会从Shell作业表中删除作业
  • 使用nohup运行的进程将忽略SIGHUP信号
  • 默认情况下,nohup.out文件用于所有内容(stdout和stderr)
  • 一旦使用nohup执行作业,stdin将不可用(这就是为什么0链接到/dev/null的原因)