目录
当我们在执行Shell脚本时,会感觉到Shell脚本就是在当前的Shell命令行提示符下被解释执行的,其实不是的,,当脚本被执行的时候,当前的Shell会启动一个子进程执行当前的Shell脚本。本篇文章就讲解下子Shell和进程处理
我们首先来了解第一个Shell是如何启动的?
当用户登录Linux后,操作系统会根据用户/etc/passwd文件中的配置启动一个Shell进程,该Shell进程是当前用户所执行的Shell命令的父进程。每个用户都可以指定自动的默认Shell程序,下面显示部分/etc/passwd的内容:
eden_ubuntu@edenubuntu:~/Documents/Shell/12$ cat /etc/passwd
root:x:0:0:root:/root:/bin/bash
daemon:x:1:1:daemon:/usr/sbin:/usr/sbin/nologin
bin:x:2:2:bin:/bin:/usr/sbin/nologin
sys:x:3:3:sys:/dev:/usr/sbin/nologin
sync:x:4:65534:sync:/bin:/bin/sync
games:x:5:60:games:/usr/games:/usr/sbin/nologin
man:x:6:12:man:/var/cache/man:/usr/sbin/nologin
lp:x:7:7:lp:/var/spool/lpd:/usr/sbin/nologin
mail:x:8:8:mail:/var/mail:/usr/sbin/nologin
news:x:9:9:news:/var/spool/news:/usr/sbin/nologin
uucp:x:10:10:uucp:/var/spool/uucp:/usr/sbin/nologin
proxy:x:13:13:proxy:/bin:/usr/sbin/nologin
其中/etc/passwd每一行描述了一个用户信息,一共有7个字段,每个字段的含义如下:
用户名:x:用户ID:用户组ID:备注信息:用户主目录:默认Shell程序
默认Shell程序使用绝对路径。如果这个字段的Shell程序不存在,不合法,则无法登录主机。如果用户不需要登录,则可以将路径设置为 /usr/sbin/nologin。
下图描述了父子Shell的工作过程:
在一些其他书籍中,我们经常看到所谓内部命令和外部命令这个说法,这里来解释下它们的区别。
内部命令是指包含在Shell工具包中的命令,内部命令嵌入在Shell程序中,并不以单独的磁盘文件的形式(可执行文件)存在。比如cd, bg, exit,exec, eval,pwd等.
外部命令是Linux系统中的实用程序部分,这些程序以磁盘文件的方式存在于磁盘中。在用户登录时,外部命令并不像内部命令一样随着默认Shell加载到内存中,而是在需要的时候才被调用进内存。Shell程序管理外部命令执行时的路径查找和代码加载,并控制命令的执行。比如ls,at,du,host等都是外部命令。外部命令通常都位于/usr/bin以及/usr/sbin等目录中,其中/usr/sbin中的命令通常与系统管理有关。
Shell的保留字一般就是Shell语法中的关键字,这里不一一列出了。
(command1;command2;...)
(command1;command2;...)&
当把命令放到一个圆括号中执行时,该组命令会在子Shell中执行 ,如果在括号后面加上&,表示该子Shell后台执行,不会阻塞当前父进程。
这种方法先了解,以后有地方需要再看看,目前我感觉还用不到,但是要了解,当看到这种代码时要懂。
什么是进程,这里就不多做介绍了,我们首先理解下作业这个概念:一个作业可以包含多个进程,作业是针对用户而言的,是用户为了完成某项任务而启动的进程,1个作业可以包含1个,也可以包含多个进程,这些进程之间协同工作,共同完成任务。而进程是针对操作系统而言的,是操作系统程序执行的基本单位。
比如:
ls -l | grep 13 | more
上面一组命令可以称为一个作业,但是还会启动3个进程。
当我们后台执行Shell脚本时,比如:
eden_ubuntu@edenubuntu:~/Documents/Shell/13$ ./13-10.sh &
[1] 16386
会显示一个[1] 和 16386
其中[1]中的1表示作业号,16386表示执行脚本的进程号。
当该作业完成会有提示:
[1]+ Done ./13-10.sh
以上提示包括作业号 状态 所执行的脚本命令
再执行前台作业时,可以执行Ctrl+Z将当前任务挂起,比如我执行vi 命令编辑一个文件,然后按Ctrl+Z的效果:
eden_ubuntu@edenubuntu:~/Documents/Shell/13$ vi 13-2.sh
[2]+ Stopped vi 13-2.sh
以上提示作业号为2的作业已经被挂起。
使用fd命令,是一个内部命令,将作业从后台移至前台运行
fd [jobspec]
jobsepc用来指定要切换的作业,fd指定切换作业的方法:
方法 | 说明 |
---|---|
%n | n为整数,表示作业号 |
%string | 以string字符串开头的命令所对应的作业 |
%?string | 包含string字符串的命令所对应的作业 |
%+或者%% | 最近提交的作业 |
%- | 倒数第二提交的作业 |
jobs命令查看正在后台执行的作业的列表,基本语法如下:
jobs [options]
eden_ubuntu@edenubuntu:~/Documents/Shell/13$ jobs
[2]- Stopped vi 13-2.sh
[3]+ Stopped vi 13-2.sh
其中[3]旁边的+表示最近的一个作业,[2]旁边的-号表示倒数第二的作业。
作业的状态:
状态 | 说明 |
---|---|
Running | 正在运行 |
Stopped | 被挂起 |
Done | 该作业已完成退出码为0 |
Done(code) | 该作业已正常完成并退出,退出状态码非0,状态码使用10进制表示 |
disown命令用来删除作业列表中的作业
disown [jobsepc]
用法与fd命令一样。
kill 命令可以给进程传递信号。
kill -l命令显示当前系统支持的信号:
eden_ubuntu@edenubuntu:~/Documents/Shell/13$ kill -l
1) SIGHUP 2) SIGINT 3) SIGQUIT 4) SIGILL 5) SIGTRAP
6) SIGABRT 7) SIGBUS 8) SIGFPE 9) SIGKILL 10) SIGUSR1
11) SIGSEGV 12) SIGUSR2 13) SIGPIPE 14) SIGALRM 15) SIGTERM
16) SIGSTKFLT 17) SIGCHLD 18) SIGCONT 19) SIGSTOP 20) SIGTSTP
21) SIGTTIN 22) SIGTTOU 23) SIGURG 24) SIGXCPU 25) SIGXFSZ
26) SIGVTALRM 27) SIGPROF 28) SIGWINCH 29) SIGIO 30) SIGPWR
31) SIGSYS 34) SIGRTMIN 35) SIGRTMIN+1 36) SIGRTMIN+2 37) SIGRTMIN+3
38) SIGRTMIN+4 39) SIGRTMIN+5 40) SIGRTMIN+6 41) SIGRTMIN+7 42) SIGRTMIN+8
43) SIGRTMIN+9 44) SIGRTMIN+10 45) SIGRTMIN+11 46) SIGRTMIN+12 47) SIGRTMIN+13
48) SIGRTMIN+14 49) SIGRTMIN+15 50) SIGRTMAX-14 51) SIGRTMAX-13 52) SIGRTMAX-12
53) SIGRTMAX-11 54) SIGRTMAX-10 55) SIGRTMAX-9 56) SIGRTMAX-8 57) SIGRTMAX-7
58) SIGRTMAX-6 59) SIGRTMAX-5 60) SIGRTMAX-4 61) SIGRTMAX-3 62) SIGRTMAX-2
63) SIGRTMAX-1 64) SIGRTMAX
也可以通过man 7 signal查看信号的帮助手册。
信号 | 值 | 含义 |
---|---|---|
SIGHUP | 1 | 终端挂起或者控制进程终止 |
SIGINT | 2 | 键盘中断 |
SIGQUIT | 3 | 键盘退出键被按下 |
SIGABRT | 6 | 由about(3)发出的退出指令 |
SIGKILL | 9 | 立即结束进程 |
下面表示使用kill命令给进程发信号的命令语法:
kill [-s signal] pid
对于有些信号,进程会由默认的响应动作,而有些信号进程可能会直接忽略。在Shell中用户可以通过trap命令来设定响应某个信号的动作。trap是一个内部命令,语法如下:
trap [[arg] signspec ...]
举例:
- #!/bin/bash
- function signal_handler()
- {
- echo "Good bye"
- }
-
- trap signal_handler 0
在POSIX标准中把0定义为空信号,在程序退出时会触发,该程序的执行结果:
eden_ubuntu@edenubuntu:~/Documents/Shell/13$ ./13-11.sh
Good bye
本篇文章主要说明了父子Shell,内部命令和外部命令,前后台运行,进程与作业以及对它们的控制。