Shell程序的运行原理
Linux Shell脚本类似于Windows的批处理,但它有着比Windows批处理强大很多的功能。Shell脚本实际上是一个Shell命令的堆叠,再配合上Shell的运算,条件判断,循环结构及逻辑判断等语法,使得Shell脚本程序实现强大的功能。那么Shell脚本是怎么运行的呢? 说到Shell脚本的运行我们就先要说说Shell是什么。我们从字面意思可以看出,Shell是一个壳,它即是操作系统提供给用户的管理操作系统的接口,类似于Windows中的Explorer(图形界面)或者cmd命令提示符工具(命令界面DOS),Shell使用的是一种命令语言,它是一种命令解释器,把用户输入的命令解释后然后送由内核进行处理。Linux中有很多不同的Shell程序,最常用的即bash(Bourne Again shell),它是Bourne shell的扩展,而bash脚本中首行的#! /bin/bash即是为了指明该脚本所使用的解释器,Bash读取脚本中程序逻辑并由Bash解释执行,如果是非Bash内置命令,则从PATH中寻找对应的程序调用执行程序指令。
bash环境下的变量
变量即可变更的量,它是一块指向内存的地址空间,用来存储用户输入的数据或者程序运行过程中产生的数值或者对象
本地变量
在Bash中输入SET命令可以看到所有本地定义的Shell变量,作用域为当前Shell进程
PATH:指定命令的搜索路径
HOME:指定用户的主工作目录(即用户登陆到Linux系统中时,默认的目录)
HISTSIZE:指保存历史命令记录的条数
LOGNAME:指当前用户的登录名
HOSTNAME:指主机的名称,程序通常从这个环境变量中来取得主机名称
SHELL:指当前用户用的是哪种Shell
LANG/LANGUGE:和语言相关的环境变量,使用多种语言的用户可以修改此环境变量
MAIL:指当前用户的邮件存放目录
PS1:命令基本提示符,对于root用户是#,对于普通用户是$
PS2:附属提示符,默认是“>”
位置参数变量
在脚本中用于引用传递给脚本的参数;在函数中引用传递给函数的参数,$1-$9表示第1到第9个位置参数,如果第10个则使用${10}
局部变量
由用户在程序中定义,作用于函数的执行过程
特殊变量
$? 上一次执行的状态码
$0 脚本本身的名字
$# 脚本参数个数
$* 所有的位置参数列表,相当于"$1 $2 $3" 一个字符串,见下面示例程序
$@ 所有的位置参数列表,相当于"$1" "$2" "$3"三个字符串,见下面示例程序
$$ 脚本运行的进程ID
示例程序:
#!/bin/bash echo $# echo $0 echo $* echo $@ echo $$ for key in $* #try to take out each element do echo $key done for key2 in "$*" do echo $key2 done for key3 in $@ do echo $key3 done for key4 in "$@" do echo $key4 done执行结果:
[root@localhost ~]# bash values.sh 3 2 1 3 values.sh 3 2 1 3 2 1 3700 ----values in $* without Quotation Marks----- 3 2 1 ----values in $* with Quotation Marks----- 3 2 1 ----values in $@ without Quotation Marks----- 3 2 1 ----values in $@ with Quotation Marks----- 3 2 1
变量的赋值
name=value
name :变量名,只能包含数字、字母和下划线;且不能以数字开头;
=:赋值符号
value:值
引用变量:$name ,${name}, "$name"在程序中将替换为变量值,当引用变量后紧跟其它字符时,需使用后两种方式以防止变量名称歧义。使用‘‘时不会对变量进行替换操作而直接显示’’中的原有字符。
如果要引用命令的执行结果,可使用${command}或者使用反单引号`command`
declare命令
declare命令用于显示和声明shell变量,当不提供变量名参数时显示所有shell变量,其用法如下:
+/-:"-"可用来指定变量的属性,"+"则是取消变量所设的属性
-f:仅显示函数
-r:将变量设置为只读,相当于命令readonly variable_name
-x:指定的变量会成为环境变量
-i:声明为整型数值,或者使用let name=value设置变量为整型,然后使用let进行算数运算
后跟name=value即可定义变量并赋值
定义环境变量
export name=[value] 导出变量为环境变量并赋值
declare –x name=[value] 同export效果
变量的撤销
变量从创建开始生效到Shell进程结束终止,如果需要撤消变量,则需要使用unset命令撤消变量
unset variable_name unset命令无法删除readonly属性的变量,readonly变量只有当Shell进程结束后才会撤消
脚本执行方式
./PATH/TO/SCRIPT_FILE
bash /PATH/TO/SCRIPT_FILE
bash –x /PATH/TO/SCRIPT_FILE 调试执行脚本,显示详细执行过程
bash –n /PATH/TO/SCRIPT_FILE 检查脚本语法错误
命令状态结果
$? : 上一条命令的执行状态结果
0: 成功
1-255:失败
布尔型: true : 成功 false :失败
自定义状态结果:
exit [n] 表示结束脚本程序并返回状态结果n
程序示例:
#!/bin/bash echo hello echo $? dirr &> /dev/null #a wrong command echo $? mkdir -qw test &> /dev/null #command with wrong options echo $? exit 5 echo $? #因程序退出此命令不会被执行结果:
[root@localhost ~]# bash return.sh hello 0 127 #return value of unknow command 1 #return value of command with wrong option [root@localhost ~]# echo $? #显示脚本运行返回的结果 5
条件测试
Linux中的条件测试主要用于判断某种条件是否存在
(1) 根据运行的命令的状态结果
(2) 测试表达式
test EXPRESSION
[ EXPRESSION ]
[[ EXPRESSION ]]
条件EXPRESSION是一个表达式,该表达式可为数字、字符串、文本和文件属性的比较,同时可同时加入各种算术、字符串、文本等运算符;‘[‘属于bash内置命令,相当于test ,所以‘[‘和测试语句中间必须要有空格,与其成对出现的 ‘]‘ 前也必须要有空格,[会把其后的比较表达式或文件测试当作参数来执行,并返回对应的比较结果(0表示true,1表示false);‘[[‘不属于bash内置命令,和if、for等一样属于bash关键字,双方括号是单方括号的扩展;因逻辑运算和字符测试在单括号中会出现错误的结果,建议使用双括号;
[root@gxd ~]# type [ [ is a shell builtin [root@gxd ~]# type for for is a shell keyword [root@gxd ~]# type [[ [[ is a shell keyword
[root@gxd ~]# [ abc < def ] [root@gxd ~]# echo $? 0 [root@gxd ~]# [ abc > def ] [root@gxd ~]# echo $? 0 #返回值错误,依旧是0 [root@gxd ~]# [[ abc < def ]] [root@gxd ~]# echo $? 0 [root@gxd ~]# [[ abc > def ]] [root@gxd ~]# echo $? 1 #返回值正确
整数测试:隐含着做数值大小比较,所以不要给变量引用加引用;
$A -gt $B:大于
$A -ge $B: 大于等于
$A -lt $B:小于
$A -le $B: 小于等于
$A -eq $B: 等于
$A -ne $B:不等于
字符串测试:按照字符的ASCII码大小进行比较
"$A" > "$B":大于
"$A" < "$B":小于
"$A" == "$B":等于
"$A" != "$B":不等于
-z "$A":是否为空;空则为“真”,否则为“假”
-n "$A":是否不空;不空则“真”,空则为“假”
=~ : 模式匹配,右边字符是否匹配左边的正则模式
注意:须使用[[ EXPRESSION ]]
文件测试:测试文件的存在性以及属性;
-e $file: 是否存在;存在则为“真”,否则为“假”
-a $file: 同上
-f $file:文件是否存在且为普通文件
-d $file:文件是否存在且为目录
-h $file:是否存在且为符号链接文件
-L $file: 同上
-b $file:是否存在且为块设备文件
-c $file:是否存在且为字符设备文件
-S $file:是否存在且为套接字文件
-p $file: 是否存在且为管道文件
-r $file: 当前用户对文件是否拥有读权限
-w $file:当前用户对文件是否拥有写权限
-x $file:当前用户对文件是否拥有执行权限
-u $file:文件是否拥有SUID权限
-g $file:文件是否拥有SGID权限
-k $file:文件是否拥有sticky权限
-O $file: 当前用户是否为指定文件的属主
-G $file: 当前用户是否为指定文件的属组
双目操作符:
$file1 -nt $file2: file1是否新于file2, file1的最近一次的修改时间戳是否晚于file2的
$file1 -ot $file2: file1是否旧于file2, file1的最近一次的修改时间戳是否早于file2的
$file1 -ef $file2:file1与file2是否指向了同一个inode;测试二者是否为同一个文件的硬链接
END
原文地址:http://hubla.blog.51cto.com/1093504/1697951