Shell脚本:后台运行

1. 名词解释

名词(中文)

名词(英文)

解释

会话

Session

每打开一次终端(本地或远程)登录Linux,都会生成一个新的会话;除此之外,程序中也可以调用函数setsid创建一个新的会话;脚本也可以调用命令setsid创建一个新的会话。新建的会话无控制终端。

会话ID

SessionID

用来标识一个会话,同一时刻不同会话的ID不会相同,是一个int类型的整数值。

用户

User

指能登录Linux的用户帐号

用户ID

UserID

用来唯一标识一个用户

伪终端或叫虚拟终端

 pty

(Pseudo Terminal)

控制终端

tty

(Teletypewriter或Teletype)

字符型设备

pts

(pseudo-terminal slave)

pty的实现方法,分两端:一端叫master,另一端叫slave。可打开的最多pts数为/proc/sys/kernel/pty/max,当前已打开的pts数为/proc/sys/kernel/pty/nr。

2. 什么是守护进程?

在后台运行的进程不一定是守护进程!一个进程要成为守护进程,必须做到以下两点:

1) 在后台运行

2) 脱离了终端

2.1. 后台运行

要使一个进程在后台运行,代码中可以通过fork子进程来实现,而命令行或脚本中可以通过使用“&”来实现。

fork之后,子进程会继承父进程的SessionID,调用execve()后的进程的SessionID不会改变。

2.2. 解释关系

子进程从父进程继承了:SessionID、进程组ID和打开的终端。子进程如果要脱离这些,代码中可通过调用setsid来实现。,而命令行或脚本中可以通过使用命令setsid来运行程序实现。setsid帮助一个进程脱离从父进程继承而来的已打开的终端、隶属进程组和隶属的会话。

需要注意,代码中调用setsid是有条件的:即调用进程自己不能是进程组长。因此,调用setsid之前需要先fork,然后由产生的子进程调用setsid。

3. 以“&”方式运行有何问题?

以“&”方式可以将一个前台进程以后台方式运行,但是如果它是一个终端的job,则如果向终端收到SIGHUP信号,终端也会向它的所有job发送SIGHUP,这样以“&”方式运行的进程则会因为收到SIGHUP则退出。

当用户注销(logout)或者网络断开时,终端会收到 SIGHUP(hangup)信号从而关闭其所有子进程。

早期的Unix,终端通过Modem和系统通讯,当用户注销(logout)时,Modem就会挂断(hangup)电话;当Modem断开时,会给终端发SIGHUP来通知终端关闭所有子进程。

4. setsid&setuid

setsid命令或函数

setuid函数(相对应的命令为chmod)

1) 创建一个会话

2) 调用进程将成为会话的组长

3) 调用进程将成为进程组的组长

4) 调用进程将脱离控制终端(tty)

5) 会话ID和进程组ID都和调用进程的PID相同

1) 设置调用进程的真实用户ID、有效用户ID和保存用户ID

按下“ctrl+z”会触发SIGTSTP,注意不是SIGSTOP,这两个信号的区别是前者可以捕获,而后者不可以。进程收到这两个信号后,都进入STOP状态,使用ps aux看到的状态值为“T”,可以通过发送信号SIGCONT重新回到运行状态。

4.1. setuid应用场景

1) 以root启动,但以其它用户身份运行,常见于Webserver,因为需要监听80端口,不得不以root启动,但root权限过大,因此运行经常会从root切换到nobody等用户;

2) 开发中经常需要让非root用户能够去gdb一些root启动的进程,这个时候只开放gdb等少数一些命令给非root用户。

5.让shell脚本后台运行的方法

当使用ssh连接到服务器运行程序时,用户注销(logout)或者网络断开时,终端会收到 HUP(hangup)信号从而关闭其所有子进程。但这往往不是我们想要的结果。为了避免这种情况的发生,让程序能够在服务器上正常运行,的解决办法就有两种途径:

  • 让进程忽略HUP信号;
  • 让进程运行在新的会话里从而成为不属于此终端的子进程。

nohup … &

nohup命令用途就是让提交的命令忽略HUP信号;&命令用途是让提交的命令在后台运行。同时使用nohup ... &可以让提交的命令忽略HUP信号,并将该命令放在后台运行。

e.g.:nohup sh big_task.sh > big_task.log 2>&1

Q:nohup 和 nohup … & 的区别?

A:nohup仅表示让提交的命令忽略hangup信号,但该命令仍然在前台运行,当前的shell会被阻塞,无法继续进行操作。但可以通过 ctrl-z将当前的命令挂起到后台,然后再使用bg命令让其在后台运行,这样就可以达到和使用nohup ... &同样的效果

Q:仅使用 & 命令会如何?

A:仅使用&命令仅会将命令放在后台执行,但仍然可能会受到HUP信号的影响。但此时可以通过使用disown -h命令让其忽略HUP信号

setsid

setsid可以让提交的命令在一个新的session中运行,新的进程不属于接受hangup信号的终端的子进程,这样即使ssh连接中断,新的进程也不会受到影响。

screen

screen可以用来创建一个新的session,它不属于ssh连接进程的子进程,因而不需要费心考虑HUP信号。

jobs


通过以下命令,我们可以对放入到后台的命令进行控制

查看当前终端下的后台进程:
直接执行:jobs

将查看到的某个后台进程放回到前台:
直接输入:fg %jobid //这里的jobid是通过jobs命令中看到的进程前[]中的数字。

将当前正在前台运行的进程放到后台运行:
先敲下快捷键:ctrl +z //暂停当前正在运行的进程。
再执行:bg

终止当前正在前台运行的进程:
直接敲下快捷键:ctrl +c

disown


亡羊补牢,为没有使用nohup与setsid的进程加上忽略HUP信号的功能。
使用方法:
将当前正在前台运行的进程放到后台运行(ctrl+z和bg);
然后执行disown -h %jobid //这里的jobid是通过jobs命令中看到的进程前[]中的数字。

猜你喜欢

转载自blog.csdn.net/u012460314/article/details/84348055
今日推荐