1、shell编程之为什么学、怎么学
为什么学shell编程
Linux系统批量管理
提升工作效率,减少重复工作
学好shell编程所需要的基础知识
熟悉使用vim编辑器
熟悉SSH终端
熟练掌握Linux常用命令
熟练掌握Linux正则表达式及三剑客命令(grep、sed、awk)
如何学shell编程
阅读、模仿、阅读、模仿
核心:多练---->多思考---->再练---->再思考,坚持循环即可
大忌:不可拿来主义,可以模仿,但是要自己嚼烂了再吃下去
本阶段学习要求
看懂简单脚本
尝试写脚本
变量,循环,判断
2、shell编程基础
什么是shell
命令解释器:你输入的命令,谁来给你运行、解释
Centos默认的Shell是bash
[root@luffy-001 log]# echo $SHELL SHELL变量 /bin/bash [root@luffy-001 log]# cat /etc/shells 所有的命令解释器 /bin/sh /bin/bash /sbin/nologin /bin/dash /bin/tcsh /bin/csh [root@luffy-001 log]# cat /etc/passwd root:x:0:0:root:/root:/bin/bash root用户 的命令解释器 bin:x:1:1:bin:/bin:/sbin/nologin daemon:x:2:2:daemon:/sbin:/sbin/nologin adm:x:3:4:adm:/var/adm:/sbin/nologin lp:x:4:7:lp:/var/spool/lpd:/sbin/nologin sync:x:5:0:sync:/sbin:/bin/sync shutdown:x:6:0:shutdown:/sbin:/sbin/shutdown halt:x:7:0:halt:/sbin:/sbin/halt mail:x:8:12:mail:/var/spool/mail:/sbin/nologin uucp:x:10:14:uucp:/var/spool/uucp:/sbin/nologin operator:x:11:0:operator:/root:/sbin/nologin games:x:12:100:games:/usr/games:/sbin/nologin gopher:x:13:30:gopher:/var/gopher:/sbin/nologin ftp:x:14:50:FTP User:/var/ftp:/sbin/nologin nobody:x:99:99:Nobody:/:/sbin/nologin dbus:x:81:81:System message bus:/:/sbin/nologin vcsa:x:69:69:virtual console memory owner:/dev:/sbin/nologin abrt:x:173:173::/etc/abrt:/sbin/nologin haldaemon:x:68:68:HAL daemon:/:/sbin/nologin ntp:x:38:38::/etc/ntp:/sbin/nologin saslauth:x:499:76:Saslauthd user:/var/empty/saslauth:/sbin/nologin postfix:x:89:89::/var/spool/postfix:/sbin/nologin sshd:x:74:74:Privilege-separated SSH:/var/empty/sshd:/sbin/nologin tcpdump:x:72:72::/:/sbin/nologin pizza:x:500:500::/home/pizza:/bin/bash oldboy:x:501:501::/home/oldboy:/bin/bash
什么是Shell脚本
命令大礼包,就是一个程序文件,包含若干行Linux命令语句
循环,条件语句
一般以.sh结尾,或者通过file命令查看,其类型是shell script
[root@luffy-001 log]# file /server/scripts/ip.sh /server/scripts/ip.sh: Bourne-Again shell script text executable
创建Shell脚本
1、统一脚本存放目录,/server/scripts/
2、推荐使用vim编辑器编辑脚本,脚本以.sh结尾
3、第一行支出是由哪一个解释器来执行脚本中的内容
#!/bin/bash /sbin/ifconfig eth0|awk -F '[ :]+' 'NR==2{print $4}'
#! 称为幻数,能被内核识别
必须写在第一行,如果不是第一行就编程脚本注释行
又可以写成#!/bin/sh
4、版权声明
# desc: show ip address # author: pizza # time: 20191111 # version: v1.0
5、题目:写一个简单的脚本(切换目录显示文件实行)并运行
3、shell脚本深入
变量
用一个固定的字符串,替代更多更复杂的内容,省事
x=1
[root@luffy-001 scripts]# x=1
[root@luffy-001 scripts]# echo $x
1
devPath=/server/ filelist=`ls`或者$(ls)
$LANG
$PATH
变量又分为局部变量(普通变量)、全局变量(环境变量)、特殊变量
局部变量(普通变量)
只能在创建他们Shell函数或者Shell脚本中使用
形式:变量名=value 变量名要求: #1、字母、数字、下户线组成 #2、必须以字母开头 #3、见名知意,规范变量名写法定义 #4、驼峰写法:RedPizzaCar 应用变量尽量使用${} [root@luffy-001 scripts]# week=10 [root@luffy-001 scripts]# echo ${week}day 10day [root@luffy-001 scripts]# echo $weekday #这样写什么也没有 [root@luffy-001 scripts]# 可以把一个命令作为变量 普通字符串via你来定义测试
全局变量(环境变量)
大写、linux里面哪里都可以用(常用的$PATH、$LANG、$PS1)
在创建他们的Shell及其派生出来的子Shell中使用
与普通变量的区别
注意:普通变量是无法直接调用的,需要使用export将其转化成全局变量后方能使用,例子见下面代码
[root@luffy-001 scripts]# vim pizza.sh #!/bin/bash echo $PIZZA ~ ~ ~ "pizza.sh" 4L, 26C written [root@luffy-001 scripts]# PIZZA=10 [root@luffy-001 scripts]# echo $PIZZA 10 [root@luffy-001 scripts]# sh pizza.sh [root@luffy-001 scripts]# export PIZZA [root@luffy-001 scripts]# sh pizza.sh 10 [root@luffy-001 scripts]#
分类
1、Shell通过环境变量来确定登录用户名、命令路径、终端类型、登录目录(LANG、PATH、SHELL、UID)
2、自定义环境变量:
建议所有环境变量均为大写
必须用export命令定义
查看全局变量:env
取消全局变量:unset PIZZA
与用户环境变量有关的文件目录...
与用户环境变量有关的文件目录
全局环境变量配置文件
/etc/profile
/etc/bashrc
/etc/profile.d/ 用户登录到系统,会运行这个目录下面的脚本(脚本要有执行权限chmod +x)
用户环境变量配置文件
~/.bash_profile
~/.bashrc
特殊变量
位置变量
$0 获取当前执行脚本的文件名。如果执行脚本带路径,那么就包括脚本路径。模拟系统脚本使用$0
$n n代表脚本后面的参数,
$# 脚本一共有多少个参数,参数的个数
进程状态变量
$? 显示上一个命令的执行结果
###命令执行正确 结果0
###命令执行错误 结果非0
变量赋值-如何向变量中放内容
1、直接给!
x=1 y=2 echo $x $y w=$1 s=$2 echo $w $s [root@luffy-001 scripts]# sh pizza.sh 10 20 10 1 2 10 20
2、read
[root@luffy-001 scripts]# read -p "input x y:" x y input x y:10 20 [root@luffy-001 scripts]# echo $x $y 10 20
可以将该语句直接放入脚本中执行
read得到的输入默认存储在变量REPLY中
可以存储在一个或者多个变量中
-p “提示语句”, 屏幕就会显示交互式语句
-t 等待时间
-s 关闭回显,用于密码输入
条件表达式
[ <测试表达式> ]注意两边要有空格
判断文件
-f 判断文件是否存在
[root@luffy-001 scripts]# [ -f /server/scripts/pizza.sh ] [root@luffy-001 scripts]# echo $? 0
-d 判断目录是否存在 [root@luffy-001 scripts]# [ -d /server/scripts/ ] [root@luffy-001 scripts]# echo $? 0
判断整数
等于equal -eq
不等于not equal -ne
大于 greater than -gt
大于等于 greater equal -ge
小于less than -lt
小于等于 less equal -le
[root@luffy-001 scripts]# [ 1 -eq 1 ] [root@luffy-001 scripts]# echo $? 0
简单案例:判断命令行参数个数等于2(配合&&)
[ $# -eq 2 ] && echo "arg:$#"
题目:如果/oldboy目录不存在则创建
[ -d /oldboy ] || mkdir -p /oldboy
题目:如果/root/oldboy.txt存在则提示文件已存在
[ -f /root/oldboy.txt ] && echo file esists
if条件语句
单分支条件语句
语法:if [条件];then 命令 fi
题目:如果第一个数比第二个数大,显示第一个数大于第而个数
num1=$1 num2=$2 if [ $num1 -gt $num2 ]; then echo $num1 bigger than $num2 fi
多分支条件语句
语法:if [条件];then 命令 else 命令 fi
num1=$1 num2=$2 if [ $num1 -gt $num2 ]; then echo $num1 bigger than $num2 elif [ $num1 -lt $num2 ]; then echo $num1 less than $num2 else echo $num1 equal $num2 fi
现在有一个问题是这样的:如果参数过多,也会运行,后面多余的参数变成了无用参数,只有一个参数会报错
num1=$1 num2=$2 if [ $# -ne 2 ];then echo "Usage:"please input 2 num : num1 num2 exit fi if [ $num1 -gt $num2 ]; then echo $num1 bigger than $num2 else echo $num1 less than $num2 fi
[ -d /oldboy ] 相当于 test -d /oldboy
man test
for循环语句
语法格式:
for 变量名字 in 列表 do 命令 done
例子:
[root@luffy-001 scripts]# for num in 1 2 3 4 5 > do > echo "the num is:$num" > done the num is:1 the num is:2 the num is:3 the num is:4 the num is:5
生成序列seq 或者{}
[root@luffy-001 scripts]# for num in {1..10}; do echo "the num is:$num"; done the num is:1 the num is:2 the num is:3 the num is:4 the num is:5 the num is:6 the num is:7 the num is:8 the num is:9 the num is:10
题目:优化linux开机启动项,只保留crond;sshd;network;rsyslog;sysstat,其他的都关闭
提示:chkconfig 服务 off
for name in $(chkconfig |egrep "crond|sshd|rsyslog|network|sysstat" -v |awk '{print $1}') do chkconfig $name off done
查看脚本执行过程 -x
题目:批量添加yoghurt并设置随机密码