jobs
在后台列出所有正在运行的作业, 给出作业号. 并不象ps命令那么有用.
*作业和进程的概念太容易混淆了. 特定的内建命令, 比如kill, disown,和wait命令即可以接受作业号为参数, 也可以接受进程号为参数. 但是fg,bg和jobs命令就只能接受作业号为参数.
bash$ sleep 100 &
[1] 1384
bash$ jobs
[1]+ Running sleep 100 &
“1”是作业号(作业是被当前shell所维护的),而”1384”是进程号(进程是被系统维护的). 为了kill掉作业/进程,或者使用kill %1或者使用kill 1384. 这两个命令都行.
disown
从shell的激活作业表中删除作业.
fg,bg
fg命令可以把一个在后台运行的作业放到前台来运行. 而bg命令将会重新启动一个挂起的作业,并且在后台运行它. 如果使用fg或者bg命令的时候没有指定作业号, 那么默认将对当前正在运行的作业进行操作.
wait
停止脚本的运行, 直到后台运行的所有作业都结束为止, 或者如果传递了作业号或进程号为参数的话, 那么就直到指定作业结束为止. 返回等待命令的退出状态码.
可以使用wait命令来防止在后台作业没完成(这会产生一个孤儿进程)之前退出脚本.
例:在继续处理之前,等待一个进程的结束.
#!/bin/bash
# wait.sh: 在继续处理之前,等待一个进程的结束.
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'命令执行完成.
#+ 脚本可能在'updatedb'命令还在运行的时候退出,
#+ 这将会导致'updatedb'成为一个孤儿进程.
exit 0
可选的, wait也可以接受一个作业标识符作为参数, 比如, wait%1或者wait $PPID.
在一个脚本中, 使用后台运行命令(&)可能会使这个脚本挂起, 直到敲ENTER, 挂起的脚本才会被恢复. 看起来只有在这个命令的结果需要输出到 stdout 的时候, 这种现象才会出现. 这是个很烦人的现象.
#!/bin/bash
# test.sh
ls -l &
echo "Done."
运行:
bash$ ./test.sh
Done.
bash$ total 1
-rwxr-xr-x 1 liudezhi liudezhi 44 Aug 17 10:31 test.sh
-
只要在后台运行命令的后面加上一个wait命令就会解决这个问题.
#!/bin/bash
# test.sh
ls -l &
echo "Done."
wait
运行:
bash$ ./test.sh
Done.
total 1
-rwxr-xr-x 1 liudezhi liudezhi 44 Aug 17 10:31 test.sh
bash$
suspend
与Control-Z很像,但是它挂起的是这个shell(这个shell的父进程应该在合适的时候重新恢复它).
logout
退出一个已经登录上的shell,也可以指定一个退出状态码.
times
给出执行命令所占用的时间,使用如下形式进行输出:
0m0.020s 0m0.020s
kill
通过发送一个适当的结束信号,来强制结束一个进程.
例:一个结束自身的脚本程序.
#!/bin/bash
# self-destruct.sh
# By Liudezhi 2017/08/17
kill $$ # 脚本将在此处结束自己的进程("$$"就是脚本的PID).
echo "This line will not echo."
# shell将会发送一个"Terminated"消息到"stdout".
exit 0
# sh self-destruct.sh
#+ echo $?
#+ 143
# 143 = 128 + 15
# 结束信号
kill -l 将会列出所有信号. kill -9 是”必杀”命令, 这个命令将会结束顽固的不想被kill掉的进程. 有时候 kill -15 也能干这个活. 一个”僵尸进程”,僵尸进程就是子进程已经结束了, 但是父进程还没kill掉这个子进程, 不能被登陆的用户kill掉 – 因为你不能杀掉一些已经死了的东西 – 但是init进程迟早会把它清除干净.
killall
killall命令将会通过名字来杀掉一个正在运行的进程, 而不是通过进程ID. 如果某个特定的命令有多个实例正在运行, 那么执行一次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”声明的函数, 在它第一次被调用的时候才会被加载. 这样做是为了节省系统资源.
作业标识符:
记法 | 含义 |
---|---|
%N | 作业号 |
%S | 以字符串S开头的被(命令行)调用的作业 |
%?S | 包含字符串S的被(命令行)调用的作业 |
%% | “当前”作业(前台最后结束的作业, 或后台最后启动的作业) |
%+ | “当前”作业(前台最后结束的作业, 或后台最后启动的作业) |
%- | 最后的作业 |
$! | 最后的后台进程 |