《学习bash》笔记--进程处理

本文详细介绍了Bash shell中的进程处理,包括进程ID和作业编号、作业控制(前台和后台操作、挂起作业)、信号处理(控制键信号、kill命令、trap和进程ID变量)以及子shell的使用(继承和嵌套)。通过学习,你可以掌握如何在Bash中有效地管理和控制进程。
摘要由CSDN通过智能技术生成

1.进程ID和作业编号

 当通过附加&号后运行命令时,shell会响应如下:

$ ls &
[1] 3318
其中[1]是作业号,3318是进程号。
一个后台进程完成时,shell会给出作业编号信息,如下:
[1]+  Done                    ls --color=auto
如果作业以非0状态退出时,shell指出其退出状态。

2.作业控制

作业编号可以使它们在shell命令中进行作业控制。一旦作业在后台运行,你可以让它一直运行,或把它放到前台,或向其发送信号。

2.1.前台和后台

内置fg命令将后台作业放到前台。使用不带参数的fg,shell会把后台作业放到前台,如果有多个作业在后台,shell会挑出最新在后台
运行作业放到前台。如果想要将其他作业放到前台,需要给出前面加上百分号%的作业命令,或者使用作业编号前面加百分号%,也
可以是不带百分号的进程ID。可以使用命令jobs列出后台作业。
例如:
yanwenjie@ywjpc:~/ctest$ ./a &
[1] 3481
yanwenjie@ywjpc:~/ctest$ ./b &
[2] 3482
yanwenjie@ywjpc:~/ctest$ ./c &
[3] 3483
yanwenjie@ywjpc:~/ctest$ jobs
[1]   Running                 ./a &
[2]-  Running                 ./b &
[3]+  Running                 ./c &
-p选项只列出进程号:
$ jobs -p
3481
3482
3483
如果键入fg,会把c放到前台,因为它是最新在后台运行的作业。
如果键入fg %b,或者fg %2,b会进入前台。
还可以通过%+引用被放到后台的最新作业,通过%-引用下一个最近被放到后台的作业。这边是b。

下面列出了引用后台作业的几种方式:
%N   作业编号N
%string  其命令以string开始的作业
%?string  其命令包含string的作业
%+ 最近被调用的后台作业
%%  同上
%-  第二个最近被调用的后台程序

2.2.挂起一个作业

要挂起一个作业,在其运行时键入ctrl-z即可。shell会相应如下消息:
$ ./a
^Z
[1]+  Stopped                 ./a
然后返回shell提示符,要恢复一个挂机的作业使其继续在前台执行,键入fg即可。如果有多个挂起的作业,可以使用带有一个作
业名或者编号的fg。
yanwenjie@ywjpc:~/ctest$ jobs
[1]   Stopped                 ./a
[2]-  Stopped                 ./b
[3]+  Stopped                 ./c
yanwenjie@ywjpc:~/ctest$ fg %1
./a
如果键入ctrl-z后跟bg,就会把该作业放到后台运行。
yanwenjie@ywjpc:~/ctest$ jobs
[1]   Stopped                 ./a
[2]-  Stopped                 ./b
[3]+  Stopped                 ./c
yanwenjie@ywjpc:~/ctest$ bg %2
[2]- ./b &
yanwenjie@ywjpc:~/ctest$ jobs
[1]-  Stopped                 ./a
[2]   Running                 ./b &
[3]+  Stopped                 ./c

3.信号

3.1.控制键信号

键入ctrl-c时,shell发送INT信号给当前作业,键入ctrl-z时,shell则发送TSTP。也可以向当前作业发送一个QUIT信号,方法是键入
ctrl-\。
可以使用stty命令选项定制发送信号的控制键。这一点随系统的不同而变化,通常的语法是:stty signame char。signame时信号
名,char是控制字符,可通过使用^符号表示控制后跟控制字符给出。例如,要将INT键设置为大多数系统上的ctrl-x,可使用:
stty intr ^x。

3.2.kill

可以使用内置shell命令kill向你创建的任何进程发送一个信号,kill的参数为进程ID,作业编号。
默认情况下,kill发送TERM信号,其效果与使用ctrl-c发送的INT信号一样。
下面是kill的例子。这里有一个a进程,进程号是2680,作业号时1,开始可以使用如下命令:
# ./a &
[1] 2680

# kill %1

[1]+  Terminated              ./a

如果没有看到该消息,TERM信号中断作业失败,下一步再试试QUIT:

kill -QUIT %1

如果工作正常会看到:

[1]+  Quit                    (core dumped) ./a

如果QUIT也不正常运行,自后一种方式是使用KILL:

# kill -KILL %1

[1]+  Killed                  ./a


3.3.trap


trap内置命令使你可以设置为捕获特定信号并以自己的方式处理它们。trap内置命令使你可以在一个shell脚本中完成此功能。
trap的语法是:
trap cmd sig1 sig2 ...
意思是 sig1,sig2等被接收时,运行cmd,然后恢复执行,cmd完成后,脚本在被打断的命令后恢复执行。cmd可以为脚本或者
函数。sigs可用名称或数字指定。
例如:
trap "echo 'you hit ctrl-c'" INT
while true; do
sleep 60
done
执行:
# ./a.sh 
^Cyou hit ctrl-c
^Cyou hit ctrl-c
按下ctrl-c后,脚本不会停止运行,而是sleep命令退出,脚本会循环回来启动另一个sleep。

3.4.进程ID变量

$$是一个特殊shell变量,取值为当前shell的进程ID。
例如如下脚本:
echo $$
while true; do
sleep 10
done
执行结果:
root@ywjpc:/home/yanwenjie/bashtest# ./a.sh &
[1] 3258
root@ywjpc:/home/yanwenjie/bashtest# 3258

3.5.重置陷阱信号

另一个trap命令的特例发生在将短划线指定为命令参数时。它会将收到信号时的行为重置为默认欣慰,通常是进程的终止。
例如a.sh如下所示:
$ cat a.sh 
trap "echo 'ctrl c is received'" INT
i=5
while [ $i -gt 0 ]; do
sleep 5
i=$((i-1))
done
trap - INT
i=5
while [ $i -gt 0 ]; do
        sleep 5
        i=$((i-1))
done
执行脚本:
$ ./a.sh 
^Cctrl c is received
^Cctrl c is received
^Cctrl c is received
^Cctrl c is received
^Cctrl c is received
^C

4.协同程序

例如下面的脚本:
alice &
hatter
此时hatter时脚本中最后一个命令,上述代码只有当alice首先完成时,才能工作正常。如果当脚本完成时,alice仍然运行,那么
它就变成孤儿。
有一种方法可以确保alice完成前脚本不会完成:内置命令wait。不带参数时,wait指示等待,直至所有后台作业完成,因此要确保
上述代码工作正常,加入wait如下:
alice &
hatter
wait
这里,如果hatter先完成, 父shell在结束自己前会等待alice完成。

5.子shell

5.1.子shell继承

关于子shell最关键的一点是它们从其父shell获得或继承了如下特性:
  • 当前目录
  • 环境变量
  • 标准输入,标准输出和标准错误,以及其它任何打开的文件描述符。
  • 被忽略的信号。
子shell未从其父shell继承的内容如下:
  • shell变量
  • 没有被忽略的信号处理

5.2.嵌套子shell

子shell不需要放在单独的脚本中,你也可以在与父shell相同的脚本中启动子shell。可以把某些shell代码放到圆括号中,则该代码
将运行在子shell。我们称之为嵌套子shell。例如:
( while read line; do
    echo $line
done
) | dc
圆括号内代码会运行为一个单独的进程。这通常不如一个命令块效率高。子shell和命令块在功能上的差别很少;它们之间的主要区别
是作用域;亦即在该范围内一些定义是已知的,如shell变量和信号陷阱。首先,嵌套子shell内的代码服从上述子shell继承规则,除此
之外还直到外部shell中定义的变量,块可以看做继承了外部shell的一切内容的代码单元。第二,一个命令块中定义的变量和信号陷阱
对块后的shell代码时已知的,而在子shell中则不是。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值