Shell脚本:后台运行
1. 名词解释名词(中文)名词(英文)解释会话Session每打开一次终端(本地或远程)登录Linux,都会生成一个新的会话;除此之外,程序中也可以调用函数setsid创建一个新的会话;脚本也可以调用命令setsid创建一个新的会话。新建的会话无控制终端。...
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命令中看到的进程前[]中的数字。
更多推荐
所有评论(0)