Shell 脚本(即 Shell Script),Shell 脚本类似于 Windows/Dos 下的批处理,也就是将所需的各类命令预先放入到一个文件中,方便一次性执行的一个程序文件,主要应用在 Linux 系统运维上,方便管理员进行设置或者管理用的。但是它比 Windows 下的批处理更强大,比用其他编程语言编写的程序效率更高。由于它使用了 Linux/Unix 下的命令,因此想编写满足功能需求的 Shell 脚本,需要了解各种 Linux/Unix 命令,如 grep、sed、awk 等等。
Shell 脚本的第一行
一般来说,Shell 脚本的第一行用于指定执行该脚本的解释器,如:
#!/bin/bash
“#!”符号读作“Sha-bang”,是 Shell 脚本的起始符号,后面紧跟解释器的路径,这里是 /bin/bash,此外我们还可能看到 /bin/sh、/bin/python 等等。
Shell 脚本的变量
我们在 Shell 脚本中经常会遇到 $#
、$*
、$$
、$@
、$0
、$1
、$2
、$?
等形式的符号,要是不清楚其含义,就很容易懵逼,所以有必要记住以下这些规则。
$# —— 表示执行脚本传入参数的个数
$* —— 表示执行脚本传入参数列表
$$ —— 表示进程id
$@ —— 表示执行脚本传入所有参数
$0 —— 表示执行脚本名称
$1 —— 表示第一个参数
$2 —— 表示第二个参数
$? —— 表示脚本执行状态0正常,其他表示有错误
Shell 脚本中可以加入延时
在 Shell 脚本中经常需要做一些延时处理,那么延时需要用到系统的 sleep 或 usleep。
sleep : 默认以秒(s)为单位
usleep : 默认以微秒(us)为单位【 1s = 1000ms = 1000000us 】
此外,sleep 不仅可以用秒为单位,还可以指定延迟的单位,例如:
sleep 1s 表示延迟一秒
sleep 1m 表示延迟一分钟
sleep 1h 表示延迟一小时
sleep 1d 表示延迟一天
值得一提的是,使用 sleep 或 usleep 进行延时是会阻塞的,假如我们在一个 Shell 脚本(姑且称为父脚本)中调用了另一个 Shell 脚本(子脚本),而子脚本恰好使用了延时,那么父脚本也会阻塞。如果这不是你想要的效果,请往下看(合理地使用 &)。
Shell 脚本的执行流程
Shell 是单线程顺序执行的,要想实现“多线程”可以通过在后台运行多进程的方式来实现。在 bash 中,使用后台任务来实现任务的“多进程化”。在不加控制的模式下,不管有多少任务,全部都后台执行。也就是说,在这种情况下,有多少任务就有多少“进程”在同时执行。
举个栗子:
# !/bin/bash
for ((i = 0 ;i < 5 ;i ++ )); do
{
sleep 3 ;echo 1 >> aa && echo " done! "
}
done
wait
cat aa | wc - l
rm aa
上面这种情况下,程序顺序执行,每个循环3s,共需15s左右。输出结果如下:
$ time bash test . sh
done !
done !
done !
done !
done !
5
real 0m15 . 030s
user 0m0 . 002s
sys 0m0 . 003s
进行“多进程化”改造:
# !/bin/bash
for ((i = 0 ;i < 5 ;i ++ )); do
{
sleep 3 ;echo 1 >> aa && echo " done! "
} &
done
wait
cat aa | wc - l
rm aa
这个改造实际上就在上面基础上多加了一个后台执行 & 符号,此时应该是5个循环任务并发执行,最后需要3s左右时间。输出结果如下:
$ time bash test . sh
done !
done !
done !
done !
done !
5
real 0m3 . 011s
user 0m0 . 002s
sys 0m0 . 004s
这里顺便说一下 wait 的作用。wait 是等待前面的后台任务全部完成才往下执行,否则程序本身是不会等待的,这样对后面依赖前面任务结果的命令来说就可能出错。例如上面 wc -l
的命令就报错:不存在 aa 这个文件。
案例:Shell 脚本找出某个进程并将其 kill
【test.sh】
#!/bin/bash
NAME=$1
PID=`ps -ef | grep "$NAME" | grep -v "$0" | grep -v "grep" | awk '{print $1}'`
echo $PID
for id in $PID
do
kill -9 $id
echo "killed $id"
done
测试:为该 Shell 脚本设置执行权限,chmod a+x test.sh
,执行 ./test.sh 进程名
即可。