高级Bash脚本编程指南(21):作业控制命令

高级Bash脚本编程指南(21):作业控制命令

成于坚持,败于止步

在下面的学习作业控制命令的过程中,你会不止一次的碰到一些标识符,这里叫做“作业标识符”,首先列出这是标识符

记法含义
%N作业号[N]
%S以字符串S开头的被(命令行)调用的作业
%?S包含字符串S的被(命令行)调用的作业
%%"当前"作业(前台最后结束的作业, 或后台最后启动的作业)
%+"当前"作业(前台最后结束的作业, 或后台最后启动的作业)
%-最后的作业
$!最后的后台进程

jobs

在后台列出所有正在运行的作业, 给出作业号. 并不象ps命令那么有用.

作业和进程的概念太容易混淆了. 特定的内建命令, 比如kill, disown, 和wait命令,既可以接受作业号为参数, 也可以接受进程号为参数. 但是fg, bg和jobs命令就只能接受作业号为参数.

root@haitao-VirtualBox:~# sleep 100 &
[1] 14884
root@haitao-VirtualBox:~# jobs
[1]+  Running                 sleep 100 &
root@haitao-VirtualBox:~# 

"1"是作业号(作业是被当前shell所维护的), 而"14884"是进程号(进程是被系统维护的). 为了kill掉作业/进程, 或者使用kill %1或者使用kill 1384. 这两个命令都行.

disown

从shell的激活作业表中删除作业.

fg, bg

fg命令可以把一个在后台运行的作业放到前台来运行. 而bg命令将会重新启动一个挂起的作业, 并且在后台运行它. 如果使用fg或者bg命令的时候没有指定作业号, 那么默认将对当前正在运行的作业进行操作.

wait

停止脚本的运行, 直到后台运行的所有作业都结束为止, 或者如果传递了作业号或进程号为参数的话, 那么就直到指定作业结束为止. 返回等待命令的退出状态码.

你可以使用wait命令来防止在后台作业没完成(这会产生一个孤儿进程)之前退出脚本.

在继续处理之前, 等待一个进程的结束的实例

#!/bin/bash

ROOT_UID=0   # 只有$UID为0的用户才拥有root权限.
E_NOTROOT=65
E_NOPARAMS=66

if [ "$UID" -ne "$ROOT_UID" ]
then
  echo "Must be root to run this script."
  # "Run along kid, it's past your bedtime."
  exit $E_NOTROOT
fi

if [ -z "$1" ]
then
  echo "Usage: `basename $0` find-string"
  exit $E_NOPARAMS
fi


echo "Updating 'locate' database..."
echo "This may take a while."
updatedb /usr &     # 必须使用root身份来运行.

wait
# 将不会继续向下运行, 除非'updatedb'命令执行完成.
# 你希望在查找文件名之前更新database.

locate $1

#  如果没有'wait'命令的话, 而且在比较糟的情况下,
#+ 脚本可能在'updatedb'命令还在运行的时候退出,
#+ 这将会导致'updatedb'成为一个孤儿进程.

exit 0
可选的, wait也可以接受一个作业标识符作为参数, 比如, wait%1或者wait $PPID. 

在一个脚本中, 使用后台运行命令(&)可能会使这个脚本挂起, 直到敲ENTER, 挂起的脚本才会被恢复. 看起来只有在这个命令的结果需要输出到stdout的时候, 这种现象才会出现. 这是个很烦人的现象.

#!/bin/bash
# test.sh		

ls -l &
echo "Done."
结果:
root@haitao-VirtualBox:~/test# chmod +x test1.sh 
root@haitao-VirtualBox:~/test# ls
test1.sh
root@haitao-VirtualBox:~/test# ./test1.sh 
Done.
root@haitao-VirtualBox:~/test# total 4
-rwxr-xr-x 1 root root 46 2013-06-17 18:43 test1.sh

root@haitao-VirtualBox:~/test#
看起来只要在后台运行命令的后边加上一个wait命令就会解决这个问题.
#!/bin/bash

# test.sh		



ls -l &

wait

echo "Done."
结果:
root@haitao-VirtualBox:~/test# ./test1.sh 
total 4
-rwxr-xr-x 1 root root 51 2013-06-17 18:44 test1.sh
Done.
root@haitao-VirtualBox:~/test# 
如果将后台运行命令的输出重定向到文件中或/dev/null中, 也能解决这个问题.这里原理其实是一样的

suspend

这个命令的效果与Control-Z很相像, 但是它挂起的是这个shell(这个shell的父进程应该在合适的时候重新恢复它).

logout

退出一个已经登陆上的shell, 也可以指定一个退出状态码.

times

给出执行命令所占用的时间, 使用如下的形式进行输出:

0m0.020s 0m0.020s

这只能给出一个很有限的值, 因为它很少在shell脚本中出现.

kill

通过发送一个适当的结束信号, 来强制结束一个进程

一个结束自身的脚本程序

#!/bin/bash

kill $$ # 脚本将在此处结束自己的进程.

# 回忆一下,"$$"就是脚本的PID.

echo "This line will not echo."

# 而且shell将会发送一个"Terminated"消息到stdout.

exit 0
结果:
root@haitao-VirtualBox:~/test# chmod +x test2.sh 
root@haitao-VirtualBox:~/test# ./test2.sh 
Terminated
root@haitao-VirtualBox:~/

kill -l将会列出所有信号. kill -9是"必杀"命令, 这个命令将会结束顽固的不想被kill掉的进程. 有时候kill -15也能干这个活. 一个"僵尸进程", 僵尸进程就是子进程已经结束了, 但是父进程还没kill掉这个子进程, 不能被登陆的用户kill掉 -- 因为你不能杀掉一些已经死了的东西 -- 但是init进程迟早会把它清除干净.

killall

killall命令将会通过名字来杀掉一个正在运行的进程, 而不是通过进程ID. 如果某个特定的命令有多个实例正在运行, 那么执行一次killall命令就会把这些实例全部杀掉.这里所指的killall命令是在/usr/bin中, 而不是/etc/rc.d/init.d中的killall脚本.

command

对于命令"COMMAND", command COMMAND会直接禁用别名和函数的查找.注意一下Bash执行命令的优先级:

1	别名
2	关键字
3	函数
4	内建命令
5	脚本或可执行程序($PATH)
这是shell用来影响脚本命令处理效果的三个命令之一. 另外两个分别是builtin和enable. (译者注: 当你想运行的命令或函数与内建命令同名时, 由于内建命令比外部命令的优先级高, 而函数比内建命令的优先级高, 所以Bash将总会执行优先级比较高的命令. 这样当你想执行优先级低的命令的时候, 就没有选择的余地了. 这三个命令就是用来为你提供这样的机会. )

builtin

当你使用builtin BUILTIN_COMMAND的时候, 只会调用shell内建命令"BUILTIN_COMMAND", 而暂时禁用同名的函数, 或者是同名的扩展命令.

enable

这个命令或者禁用内建命令或者恢复内建命令. 比如, enable -n kill将禁用内建命令kill, 所以当我们调用kill命令时, 使用的将是/bin/kill外部命令.

-a选项会enable所有作为参数的shell内建命令, 不管它们之前是否被enable了.

 (译者注: 如果不带参数的调用enable -a, 那么会恢复所有内建命令.) -f filename选项将会从适当的编译过的目标文件中, 让enable命令以共享库的形式来加载内建命令.

autoload

这是从ksh中的autoloader命令移植过来的. 一个带有"autoload"声明的函数, 在它第一次被调用的时候才会被加载.这样做是为了节省系统资源.

注意, autoload命令并不是Bash核心安装时候的一部分. 这个命令需要使用命令enable -f来加载(参考上边的enable命令).

先到这里了,O(∩_∩)O~

我的专栏地址:http://blog.csdn.net/column/details/shell-daily-study.html

待续。。。。

  • 1
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值