分类: LINUX
2009-12-11 15:19:05
0、脚本的执行过程:
./test.sh arg1,操作系统先读取./test.sh文件的首行(#!/bin/sh)得到脚本解释器可执行文件的绝对路径,然后运行该解释器程序,并把该脚本的
文件名和输入的参数传递给该解释器,所以上面脚本的执行相当于:/bin/sh ./test.sh arg1。这种执行过程的方法适用于包括shell/awk/python/perl
/expect等脚本语言。
1、变量
*变量定义:VAR=value,${VAR:=value},变量默认为全局变量,如果加上local则为局部变量,未初始化的变量的初值为空字符串
*变量引用:$VAR,${VAR}
*本地变量:脚本中默认定义的变量都是本地变量,本地变量不能想子脚本进行传递。通过export变成环境变量。
*环境变量:可以被所有的包括新创建的子进程引用到,包括:系统环境变量和export 的变量。
*特殊变量:
命令行参数:$0脚本名称,$1/2/3...分别表示输入的各个参数,shit后则sn==sn+1,$#参数个数,
其他特殊变量:$?上一命令的执行结果,$$当前进程的pid,
其他说明:
1. 变量与变量内容以等号『=』来连结;
2. 等号两边不能直接接空格符;
3. 变量名称只能是英文字母与数字,但是数字不能是开头字符;
4. 若有空格符可以使用双引号 " 或单引号 ' ,来将变量内容结合起来。
5. 必要时需要以跳脱字符『 \ 』来将特殊符号 ( 如 Enter, $, \, 空格符, ' 等 ) 变成一般符号;
6. 在一串指令中,还需要藉由其它的指令提供的信息,可以使用 quote 『 ` command` 』;(那个 ` 是键盘上方的数字键 1 左边那个按键,而不是单引号!)
7. 若该变量为扩增变量内容时, 则需以双引号及 $变量名称 如: "$PATH":/home』继续累加内容;
8. 若该变量需要在其它子程序执行, 则需要以 export 来使变量变成环境变量, 如export PATH
9. 通常大写字符为系统预设变量,自行设定变量可以使用小写字符,方便判断。
10. 取消变量的方法为:『unset 变量名称』。
2、函数
function fname() { //一定要定义在最前面
程序段
}
*书写函数定义的时候不需要写参数列表,参数列表都为()
*函数调用方式:fname, fname "$a" "$b" "$c"
*函数局部变量用local修饰,
*函数返回格式:return n;
*函数参数:$1,$2,$3...表示函数的第1/2/3...个参数
3、流程控制
1)条件,分支
if [条件判断] &&/|| [..]: then if [条件判断] &&/|| [..]: then if [条件判断] &&/|| [..]: then
fi else elif [ 条件判断式二 ]; then
fi else
fi
case $变量名称 in
"第一个变量内容")
程序段
;;
"第二个变量内容")
程序段
;;
*)
不包含第一个变量内容与第二个变量内容的其它程序执行段
exit 1
;;
esac
2)循环
while [ condition ] until [ condition ] for (( 初始值; 限制值; 执行步阶 )) for var in con1 con2 con3 ...
do do do do
程序段落 程序段落 程序段落 程序段落
done done done done
4、shell内置命令:
内置命令和外部命令不同,外部命令是可以在文件系统的目录下找到可执行文件的,但内置命令则是有bash解释器内部支持的。
常用的内部命令有:echo, eval, exec, export, readonly, read, shift, wait和点(.)。
可以通过:type -tpa [command name] 显示一命令是外部指令还是 bash 内建的指令。
;可以作为两条在一行执行指令的间隔符号
5、常用工具:
echo
[]/test
sed
awk
tee
basename
dirname
4、调试选项
~]# sh [-nvx] scripts.sh
参数:
-n :不要执行 script,仅查询语法的问题;
-v :再执行 sccript 前,先将 scripts 的内容输出到屏幕上;
-x :将使用到的 script 内容显示到屏幕上,这是很有用的参数!
set命令用来打开脚本中的选项. 你可以在脚本中任何你想让选项生效的地方插入set -option
-C noclobber 防止重定向时覆盖文件(可能会被>|覆盖)
-D (none) 列出用双引号引用起来的, 以$为前缀的字符串, 但是不执行脚本中的命令
-a allexport export(导出)所有定义过的变量
-b notify 当后台运行的作业终止时, 给出通知(脚本中并不常见)
-c ... (none) 从...中读取命令
-e errexit 当脚本发生第一个错误时, 就退出脚本, 换种说法就是, 当一个命令返回非零值时, 就退出脚本(除了until或while loops, if-tests, list constructs)
-f noglob 禁用文件名扩展(就是禁用globbing)
-i interactive 让脚本以交互模式运行
-n noexec 从脚本中读取命令, 但是不执行它们(做语法检查)
-o Option-Name (none) 调用Option-Name选项
-o posix POSIX 修改Bash或被调用脚本的行为, 使其符合POSIX标准.
-p privileged 以"suid"身份来运行脚本(小心!)
-r restricted 以受限模式来运行脚本(参考 21).
-s stdin 从stdin中读取命令
-t (none) 执行完第一个命令之后, 就退出
-u nounset 如果尝试使用了未定义的变量, 就会输出一个错误消息, 然后强制退出
-v verbose 在执行每个命令之前, 把每个命令打印到stdout上
-x xtrace 与-v选项类似, 但是会打印完整命令
- (none) 选项结束标志. 后面的参数为位置参数.
-- (none) unset(释放)位置参数. 如果指定了参数列表(-- arg1 arg2), 那么位置参数将会依次设置到参数列表中.
5、判断的标志,应用在test指令或者[]判断中
用来判断一个档是否存在,类型,权限,两个档之间的比较,两个整数之间的比较,字符串之间的判定,多重判断,用的非常广泛
测试的标志 代表意义
1. 关于某个档名的『类型』侦测(存在与否),如 test -e filename
-e 该『档名』是否存在?(常用)
-f 该『档名』是否为档案(file)?(常用)
-d 该『文件名』是否为目录(directory)?(常用)
-b 该『文件名』是否为一个 block device 装置?
-c 该『文件名』是否为一个 character device 装置?
-S 该『档名』是否为一个 Socket 档案?
-p 该『档名』是否为一个 FIFO (pipe) 档案?
-L 该『档名』是否为一个连结档?
2. 关于档案的权限侦测,如 test -r filename
-r 侦测该文件名是否具有『可读』的属性?
-w 侦测该档名是否具有『可写』的属性?
-x 侦测该档名是否具有『可执行』的属性?
-u 侦测该文件名是否具有『SUID』的属性?
-g 侦测该文件名是否具有『SGID』的属性?
-k 侦测该文件名是否具有『Sticky bit』的属性?
-s 侦测该档名是否为『非空白档案』?
3. 两个档案之间的比较,如: test file1 -nt file2
-nt (newer than)判断 file1 是否比 file2 新
-ot (older than)判断 file1 是否比 file2 旧
判断 file2 与 file2 是否为同一档案,可用在判断 hard link 的
-ef
判定上。 主要意义在判定,两个档案是否均指向同一个 inode 哩!
4. 关于两个整数之间的判定,例如 test n1 -eq n2
-eq 两数值相等 (equal)
-ne 两数值不等 (not equal)
-gt n1 大于 n2 (greater than)
-lt n1 小于 n2 (less than)
-ge n1 大于等于 n2 (greater than or equal)
-le n1 小于等于 n2 (less than or equal)
5. 判定字符串的数据
test -z string 判定字符串是否为 0 ?若 string 为空字符串,则为 true
判定字符串是否非为 0 ?若 string 为空字符串,则为 false。
test -n string
注: -n 亦可省略
test str1 = str2 判定 str1 是否等于 str2 ,若相等,则回传 true
test str1 != str2 判定 str1 是否不等于 str2 ,若相等,则回传 false
6. 多重条件判定,例如: test -r filename -a -x filename
(and)两状况同时成立!例如 test -r file -a -x file,则 file 同
-a
时具有 r 与 x 权限时,才回传 true。
(or)两状况任何一个成立!例如 test -r file -o -x file,则 file
-o
具有 r 或 x 权限时,就可回传 true。
! 反相状态,如 test ! -x file ,当 file 不具有 x 时,回传 true
5、其他
1)匹配:
shell支持简单形式的模式匹配,比如:
*表示匹配零或者多个字符
?仅仅匹配1个字符
举例:
cp test[1-5] /tmp //将 test1/2/3/4/5 若存在的话,就拷贝到 /tmp
cp test[!1-5] //和上面相反的意思
cp test[15] //只拷贝test1/test5
2)引号:
但须要特别留意, 双引号内的特殊字符可以保有变量特性,但是单引号内的特殊字符则仅为一般字符;
3)I/O重定向:
<&digit
Use file descriptor digit as standard input.
>&digit
Use file descriptor digit as standard output.
>:先清空在填输出结果
>>:直接在后面追加当前的执行结果
cmd 2>errorfile:表示将当前指令执行的错误输出进行重导向
cmd > filename 2>&1:首先将标准输出重定位到filename,然后标准错误输出定义到标准输出上。
因为标准输出已经在前面定位到了filename上,所以这行语句相当于把标准输出和标准错误输出都重定位到filename上
cmd > /dev/null 2>&1:相当于直接标准输出和标准错误输出扔到回收站一样,即不显示任何输出。
4)shell环境设定
*login shell是在用户第一次用于登录使用的那个shell
non-login shell不是用于登录用的,可能是用户在后来重新开启任务用到的新的shell
所有的X-windows下面的终端都是non-login shell
login 与 non-login shell的最大区别是读取的设定文件不同,non-login shell只会去读区~/.bashrc文件
*系统环境设定文件:
/etc/sysconfig/i18n:
/etc/profile:『PATH、USER、MAIL、 HOSTNAME、HISTSIZE、umask』
/etc/bashrc
/etc/profile.d/*.sh
/etc/man.config
*个人环境设定文件:
~/.bash_profile, ~/.bash_login, ~/.profile 只在登录shell时读一此且只会读一个,按照这个顺序读到一个就行
~/.bashrc每次执行 shell script 的时候都会被重新使用一遍
~/.bash_history每次登录的时候都会读取到内存中
~/.bash_logout: logout后希望系统要作的事情
*各类设定文件的读取顺序:
/etc/profile->[内部调用的/etc/profile.d 与 /etc/inputrc 等]->[~/.bash_profile, ~/.bash_login, ~/.profile]
->~/.bashrc 最后调用
参考资料:
初学参考:《Learning.the.bash.Shell.3rd.chm》
深入参考:《advance bash script guide.pdf》
快速参考:《man bash》