过程式编程:以指令为中心,数据服务于指令,用户编程时,关注的是指令的本身,第一步,第二步都分别做的什么
对象式编程:以数据为中心,指令服务于指令,用户编程时,关注的则是数据的结果,不注重指令的执行过程,适合处理大型
项目
shell程序:将命令按照逻辑关系顺序的写入到脚本中
计算机:运行二进制指令
编程语言:
低级:汇编
高级:
编译:高级语言-->编译器-->目标代码 (将字符串转换成二进制文件执行,转换过程利用编译器)
java,C#...
解释:高级语言-->解释器-->机器代码 (不需要生成二进制文件,输入字符串,后台会将字符串转换为二进制机器码,生成在内存中)
shell,perl,python...
编程基本概念:
顺序执行 (比如:写一个指令,两个指令,就会按照顺序执行)
循环执行 (比如:创建100个账号,就是把创建账号的指令执行100次,就可以使用循环执行)
选择执行 (比如:当满足某一个条件执行一个指令,当不满足一个指令满足别的条件的时候执行另外一个指令)
shell编程:
各种系统命令的组合
数据存储:变量,数组
表达式: a + b
语句:if
shell脚本:适合于大批量的重复工作
包含一些命令或声明,并要符合一定的格式的文本文件
格式要求:首行shebang机制(#!shell类型)如下
#!/bin/bash
#!/usr/bin/python
#!/usr/bin/perl
shell脚本用途:
自动化常用命令
执行系统管理和故障排除
创建简单的应用程序
处理文本或文件
创建shell脚本:
第一步:使用编辑器来创建文本文件
脚本一般都设为".sh"后缀
第一行必须包括shell声明序列:#!也就是shebang机制
#!/bin/bash
添加注释:(可以理解为脚本的一些介绍,用处)注释是以"#"开头,建议使用以下注释内容
#!/bin/bash
#-------------------------------
#Filename: "脚本名称"
#Revision: "脚本版本"
#Date: "创建日期"
#Author: "作者"
#Email: "邮箱"
#Description: "脚本描述"
#-------------------------------
第二步:运行脚本
赋予脚本执行权限chmod +x "脚本名"
脚本基本结构:
#!SHEBANG (shebang机制)
CONFIGURATION_VARIABLES (变量)
FUNCTION_DEFINITIONS (函数)
MAIN_CODE (其他指令)
脚本例子:
显示当前主机的各个配置信息
vim hostinfo.sh
#!/bin/bash
#Author: Fang
#Date: 2017-11-23
#Description: show system info
echo "This is hostname is `hostname`"
echo "The Kernel version is `uname -r`"
echo "The CPU version is `lscpu | grep "Model name" | tr -s " " | cut -d: -f2` "
echo "The Mem size is `cat /proc/meminfo | head -1 | tr -s " "`"
echo "The host ip is `ifconfig ens33 | grep "netmask" | tr -s " " | cut -d " " -f3`;netmask is `ifconfig ens33 | grep
"netmask" | tr -s " " | cut -d " " -f5`;"
如果想要每次直接打出脚本名就执行的话需要加入到$PATH变量中
操作步骤:查看当前系统$PATH值,然后使用mv命令将脚本移动到任意一个目录中即可
如果脚本中有一条命令输入错误,不会影响后续命令的执行,但有时候错误过于严重就会终止后续命令的执行
在脚本写完将要执行前,输入"bash -n "脚本名称""可以检测脚本中是否有错
而要观察脚本执行过程的话使用bash -x 脚本名称,会显示执行顺序和每一条命令的执行结果,但前提是脚本执行无误
变量的大概意思就是会变化的内容
变量名称:
1 只能使用字母,数字以及下划线,但不能使用数字开头
2 不要使用关键字,就是在Linux中已经有含义的字符,也不推荐字母做变量,不然后期看脚本容易混乱,如果像学生姓名这种变量名可以起
student_name一目了然,或者是驼峰法,也就是大小写,驼峰法又分为大驼峰,小驼峰,大驼峰代表只要是单词的首字母都大写,小驼峰代表第一个单词
的字母小写,后续单词的首字母大写
弱类型:写程序时不需要规定数据类型,系统自动
变量赋值:name='value'(建议使用单双引号引起变量值,变量值也可以是命令,但要用反向单引号引起来或者$(value))
变量值也可以是一篇文章或者多条数据,但是引用的时候要加给变量加双引号!!否则就会丢失一些信息
变量赋值时两边不要加空格,当不用一个变量的时候使用unset "变量名(不需要加$符号)"删除;
如果要将一个变量的值赋给另一个变量,则需要加$符号,比如"i=100"当我们想把i的值给j的时候就可以写成"j=$i",这样j就有了i的值,如果更改了
i的值或者删除了i的值,不会影响$j的值
变量的种类:
局部变量:子进程不能调用父进程的局部变量,父进程也不能调用子进程的局部变量
只是在当前shell环境下使用,当前shell表示了一个进程也就是bash,使用"echo $$"可以查看当前所在bash的进程号,也可以使用"pstree -p"命令
查看,进程与进程的关系会以倒树形结构显示的非常详细,排在左面的就是右边的父进程,越往右就是子进程
bash命令会开启一个shell,在一个shell中再次开启一个shell,那么后面的这个shell就是前面bash的子进程
使用echo $PPID可以查看父进程的进程号,父进程如果关闭,那么子进程也会停止运行,子进程关闭不影响父进程运行,如果父进程关闭子进程没有关
闭的话则说明了这个子进程也成为了僵死进程,进程会占用内存空间,所以要杀掉僵死进程释放资源
环境变量声明,赋值:
在父进程上定义的变量,一旦声明为环境变量,就可以一直继承到下面的进程,如果改了会影响当前的变量和后面的变量,但是父进程的变量不会改
set看到的是所有变量
env和declare -x和export和printenv都可以看到所有环境变量
$SHLVL 可以看到shell的嵌套深度
$_ 代表上一个命令的最后一个参数
只读变量:
只能声明,但不能修改和删除
声明只读变量:readonly "变量名称"或者declare -r "变量名称"
查看只读变量:readonly -p或者declare -r
举例说明:
[root@Centos7 bin]#name=test;( echo $name; name=222;echo $name );echo $name
test
222
test
小括号开了个子进程,括号中name的赋值只是在子进程有效,括号结束后,$name的值就又还原了,当想临时执行命令还不想影响当前工作环境就可以使
用
比如:
( umask 066;touch f3.txt /app ) 意思就是说在不改变当前umask值的情况下,使新创建的文件权限为600,而当前环境的umask值还是默认的
判断前面操作执行成功或者失败:看退出状态的值
$? : 上一条命令的执行状态,如果返回值为0那么说明执行成功,如果返回值为1-255之间的任意一个数,则说明执行失败,脚本当中 可以人为定
义$?返回的值,使用exit 要返回的值
如果要将一个变量和一个字符一起显示的话需要加花括号,比如:m=20,n=10,echo ${m}n就会显示为20n
位置变量:
$1,$2,....:对应第一个参数,第二个参数,第9个以上的参数就要使用"${10},${11}.."这种格式
$0:脚本名称
$*:代表所有参数 或 $@
$#:代表参数的个数
$@ $*被双引号引起来的时候才会有差别
$*被双引号引起来之后会将所有参数作为一个整体
$@被双引号引起来之后会认为每个参数为独立字符串
set --:清空所有位置变量
shift:使用shift会将后面的参数推到前面,shift 2:就是将后面两个参数推到前面
实例:如果每一次创建脚本文件的时候都自动生成注释可以编写一个这样的脚本;
#!/bin/bash
touch $1 (创建一个名为第一个参数的空文件)
chmod +x $1 (给此文件赋予执行权限)
echo "#!/bin/bash
#-------------------------
#Filename: $1
#Revision: 1.1
#Author: Fang
#Date: `date +%F`
#-------------------------" > $1 (将内容输入到执行脚本后的第一个参数)
#start vim
vim + $1 (编辑第一个参数内容)
bash中的算术运算:help let
+,-,*,/,%(取余),**(乘方)
实现数字运算:
let "表达式" i=10.j=20,let let sum=i+j可以算出值,同时也可以使用[],echo $[1+2],也可以使用(())表示,echo $((1+2))
还可以使用"expr 1 + 2"表达式中间是有空格的,*号需要被转义,否则会被认为是通配符,如果执行结果是0系统会认为是失败的
declare -i n=10 ,declare -i m=20(使用declare声明i是一个数字),可以再使用let sum=m+n
取余数: let n=i%3(取变量i的余数)
数字的次方:let n=2**7 (计算2的7次方)
bash中有随机生成数生成器:
echo $[$RANDOM%50] 生成的数值为0-49任意一个数
增强型赋值:
let i+=3(把自己加上数值再赋给自己)
let i-=3(把自己减去赋值再赋给自己)
let i++ (相当于i=i+1先取i再++)
let ++i (先++再处理i)
使字符串生成随机颜色的两种方法:
1 color=$[RANDOM%7+31];echo -e "\033[${color}m变颜色的字符串\033[0m"
2 color=`seq 31 37 | sort -R | head -n1`;echo -e "\033[1;5;${color}m变颜色的字符串\033[0m"()加上1,5的话可以高亮闪烁
3 如果要在文本中定义一个字符的颜色的话需要以下操作:vim打开一个空文件,输入"ctrl+v+["然后输入你要实现的颜色,高亮或者闪烁,比如:vim
color.txt;^[这两个字符是输入ctrl+v+[的时候出现的,然后在后面手动输入[1;5;31m字符串然后继续ctrl+v+[后面再输入[0m,也可以使用1或者2
这两个然后重定向到一个空文件也可以;
逻辑运算:
true,flase
非: ! (取反)
! 1 = 0
! 0 = 1
真:1 假:0
短路与运算: (任何数与0相与都是0)
cmd1 短路与 cmd2
如果cmd1为假,将不执行cmd2
如果cmd1为真,将执行cmd2
短路或运算: (任何数与1相或都是1)
cmd1 短路或 cmd2
如果cmd1为假,将执行cmd2
如果cmd1为真,将不执行cmd2
&&:表示短路与 ||:表示短路或
异或:
异或的两个值,相同为假,不同为真,比如a=40,b=20那么echo $[a^b]结果就为真,如果a=40,b=40那么echo $[a^b]就为假
条件测试:如果某些条件成立了,就返回$?是0,如果条件没有成立,就返回$?非0
测试命令:
test "表达式" 比如:比较两个字符是否相同,str1=abc,str2=def,test $str1 = $str2,echo $?,返回值就是非0,两个值相同就返回0
比较是否不同,str1=abc,str2=def,test $str1 != $str2,echo $?,返回值就是0,如果相同就返回非0
[表达式] 与test测试是等价的相同的,中括号中有字符的时候就返回的是真,如果没有字符,空的话就是假,可以用来判断变量是否有值,要
给变量双引号引起来,[ "x$a" = x ]也可以用这种写法测试变量是否有值,如果变量有值,那么两边肯定不等,会返回非0值,如果 相等
就会返回0
[]:中括号测试中可以跟的选项
-z 判断字符串是否为空,如果字符串为空就返回真
-n 判断字符串是否非空,如果字符串非空就返回真
-v 判断变量是否有值, 在中括号中变量不用加$符号
-f 判断中括号中是否为一个文件
-L 判断中括号中的是否为一个链接文件,并且会判断指向的文件类型
-d 判断中括号中的是否为一个文件夹
-S 判断中括号中的是否为套接字文件
-u 判断suid权限
-k 判断sticky权限
-v 查看变脸是否有值
-e 判断文件存在性
-大写o 判断当前文件的所有者是否为当前用户
[-eq]:相等
[-ne]:不等
[-gt]:大于
[-lt]:小于
[-ge]:大于等于
[-le]:小于等于
== 是否等于
> ascii码是否大于ascii码
< 是否小于
!= 是否不等于
=~ 用来匹配扩展正则表达式
判断文件是否可读并且这个文件是否可写,如果都满足就返回true,按照以下方式写
[ -r /etc/issue ] && [ -w /etc/shadow ] && echo true(有一个不满足就会显示false)
[-r /etc/issue -a -w /etc/shadow ] && echo true(跟上面的结果是一样的)
判断文件是否可读或者这个文件是否可写,满足任意一条返回true
[-r /etc/issue -o -w /etc/shadow ] && echo true
以下选项都是看实际权限的,包括ACL权限
-r 判断文件是否可读
-w 判断文件是否可写
-x 判断文件是否可执行
[[表达式]]可以支持的是扩展的正则表达式
var=haha;[[ "$var" =~ ha(这个ha默认是被包含的意思) ]] && echo true || echo false(返回的值是true,因为$var包含中括号中的那个字
符,所以会返回true)
判断文件后缀名是否为.sh:filename=f1.sh;[[ "$filename" =~ \.sh$ ]] && echo true || false(返回的值是true,中括号中的内容是正则表
达式,正则表达式不要用双引号引起来)
判断ip地址格式是否正确:ip="114.122.2.255";[[ "$ip" =~ ^(([0-9]|[1-9][0-9]|1[0-9]{2}|2[0-4][0-9]|25[0-5])\.){3}([0-9]|[1-9]
[0-9]|1[0-9]{2}|2[0-4][0-9]|25[0-5])$ ]] && echo true ||echo false
匹配手机号:var=13800138000;[[ "$var" =~ ^1[3456789][0-9]{9} ]] && echo true || echo false
退出状态码:
exit [n]:自定义退出状态码
脚本中一旦遇到exit命令,脚本就会立即终止;终止退出后$?返回的值取决于脚本中exit后面的值
如果没有给脚本指定退出状态码,脚本的退出状态码就会取决于脚本的最后一条命令的执行结果
ls /proc/$$/fd | wc -l(统计当前进程打开的文件描述符)
使用read命令来接受标准输入,可以实现交互式输入
比如:read name 会让你输入内容,输入后回车再查看$name就可以看到name的值
也可以同时赋予多个变量,空格做分隔符,平时很少这么用
-p 指定要显示的提示
-s 静默输入,适用于输入口令
-n 指定输入的字符长度,到达限定长度会直接退出
-d '字符' 输入结束符,看到某一个字符就结束
-t '' 限定超时时间,超过这个值就自动退出,默认以s为单位
bash中处理顺序优先级:
1 把命令行分成单个命令词
2 展开别名(脚本中不许使用别名)
3 展开大括号的声明({})echo {1..10}会将这种形式展开
4 展开波浪符声明(~)波浪符表示家目录,转换成家目录
5 命令替换 $() 和 ``会将符号中的命令展开执行
6 再次将命令行分成单词
7 查看是否有通配符,如果存在继续展开,也就是用符合条件的文件名代替这些符号(*,?,[abc]等)
8 如果发现含有重定向( < 、 > )则执行重定向
9 最后运行命令
防止扩展:
反斜线(\)转义符,会将位置参数转换为普通字符
加引号防止扩展:
单引号('')防止所有扩展
bash的配置文件,当用户登录的时候会读取这些配置文件
按生效范围划分,有两类:
全局配置:
/etc/profile,/etc/profile.d/*.sh,/etc/bashrc(对所有用户有效)
个人配置:
~/.bash_profile,~/.bashrc (对家目录的用户有效)
shell登录方式:
交互式登录:
直接通过终端输入账号密码登录
使用"su - username"切换的用户
顺序执行配置文件:
/etc/profile --> /etc/profile.d/*.sh --> ~/.bash_profile --> ~/.bashrc --> /etc/bashrc
/etc/profile中调用了/etc/profile.d下的文件
~/.bash_profile中又调用了~/.bashrc文件
~/.bashrc又调用了/etc/bashrc文件
非交互式登录:
su username
图形化打开终端
执行脚本
开启其他的bash实例,键入bash
顺序执行配置文件:
~/.bashrc --> /etc/bashrc --> /etc/profile.d/*.sh
按功能划分,存在两类:
profile类和bashrc类
profile类:为交互式登录提供配置
全局:/etc/profile,/etc/profile.d/*.sh
个人:~/.bash_profile
功能:
(1)用于定义环境变量
(2)运行命令或脚本
bashrc类:为非交互式和交互式登录提供配置(以下操作都是与用户相关的,用户登录会执行)
全局:/etc/bashrc
个人:~/.bashrc
功能:
(1)定义命令别名和函数
(2)定义本地变量
编辑配置文件生效的两种方法:
(1)重新启动shell进程
(2).或source
bash退出任务:
.bash_logout shell退出时会自动执行的操作
用于:
(1)创建自动备份
(2)清除临时文件
$-变量
$_:表示上一个命令的最后一个参数
$-:表示各种符号的组合,每个符号代表特定含义
echo $- 会显示himBH,如果要去掉某一个选项使用 set + 后面跟要去掉的选项
h:hashall,打开这个选项后,shell会将命令所在的路径hash下来;
i:判断当前shell是否为交互式shell,如果为交互式shell,是拥有i这个选项的,非交互式则没有
m:监控模式,前后台切换
B:大括号扩展可用,echo {1..10}
H:历史,可以列出历史命令中的列表,还可以是用!代表前面的命令
原文地址:http://blog.51cto.com/kaikai0720/2045132