1 、 描述shell 程序的运行原理:
Shell是一种具备特殊功能的程序,它提供了用户与内核进行交互操作的一种接口.它接收用户输入的命令,并把它送入内核去执行.内核是Linux系统的心脏,从开机自检时就驻留在计算机的内存中,直到计算机关闭为止,而用户的应用程序存储在计算机的硬盘上,仅当需要时才被调入内存.Shell是一种应用程序,当用户登录Linux系统时,Shell就会被调入内存执行.Shell独立于内核,它是连接内核和应用程序的桥梁,并由输入设备读取命令,再将其转为计算机可以理解的机械码,Linux内核才能执行该命令。
图1-1描述了Shell在Linux系统中的位置
Shell脚本是把命令堆砌在一起,shell通过词法分析,语法分析,语义分析,按顺序、选择或循环执行脚本中的命令。脚本运行结束,此Shell进程也即终止
2 、 Shell 脚本编程总结
变量: 所谓变量就是可变化的量,命名内存空间,本质就是存储数据的一个或多个计算机内存地址。
bash 环境:
本地变量:当前shell进程;
环境变量:当前shell进程及其子进程;
局部变量:某个函数执行过程;
位置参数变量:在脚本中引用传递给脚本的参数;在函数中引用传递给函数的参数;
特殊变量:
$$:当前shell的进程号。对于shell脚本,这是其正在执行时的进程ID
$!:前一个后台命令的进程号
$?:前一个命令执行后的返回值,0表示没有错误,非0表示有错误
$-:当前命令的引导符
$_:上条命令的执行结果
$*:所有参数列表。如"$*"用「"」括起来的情况、以"$1$2 … $n"的形式输 出所有参数。
$@:所有参数列表。如"$@"用「"」括起来的情况、以"$1""$2" … "$n" 的 形式输出所有参数。
$#:传递到脚本的参数数量
$0:正在被执行命令的名字。对于shell脚本而言,这是被激活命令的路径
$1~$n:该变量与脚本被激活时所带的参数相对应。n是正整数,与参数位置 相对应。
示例:编写一个位置参数的position.sh脚本
#!/bin/bash
echo"The script name is : $0" #$0表示脚本本身
echo "Parameter #1: $1"
echo "Parameter #2: $2"
echo "Parameter #3: $3"
echo "Parameter #4: $4"
echo "Parameter #5: $5"
echo "Parameter #6: $6"
echo "Parameter #7: $7"
echo "Parameter #8: $8"
echo "Parameter #9: $9"
echo "Parameter #10: $10"
echo"--------------------"
echo"All the command line parameters are: $*"
#$*和$@一样,表示从$1开始的全部参数
变量类型:
变量类型的作用:存储空间、运算、存储格式
数值,字符;
数值:整数、浮点数;
字符:ASCII
语言对变量类型的支持力度:
强类型:一种总是强制类型定义的语言,要求变量的使用要严格符合定义,所有变量都必须先定义后使用。java、.NET、C++等都是强制类型定义的。也就是说,一旦一个变量被指定了某个数据类型,如果不经过强制转换,那么它就永远是这个数据类型了;
弱类型:与强类型相反。故变量类型不严格区分;
默认存储机制:bash为字符;
bash的变量使用特点:弱类型、无须事先声明;
本地变量:
本地变量命名:
变量名=变量值;
变量名:只能包含数字、字母和下划线;且不能以数字开头;不能超过20个字符;
=:赋值符号;
变量值:我们需要给变量名赋予的值;
注意:在变量、等号和值之间不能出现空格。
引用:
弱引用: ""双引号, 其内部的变量引用会被替换为变量值;
强引用:''单引号,其变量的变量引用会保持原有字符;
命令引用:`COMMAND`反引号, 也可使用$(COMMAND),引用命令的执行结果;
声明为整型:
declare -i name[=value]
let name=value
查看所有本地变量:set命令
变量的生命周期:
创建
销毁:
自动销毁:shell进程终止;
手动销毁:unset name
环境变量:
被“导出”的本地变量
export name[=value]
declare -x name[=value]
查看所有环境变量:env,printenv, export
shell 脚本: 其实就是纯文本文件,我们可以编辑这个档案,然后让这个文本文件来帮我们一次执行多个指令,或者是利用一些运算与逻辑判断来帮我们达成某些功能启动脚本。
(1)bash 脚本名
(2)给脚本一个执行权限即可直接通过脚本路径运行脚本。
# ./PATH/TO/SCRIPT_FILE。
Shell脚本通常是以#!起始的文本文件,如“#!/bin/bash”,这行被称为shebang,指定了解释此脚本shell的路径,执行脚本时系统会调用这个shell来运行此脚本。字符#指明注释的开始。注释部分以#为起始,一直延续到行尾,注释行通常用于为代码提供注释信息,或者用于暂停执行某行代码,会被解释器忽略。
bash的常用选项:
-n: 检查脚本中的语法错误;
-x:调试执行脚本;
当我们需要查看脚本是否执行成功,可以在执行脚本以后可以使用 $? 命令查看上一条命令执行状态结果:
0: 成功
1-255:失败
我们也可在脚本中自定义脚本的状态结果:
在脚本中敲入命令exit [n]:n为我们想要输出的数字
注意:脚本中任何位置执行了exit命令即会终止当前shell进程;
条件测试:
界定程序执行环境;
(1) 根据运行的命令的状态结果;
(2) 测试表达式: EXPR 表达式
test EXPRESSION
[ EXPRESSION ]
` EXPRESSION `
整数测试:隐含着做数值大小比较,所以不要给变量引用加引用;
$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: 是否存在;存在则为“真”,否则为“假”;
-f $file:文件是否存在且为普通文件;
-d $file:文件是否存在且为目录;
-h $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,测试二者是否为同一个文件的硬链接;
特殊设备:
/dev/null: 空,bit buckets,吞下所有数据,并直接丢弃;
/dev/zero:吐出一堆0;
bash之条件判断(选择执行):
if/then ;case
if CONDITION; then
if-true-分支
fi
if CONDITION; then
if-true-分支
else
if-false-分支
fi
! CONDITION: 表示的是取反
脚本参数(位置参数变量):
# ./name.sh /etc/fstab /etc/grub.conf
$0 $1 $2
参数$0—>shell自身文件,$1—>shell中定义的第一个参数,$2—>shell中定义的第二个参数,以此类推。
特殊变量:
$?: 命令的状态结果;
$#: 传递给脚本或函数的参数的个数;
$*和$@: 引用传递给脚本或函数的参数列表;
与用户交互:
read命令:
read [options] VAR...
-p"PROMPT"
-t timeout
示例:-t5 5秒后超时退出交互。
#!/bin/bash
#
read -p "Plz enter ausername: " -t 5 username
if [ -z "$username"]; then
username="myuser"
fi
if id $username &>/dev/null; then
echo "$username exists."
else
useradd $username
fi
命令引用:
`COMMAND`, $(COMMAND)
引用命令的执行结果;
(1)ls `which cat`
(2) lines=$(wc -l /etc/fstab | cut -d'' -f1)
循环语句:循环就是通过循环编程对循环体进行多次运行,直到结果匹配给定的退出循环条件。
Shell中的循环语句:for,while, until
VARIABLE 定义的变量
for VARIABLE in LIST; do
循环体
done
LIST:是由一个或多个空格或换行符分隔开的字符串组成;即可使用LIST 给一个变量进行多次逐个赋值;LIST 不为空时进入循环,LIST逐个赋值直到最后一个结束后循环结束,即退出循环;
for username in user1 user2user3; do
循环体
done
示例:
添加10个用户,user1-user10;
#!/bin/bash
#
for username in user1 user2 user3 user4 user5; do
if id $username &> /dev/null; then
echo "$username exists."
else
useradd $username
echo "Add user $username finished."
fi
done
LIST的生成方法:
(1) 整数列表
(a) {start..end}
(b) $(seq [start `step` end)
(2) 直接给出列表
(3) glob
(4) 命令生成
示例:数值列表
#!/bin/bash
#
for i in {1..10}; do
if id user$i &> /dev/null; then
echo "user$i exists."
else
useradd user$i
echo "Add user user$i finished."
fi
done
示例:glob,即定义参数变量为绝对路径下的文件:
#!/bin/bash
#
for filename in /var/log/*; do
file $filename
done
示例:命令生成列表
#!/bin/bash
#
for username in $(cut -d: -f1/etc/passwd); do
echo "$usernameprimary group: $(id -n -g $username)."
done
Shell脚本中的算术运算:
+, -, *, /, %, **
(1) $[$A+$B]
(2) $(($A+$B))
(3) let VARIABLE=$A+$B
(4) VARIABLE=$(expr $A + $B)
示例:求100以内所以正整数之和;
#!/bin/bash
#
declare -i sum=0
for i in {1..100}; do
sum=$[$sum+$i]
done
echo $sum
增强型赋值:
+=
sum=$[$sum+$i]可写为:letsum+=$i
-=, *=, /=, %=
let count=$[$count+1] --> let count+=1 --> let count++
let count=$[$count-1] --> let count-=1 --> let count--
示例:显示/etc目录下所有普通文件列表,而后统计一共有多少个文件;
测试表达式:
整数测试:-gt,-lt, -ge, -le, -eq, -ne
字符串测试:==,>, 比较命令hostname的结果是否为localhost;
(2) 模式匹配测试:[["STRING" =~ PATTERN ]]
组合测试条件:
条件间逻辑运算:
与:多个条件要同时满足;
或:多个条件满足其一即可;
非:对指定的条件取反;
表达式组合:
与:` CONDITION1 -aCONDITION2 `
或:` CONDITION1 -oCONDITION2 `
非:[ ! CONDITION ]
命令组合:
与:COMMAND1 &&COMMAND2 /dev/null; then
echo "$username is logged."
break
else
let count++
echo "$count $username is not login."
fi
sleep 3
done
#!/bin/bash
#
declare -i count=0
username=$1
if [ $# -lt 1 ]; then
echo "At lease one argument."
exit 1
fi
if ! id $username &> /dev/null; then
echo "No such user."
exit 2
fi
until who | grep "^$username" &> /dev/null; do
let count++
echo "$count $username is not login."
sleep 3
done
echo "$username is logged on."
while循环的特殊用法:
遍历文件的每一行:
while read VARIABLE;do
循环体
done
运维网声明
1、欢迎大家加入本站运维交流群:群②:261659950 群⑤:202807635 群⑦870801961 群⑧679858003
2、本站所有主题由该帖子作者发表,该帖子作者与运维网 享有帖子相关版权
3、所有作品的著作权均归原作者享有,请您和我们一样尊重他人的著作权等合法权益。如果您对作品感到满意,请购买正版
4、禁止制作、复制、发布和传播具有反动、淫秽、色情、暴力、凶杀等内容的信息,一经发现立即删除。若您因此触犯法律,一切后果自负,我们对此不承担任何责任
5、所有资源均系网友上传或者通过网络收集,我们仅提供一个展示、介绍、观摩学习的平台,我们不对其内容的准确性、可靠性、正当性、安全性、合法性等负责,亦不承担任何法律责任
6、所有作品仅供您个人学习、研究或欣赏,不得用于商业或者其他用途,否则,一切后果均由您自己承担,我们对此不承担任何法律责任
7、如涉及侵犯版权等问题,请您及时通知我们,我们将立即采取措施予以解决
8、联系人Email:admin@iyunv.com 网址:www.yunweiku.com