linux shell总结
本文从以下几个方面详细总结bash shell相关内容:
1,shell程序的运行原理
2,shell编程中所涉及到的所有知识点:
书写格式,执行,变量,语法,命令状态
1,shell程序的运行原理;
什么是shell?
sehll是命令语言、命令解释程序及程序设计语言的统称。系统的shell作为操作系统的外壳,为用户提供使用操作系统的接口。其基本功能是解释并执行用户打入的各种命令,实现用户与Linux核心的接口.
如果把Linux内核想象成一个球体的中心,shell就是围绕内核的外层。当从shell或其他程序向Linux传递命令时,内核会做出相应的反应。
shell是一个命令语言解释器,它拥有自己内建的shell命令集,shell也能被系统中其他应用程序所调用。
用户在提示符下输入的命令都由shell先解释然后传给Linux核心。 有一些命令,比如改变工作目录命令cd,是包含在
shell内部的。还有一些命令,例如拷贝命令cp和移动命令rm,是存在于文件系统中某个目录下的单独的程序
shell工作原理:
系统初启后,核心为每个终端用户建立一个进程去执行Shell解释程序。它的执行过程基本上按如下步骤:
(1)读取用户由键盘输入的命令行。
(2)分析命令,以命令名作为文件名,并将其它参数改造为系统调用execve()内部处理所要求的形式。(词法分析: 命令,选项,参数)
(3)终端进程调用fork()建立一个子进程。
(4)终端进程本身用系统调用wait4()来等待子进程完成(如果是后台命令,则不等待)。当子进程运行时调用execve(),子进程根据文件名(即命令名)到目录中查找有关文件(这是命令解释程序构成的文件),将它调入内存,执行这个程序(解释这条命令)。
(5)如果命令末尾有&号(后台命令符号),则终端进程不用系统调用wait4( )等待,立即发提示符,让用户输入下一个命令,转⑴。如果命令末尾没有&号,则终端进程要一直等待,当子进程(即运行命令的进程)完成处理后终止,向父进程(终端进程)报告,此时终端进程醒来,在做必要的判别等工作后,终端进程发提示符,让用户输入新的命令,重复上述处理过程...
另外:
shell的另一个重要特性是它自身就是一个解释型的程序设计语言,shell程序设计语言支持绝大多数在高级语言中能见到的程序元素,如函数、变量、数组和程序控制结构。
当普通用户成功登录,系统将执行一个称为shell的程序。正是shell进程提供了命令行提示符。作为默认值(Linux系统默认的shell是BASH),对普通用户用“$”作提示符,对超级用户(root)用“#”作提示符。 一旦出现了shell提符,就可以键入命令名称及命令所需要的参数。shell将执行这些命令。如果一条命令花费了很长的时间来运行,或者在屏幕上产生了大量的输出,可以从键盘上按ctrl+c发出中断信号来中断它(在正常结束之前,中止它的执行)。 当用户准备结束登录对话进程时,可以键入logout命令、exit命令或文件结束符(EOF)(按ctrl+d实现),结束登录。
bash过程式编程:
顺序执行:逐个执行
选择执行:只执行其中一个分支
循环执行:一段代码要执行0,1或多遍
2、shell编程中所涉及到的所有知识点;
shell所涉及重要知识点,依次介绍脚本:
书写,执行,变量,语法,命令状态,以下详细说明
书写,执行方式:
脚本:文本文件
运行脚本:事实上是运行一个bash进程,此进程负责从脚本文件中读取一个执行逻辑,而后由bash进程负责解析并运行此逻辑;
启动脚本:
(1) # bash /PATH/TO/SCRIPT_FILE
(2) 一个执行权限,
# ./PATH/TO/SCRIPT_FILE
shebang:(#!/bin/bash)解释此脚本的shell路径,shell有多种类型,如:sh,csh,ksh,tcsh,..,bash引用最为广泛。
#!/bin/bash
第一行:顶格给出shebang
单行注释:#
多行注释:
: << 字符 #这里的字符可以是数字或者是字符都可以
语句1
语句2
语句3
语句4
字符
bash的常用选项:
-n: 检查脚本中的语法错误;
-x:调试执行脚本;
示例:
[root@os01 ~]# cat t1.sh #!/bin/bash echo 1 #echo 2 echo 3 echo 4 echo 5 [root@os01 ~]# ./t1.sh #单行注释的2没有输出 1 3 4 5 ~
#多行注释 [root@os01 ~]# cat t1.sh #!/bin/bash echo 1 :<<EOF #多行注释开始 echo 2 echo 3 echo 4 EOF #多行注释结束 echo 5 [root@os01 ~]# bash -n t1.sh [root@os01 ~]# #测试脚本,没有结果证明没有语法错误 [root@os01 ~]# bash -x t1.sh#注释的多行,2,3,4没有输出 + echo 1 1 + : + echo 5 5
变量
变量概念:
可变化的量,命名内存空间 (赋值后保存在内存空间)
bash环境:
本地变量:当前shell进程;
环境变量:当前shell进程及其子进程;
局部变量:某个函数执行过程;
位置参数变量:在脚本中引用传递给脚本的参数;在函数中引用传递给函数的参数;
特殊变量:$?, $*, $@, $#, $$
变量类型:
数值,字符;
数值:
整数
浮点数
字符:
ASCII
比如:120: 字符会识别为1,2,0;数值会识别为:120
变量类型的作用:
存储空间:比如声明变量为数值类型可以节省存储空间
运算:运算必须为数值类型
存储格式
语言对变量类型的支持力度:
强类型:严格区分变量类型
弱类型:变量类型不严格区分;
默认存储机制:bash为字符
bash的变量使用特点:弱类型、无须事先声明;
(1)本地变量
本地变量定义:
name=value
name: 变量名
=:赋值符号
value:值
变量名:只能包含数字、字母和下划线;且不能以数字开头;
引用变量:${name}, $name
示例:
#本地变量定义与使用,只对当前shell生效,logout后,或者在子进程时shell无效。 [root@os01 ~]# test="bird" #变量test赋值为bird [root@os01 ~]# echo "this is a $test" this is a bird#引用变量成功 [root@os01 ~]# set |egrep '\btest\b' #查看本地变量test test=bird [root@os01 ~]# bash#进入子进程(子shell) [root@os01 ~]# echo "this is a $test" this is a #子进程没有继承父进程$test,这里为空 #变量引用注意事项,当变量后直接跟字符串时,需要使用{}让shell能够识别变量名 [root@os01 ~]# test=mage [root@os01 ~]# echo "www.$testedu.com" #shell将$后的testedu识别为变量名,所以为空 www..com [root@os01 ~]# echo "www.${test}edu.com" www.mageedu.com
引用:
弱引用: "", 其内部的变量引用会被替换为变量值;
强引用:'',其变量的变量引用会保持原有字符;
命令引用:`COMMAND`, $(COMMAND),引用命令的执行结果;
示例:
#弱引用替换变量 [root@os01 ~]# echo "$test" bird #强引用保持原有字符 [root@os01 ~]# echo '$test' $test #命令引用:`COMMAND`, $(COMMAND),引用date命令的执行结果; [root@os01 ~]# echo date date [root@os01 ~]# echo `date` Tue 15 Sep 14:34:58 CST 2015 [root@os01 ~]# echo $(date) Tue 15 Sep 14:35:07 CST 2015
声明为整型:
declare -i name[=value]
let name=value
示例:
#声明整数类型 a=5,在没有声明整数类型的情况下b=5其结果一样,这是因为bash为弱类型、无须事先声明,在使用变量的时候会进行隐式转行,b在计算的时候转换为数字5;
[root@os01 ~]# declare -i a=5 [root@os01 ~]# expr $a + 2 7 [root@os01 ~]# b=5 [root@os01 ~]# b=5 [root@os01 ~]# expr $b + 2 7
查看所有变量:set
示例:查看所有本地变量与特定的本地变量
[root@os01 ~]# set|less ABRT_DEBUG_LOG=/dev/null BASH=/bin/bash BASHOPTS=checkwinsize:cmdhist:expand_aliases:extglob:extquote:force_fignore:histappend:interactive_comments:login_shell:progcomp:promptvars:sourcepath BASH_ALIASES=() BASH_ARGC=() .... [root@os01 ~]# set|egrep "\btest\b" test=mage [root@os01 ~]# set|egrep "\b^a\b"
a=5
生命周期:
创建
销毁:
自动销毁:shell进程终止;
手动销毁:unset name
示例:unset手动销毁
[root@os01 ~]# set|egrep "\btest\b" test=mage [root@os01 ~]# unset test [root@os01 ~]# set|egrep "\btest\b" 空
(2)环境变量
环境变量定义:
类似被“导出”的本地变量
export name[=value]
declare -x name[=value]
示例:定义环境变量,在子shell中仍旧生效,但是在logout以及切换用户后失效
[root@os01 ~]# export test=hello [root@os01 ~]# echo $test hello [root@os01 ~]# bash [root@os01 ~]# echo $test hello #子shell内生效 [root@os01 ~]# su - user1 Last login: Tue Sep 15 15:06:13 CST 2015 on pts/1 [user1@os01 ~]$ echo $test 空 #切换用户生效 [user1@os01 ~]$ [root@os01 ~]# exit logout [root@os01 ~]# echo $test 空 #logout后失效 [root@os01 ~]#
查看所有环境变量:
env, printenv, export
示例:查看所有环境变量和test变量内容
[root@os01 ~]# env XDG_SESSION_ID=2736 HOSTNAME=os01 TERM=linux SHELL=/bin/bash ... [root@os01 ~]# printenv XDG_SESSION_ID=2736 HOSTNAME=os01 TERM=linux SHELL=/bin/bash ... [root@os01 ~]# export declare -x HISTCONTROL="ignoredups" declare -x HISTSIZE="1000" declare -x HOME="/root" [root@os01 ~]# env|grep '\<test\>' #查看test系统变量内容 test=hello
销毁:
unset name
示例:销毁test系统环境变量
[root@os01 ~]# export test=hello [root@os01 ~]# echo $test hello [root@os01 ~]# unset test [root@os01 ~]# echo $test 空 [root@os01 ~]#
(3)局部变量
局部变量:某个函数执行过程;只在函数执行过程中生效;
示例:var1,var2变量只在函数执行过程中生效,为局部环境变量
[root@os01 ~]# cat a.sh #!/bin/bash var1="hello" fun_1() { var2="word" echo $var1 $var2 } fun_1 [root@os01 ~]# ./a.sh hello word #var1,var2变量只在函数执行过程中生效,为局部环境变量 [root@os01 ~]# echo $var1 空 [root@os01 ~]# echo $var2 空 #函数体外不生效 [root@os01 ~]#
(4)位置参数变量
位置参数变量:
在脚本中引用传递给脚本的参数;在函数中引用传递给函数的参数;特殊变量:$?, $*, $@, $#, $$
示例:
[root@os01 ~]# cat t.sh #!/bin/bash echo \$0 is $0 显示脚本名 echo \$1 is $1 第一个参数值 echo \$2 is $2 第二个参数值 echo \$3 is $3 第三个参数值 echo \$\* is $* 所有参数值 echo \$\@ is $@ 同上,所有参数值 echo \$\# is $# 参数的个数 echo \$\$ is $$ 这个脚本执行的PID(process id) echo \$\? is $? 执行结果返回状态值 [root@os01 ~]# ./t.sh a b c $0 is ./t.sh 显示脚本名 $1 is a 第一个参数值 $2 is b 第二个参数值 $3 is c 第三个参数值 $* is a b c 所有参数值 $@ is a b c 同上,所有参数值 $# is 3 参数的个数 $$ is 31794 这个脚本执行的PID(process id) $? is 0 执行结果返回状态值
命令状态
命令状态结果:
bash进程用于追踪执行的命令成功与否的状态:
0: 成功
1-255:失败
特殊变量:
$?:上一条命令的执行状态结果;
布尔型:
“真”:成功
“假”:失败
自定义脚本的状态结果:
exit [n]
注意:脚本中任何位置执行了exit命令即会终止当前shell进程;
示例:
#创建目录testdir,查看返回值 [root@os01 ~]# rm -fr testdir/ [root@os01 ~]# mkdir testdir [root@os01 ~]# echo $? 0 #成功返回值为0 [root@os01 ~]# mkdir testdir mkdir: cannot create directory ‘testdir’: File exists [root@os01 ~]# echo $? 1 #失败返回值不为0 #自定义返回值为49 [root@os01 ~]# cat test.sh #!/bin/bash a=hello b=world echo $a $b exit 49 #自定义返回值为49 [root@os01 ~]# ./test.sh hello world [root@os01 ~]# echo $? 49