1.定义:利用shell的功能编写的'程序',将一些shell的语法与命令写在里面,与正则表达式,管道,重导向一起实现我们目的;
2.特点:shell脚本提供了数组,循环,条件,逻辑判断等功能,可以被看做批处理文件;
由于利用shell与相关的工具命令,故不需编译,即可执行,且其有不错的调试工具;
3.优点:自动化管理的重要依据; 追踪与管理系统的重要工具;
简单的入侵检查功能; 连续命令单一化;
简单的数据处理; 跨平台支持与缩短学习历程;
缺点:由于利用shell与相关的工具命令,需常常调用外部函数库,故运算速度不比传统的程序语言;
适合系统的管理,但不适合处理大量的数值运算,其占用资源多;
注: bash shell 里头预设仅支持到整数的数据
4.脚本编写要点:
1.第一行用#!name指明当前脚本使用的shell名称,以便在执行程序时加载name shell的相关环境设置文件,如#!/bin/bash
2.接下来注释出:内容与功能,创建日期,作者与联系方式,版本信息,历史记录;
3.主要环境变量的设置,如PATH;
4.写程序内容;
5.告知程序结果,如,exit 0表示离开脚本时给系统回传一个0;
5.脚本的执行:
1.给脚本添加x属性,用./file执行;
2.sh [op] file:不用x属性,直接执行file;
3.. file:不同与上面两种执行,该点命令不创建新的环境(子shell)来执行脚本,故file文件中对环境的改变(如环境变量)将会实际改变当前的SHELL环境;
6.脚本的调试:
sh [op] filename
-n:不执行脚本,仅查询语法问题;
-v:先将脚本内容输出到屏幕上,再执行脚本;
-x:输出整个执行过程; -----> 好;
7.脚本调用另一个脚本:
直接使用另一个脚本的名字即可;
注:脚本相当于一个函数,只有环境变量才相当于全局变量,其他变量都相当于函数中的局部变量;
7.判断命令:(如果使用的是bash,则test为内置的命令,可在命令行直接使用)
1.test:判断结果为true($?==0)或false($?!=0),可通过$?判断;
*文件名的类型检查,如,test -e filename
-e:文件名是否存在; -f:文件名是否为文件; -d:文件名是否为目录;
-b:文件名是否为块设备; -c:文件名是否为字符设备; -S:文件名是否为套接字文件;
-p:文件名是否为管道文件; -L:文件名是否为连接文件;
*文件的权限检测,如,test -r filename;
-r:文件名是否为可读; -w:文件名是否为可写; -x:文件名是否为可执行;
-u:文件名是否为SUID; -g:文件名是否为SGID; -k:文件名是否为Sticky Bit;
-s:文件名是否为非空白文件;
*比较两个文件,test file1 -nt file2;
-nt:判断file1是否比file2新;
-ot:判断file1是否比file2旧;
-ef:判断file1是否与file2为同一文件,可用于判断硬链接,是否同时指向一个inode;
*比较两个表达式,如,test n1 -eq n2
-eq:两数相等; -ne:两数不等; -gt:>;
-lt:<(less than); -ge:>=; -le:<=;
*判断字符串:
test -z string:判断字符串是否为空;
test -n string:判断字符串是否为非空;
test string1 = string2:判断两字符串是否相等;
test string1 != string2:判断两字符串是否不相等;
*多重条件判定:test -r filename -a -x filename
-a: 表示且的关系
-o: 表示或的关系
!: 反相状态, 如test ! -e file1 && echo "the file not exit!" && exit 0;
更多内容见鸟.16.3.1
2.[]: 判断符号,它的很多参数同test,常用在if..then..fi的情况中;
[]内的各组件要用空格来分隔;
[]内的变量最好用双引号,如[ $a = "wo"],若$a变量为空,则变成[ = "wo"],则会出问题
[]内的常量最好用双引号或单引号;
如,[ -z "$HOME" ],[ "$name" == "vbird" ],[ "$name" != "vbird" ];
8.条件判断语句:
*&&,||
如,test -e tmp && echo "exit" || echo "no exit"
test ! -e tmp && echo "no exit" && exit 0
*if [条件判断式一]; then (若将then放在下一行,则不需要分号)
可执行的命令.
elif [条件判断式二]; then
可执行的命令.
else
可执行的命令;
fi
注:条件判断式中,多个条件要用多个[],[]之间则以&&或||隔开;
if/elif与[]之间要有空格;
更详细例子见文件sh07.sh;
*case $varname in
"...")
程序段
;;
"...")
程序段
;;
*)
程序段
exit 1
;;
esac
注: 多个"..."之间可用|分割,如"..." | "..."
9.循环语句:
*while [ condition ]
do
....
done:当condition成立时,就一直循环;
-------
until [ condition ]
do
....
done:当condition不成立时,就一直循环;
-------
注:如变量不声明为整数,在加减时可以:i=$(($i+1))
注意while和until后面的空格;
true可直接表示真;
0也表示真,但不能直接使用0表示真;
详细例子见文件sh11.sh;
*for ((初始值; 限制值; 执行步长))
do
...
done
注:for中设置的变量默认即为整型值(自认为),所以可以直接运算i=i+1;
详细例子见文件sh14.sh;
-------------
for var in con1 con2 con3..
do
...
done
注:for中设置的变量var,每循环一次取一次con1..中的值,即第一次var="con1"
详细例子见文件sh12.sh, sh13.sh, sh15.sh;
10.函数功能:
function myFunName()
{
local var="varValue" #声明一个局部变量
...
return 0/return 1 #返回值
}
注:
前面的function关键字可有可无!
函数拥有内置变量,同shell类似,$0表函数名,$1表示第一个参数.....如:myfun 100,$0为myfun,$1为100;
函数的调用直接使用函数名字myFunName;
若没声明函数返回值,则函数返回的就是执行最后一条命令的退出码。
11.shell的参数变量:
* $0,$1...
使用$0可显示执行的文件名,利用好其他命令可以简单第立即执行某些命令;
如: sh sh06.sh ls cp ...
$0 $1 $2 ...
更详细例子见文件sh06.sh,用sh sh07.sh ls执行;
$*:该变量列出传入shell脚本的所有参数,且其使用IFS环境变量的第一个字符作为传入参数的分隔符;
$@:同$*变量作用相同,但与IFS环境变量无关;
注:上面变量的详细使用见<<linux程序设计>>p25;
12.内置命令:shell定义的命令,不能被外部调用
break/continue/
.(如. ./myScript---点命令相当于C语言里面的#include命令,使被执行的脚本在当前shlell环境中执行,而不是建立子shell执行,从而改变当前环境设置)
12.脚本编写技巧:
*数值运算:
(1)num为整数: result=num1*num2
(2)num为字符串:result=$(($num1*$num2))----方便!
注:$((...))相当于expr ...命令,将它的参数作为一个表达式来求值,支持+/-/*///%/=/>/>=/../!=等,详见<<linux程序设计2.6.5.10>>
*sh 显示SHELL版本信息;
*/bin/sh -version:显示当前sh的版本信息;(/bin/sh是对/bin/bash的一个链接);
*/bin/shell名:即可改到用另一个shell(/bin/shells文件保存着当前版本所支持的shell类型);
*shell中的变量不需要提前申明,且所有变量默认看做字符串类型存储,shell中的一些工具会在需要时将字符串转化为对应的数值对其进行操作。
*变量在被读取是,前面需加$,在赋值时不需要。
*等号两边不能有空格。条件判断或控制语句的参数部分都需要空格分割。
*$(())用于算数计算,$()用于命令的执行和获取输出,如the current directory is $(who)