1、shell 简介
安装一定逻辑关系记录命令的文件,在此文件有执行权限的情况下可以用文件名称发起脚本的指向,shell是一种解释性语言,文件内记录的动作需要解释器shell。
2、脚本的建立
2.1 vim test.sh
一般情况下脚本的结尾为".sh"这不是系统规定的,但是是业界的一种规范
2.2 #!/bin/bash
脚本开头的写法,这是脚本的使用的解释器,也就是脚本运行时的子shell
2.3 脚本的内容
脚本的内容是用命令和命令执行的逻辑关系组成
2.4 脚本的执行方式
方法一 :sh + 脚本的名称
方法二 :chmod +x 脚本
脚本名称的调用
3、 脚本的编写规范
1》开头应该添加脚本的说明信息
[root@westosmaim ~]# vim /etc/vimrc map <F6> ms:callAddTile()<cr>'s function AddTile() call append(0,"#!/bin/bash") call append(1,"############") call append(2,"#Auther :feitian") call append(3,"#Email :feitian@westos.com") call append(4,"#Version :") call append(5,"#Description :test scripts") call append(6,"#Create_Date :".strftime("%Y-%m-%D")) call append(7,"#############") Endfunction
2》脚本中尽量不要使用中文,哪怕用拼音代替
3》脚本中出现的()|[]|{}|<>等等成对出现的要一次打出,并且内容中的字符与这些符号之间要有空格
4》脚本中的语句要一次写完在丰富内容
5》语句中使用的动作要缩进写入,使脚本易读
4. 在书写脚本过程中我们用到的命令
4.1 diff命令
diff命令是用来比较两个文件的不同,一般我们比较文件的内容是都是使用vimdiif,以为他看起来更清楚,高亮显示不同的行。但是diff可以用来打补丁
[num1,num2][a|c|d][num3,num4] #a是添加的意思 #c是改变的意思 #d删除的意思 #num1,num2是第一个文件的内容 #num3,num4是第二个文件的内容
使用diff命令打补丁
diff -u file1 file2 >file.path #生成补丁文件 patch file1 file.patch #给file1打补丁,打完补丁之后,他就和file2相同 patch -b file1 file.patch #备份原文件为file.orgi
4.2 grep命令
-n | 只显示过滤出来的那一行 | -E | 多层过滤 |
-n3 | 显示过滤出来的上下3行(共7行) | ^test | 以test开头的内容 |
-A3 | 显示过滤出来的前边4行(共4行) | test$ | 以test结尾的内容 |
-B3 | 显示过滤出来的后边4行(共4行) | "\<test" | 以test开头的内容 |
-i | 对原文件就行修改 | "test\>" | 以test结尾的内容 |
-v | 除了包含过滤字符的内容 | ^$ | 空行 |
4.3 cut命令
cut -c 1-4|1,4 #打印文件2每行的前4个字符 cut -d 分隔符 -f 要打印的域 file
一个关于cut和grep的简单脚本 :打印出系统eth0的ip,如过由两块网卡,则下面会介绍方法。
[root@client scripts]# vim ip_print.sh #!/bin/bash ############ #Auther :feitian #Email :feitian@westos.com #Version : #Description :test scripts #Create_Date :2017-08-08/22/17 ############# IP=`ifconfig | grep "inet\>" |grep -v 127.0.0.1|cut -d " " -f 10` NAME=`ifconfig |grep mtu |grep -v lo | cut -d ' ' -f 1` echo "$NAME$IP" [root@client scripts]# sh ip_print.sh eth0:192.168.0.100
4.4 awk 命令
TEST=`############################` awk -F 分隔符 -v TEST=$TEST 'BEGIN {print TEST} {print $2} END {print TEST} /etc/passwd #可以使用特殊
一个简单的有关awk的脚本,还是刚才的问题,打印系统的网卡,这次就是多块网卡。
[root@client scripts]# vim ip_print.sh #!/bin/bash ############ #Auther :feitian #Email :feitian@westos.com #Version : #Description :test scripts #Create_Date :2017-08-08/22/17 ############# NAME=`cat /proc/net/dev |egrep "Inter|face|lo" -v|awk -F : '{print $1}'` for Device_Name in $NAME do ifconfig $Device_Name | grep "inet\>" |awk -F " " -v INTERFACE=$Device_Name 'BEGIN {print INTERFACE} { print $2}' done [root@client scripts]# sh ip_print.sh eth0 192.168.0.100 eth1 192.168.1.100
4.5 使用不同底色和不同颜色的字体
有关字体的颜色编号:
字体背景颜色 | 所对应的编号 | 字体颜色 | 所对应的编号 |
40 | 黑色 | 30 | 黑色 |
41 | 深红色 | 31 | 红色 |
42 | 绿色 | 32 | 绿色 |
43 | ××× | 33 | ××× |
44 | 蓝色 | 34 | 蓝色 |
45 | 紫色 | 35 | 紫色 |
46 | 深绿色 | 36 | 深绿色 |
47 | 白色 | 37 | 白色 |
图
一个简单10秒倒计时输出结果的字体为红色
#!/bin/bash ############ #Auther :feitian #Email :feitian@westos.com #Version : #Description :test scripts #Create_Date :2017-08-08/22/17 ############# for i in {10..1} do echo -ne "\033[31m$i \033[0m " echo -ne "\r \r" sleep 1 done
5. 脚本中的变量
5.1 变量的命名规则
变量中只能包含字母,数字和下滑线,他的写法一般为这3种 :TEST_REDAHAT,Test_Read和testReadhat.
关于变量的一个简单脚本,其实在前边我们已经用到变量,其实就是参数传递的作用。这里我们写一个建立用户的脚本,给定一个文件,让你把这个文件中的用户建立出来
[root@client scripts]# vim useradd.sh #!/bin/bash ############ #Auther :feitian #Email :feitian@westos.com #Version : #Description :test scripts #Create_Date :2017-08-08/22/17 ############# Max_Line=`wc -l /scripts/username|cut -c 1` for Line_Number in `seq 1 $Max_Line` do Username=`sed -n ${Line_Number}p /scripts/username` useradd $Username done [root@client scripts]# sh useradd.sh [root@client scripts]# sh useradd.sh useradd: user 'username1' already exists useradd: user 'username2' already exists useradd: user 'usernaem3' already exists
5.2变量的设定方式
环境级变量:在当前环境生效,当前环境关闭,变量失效
[root@client scripts]# export A=1 [root@client scripts]# echo $A 1
用户级变量:只针对设置过的用户生效,其他用户无法使用
在用户的家目录中修改,也就是文件/root/.bash_profile或者/student/.bash_profile
5.3 系统别名的设定方式
系统别名的设定也分为2个级别,他和系统变量的级别差不多,只是少一个环境级,他有用户级和系统级别名
用户级:在文件也是在用户的家目录下的.bashrc
[root@westosmaim~]# vim /root/.bashrc alias day='date' [root@westosmaim~]# source /root/.bashrc [root@westosmaim~]# day Tue Aug 2221:29:40 EDT 2017
系统级别名:系统级别名在/etc/bashrc,添加方式和系统级别名添加方式一样。
5.4 另一种变量的命名方式
$1 执行脚本时代表的第一串字符串
$2 同理,执行脚本中时代表的第二串字符串
$* 执行脚本时后面跟的所有字符串
$# 执行脚本时后面跟的字符串的个数
$? 执行脚本成功时返回0,执行脚本失败时返回非零。
[root@westosmaim scripts]# vim test.sh #!/bin/bash ############ #Auther :feitian #Email :feitian@westos.com #Version : #Description :test scripts #Create_Date :2017-08-08/22/17 ############# echo '$1 is '$1' ' echo '$1 is '$2' ' echo '$* is '$*' ' echo '$# is '$#' ' [root@westosmaim scripts]# sh test.sh lala hehe $1 is lala $1 is hehe $* is lala hehe $# is 2
注意:在重复两个单引号时可以抵消,好像是没有一样。
[root@westosmaim scripts]# echo $A 1 [root@westosmaim scripts]# echo '$A' $A [root@westosmaim scripts]# echo ''$A'' 1
这里穿插二个简单的脚本,第一个判断一个网段的ip是不是通的
#!/bin/bash ############ #Auther :feitian #Email :feitian@westos.com #Version : #Description :test scripts #Create_Date :2017-08-08/22/17 ############# echo "please input ip that netmask is (255.255.255.0) " echo "please input ip that as 172.25.254" for i in {1..254} do ping -w1 -c1 $1.$i &> /dev/null && echo"$1.$i is up" || echo "$1.$i is down" done
6. Shell脚本中函数的定义和变量的比较
使用test 可以用来作为变量的比较,在下面的脚本中有使用到 "$WANT" = "C" 判断WANT 的值等不等于C。
TEST() { echo test } #函数体 TEST #对函数的调用
这里穿插一个简单的脚本,就是判断一个网段的IP是不是通的。
#!/bin/bash ############ #Auther :feitian #Email :feitian@westos.com #Version : #Description :test scripts #Create_Date :2017-08-08/22/17 ############# ACTION() { read -p "please input a IP that it will be checked: " IP ping -w1 -c1 $IP &>/dev/null && echo "$IP is up" || echo "$IP is down" } CHECK() { read -p "what will you do? please inputQUIT(Q) or CHECK(C)" CHECK WANT=`echo $CHECK|tr a-z A-Z` test "$WANT" = "C" && ( ACTION CHECK) test "$WANT" == "Q" && exit 0 } MAIN
#这个也可以使用case语句 #!/bin/bash ############ #Auther :feitian #Email :feitian@westos.com #Version : #Description :test scripts #Create_Date :2017-08-08/22/17 ############# ACTION() { read -p "please input a IP that it will be checked: " IP ping -w1 -c1 $IP &>/dev/null && echo "$IP is up" || echo "$IP is down" } CHECK() { read -p "what will you do? please inputQUIT(Q) or CHECK(C)" CHECK WANT=`echo $CHECK|tr a-z A-Z` case $WANT in C) ACTION CHECK ;; Q) exit 0 ;; *) echo "please inputQ or C" ;; esac } CHECK
7.变量的判断
注意:这里举例均为正确的
[root@westosmaim scripts]# echo $A 1 [root@westosmaim scripts]# [ "$A"= "1" ]&& echo yes || echo no yes [ “1” = “1” ] [ “2” > “1” ] [ “1” < “2” ] [ “1” != “2”] #注意在“[”和“]”和你的比较对象之间必须要有空格 [ “$A” -eq “1” ] #1等于1 [ “$A” -ne “2” ] #1不等于二 [ “2” -gt “$A” ] #2大于1 [ “1” -ge “$A” ] #1大于等于1 [ “$A” -lt “2” ] #1小于2 [ “$A” -le “1” ] #1小于等于1 [ “$A” -eq “1” -a “2” lt “3” ] #1等于1并且2小于3 [ “2” -eq “2” -o “1” -gt “2” ] #2等于2或者1大于2,一个为真则为真。 [ -e /mnt/file ] #判断/mnt/file是不是存在 [ -f /mnt/file ] #判断/mnt/file是不是普通文件,如果不存在也是他也是返回非0 [ -x /mnt/file] #判断/mnt/file是不是有执行权限,如果文件不存在也返回非0 [ -d /mnt/file] #判断/mnt/file是不是一个目录,如果不是也返回非0 [ -z “helle”] #判断是否为空 #这里有很多参数,比如-b -S -p等等,都可以判断,读者可以自己理解,在前边find命令时都有讲过,这里就不过多介绍了。
8. Shell 脚本中的转义和注释
\ #转义单个字符
‘’ #强引用
“” #若引用,其转义功能不能转义“!”“$” “\” “`”
${A}1 #输出为11
[root@westosmaim scripts]# echo $A 1 [root@westosmaim scripts]# echo ${A}1 11 [root@westosmaim scripts]# echo $A1 #这里输出为空,因为没有A1这个变量
10.Sehll脚本中的四则运算
10.1四则运算符号
和c语言中的差不多,基本一样。
++ i++ ==>i+1 #自加1
-- i-- ==>i-1 #自减1
+= i+=j ==>i=i+j
-= i-=j ==>i=i-j
+ #加
- #减
* #乘
/ #除
% #取余
** #幂预算
10.2运算的命令
[root@westosmaim scripts]# echo $[3+2] 5 [root@westosmaim scripts]# let A=3+2 [root@westosmaim scripts]# echo $A 5 [root@westosmaim scripts]# echo `expr 3"+" 2` 5
#注意在expr作运算的时候,在“+”旁边必须有空格
11 .sehll 运算中的一些简单的语句
11.1 shell脚本中的for语句
这里写一个简单的例子,写一个简单的for语句的倒计时
#!/bin/bash ############ #Auther :feitian #Email :feitian@westos.com #Version : #Description :test scripts #Create_Date :2017-08-08/23/17 ############# TIME=10 for((TIME;TIME>0;TIME--)) do echo -n "After ${TIME}s is end" echo -ne "\r \r" sleep 1 done
当你输入一个字符串,他会他会反着输出
#!/bin/bash ############## #Auther :feitian #Email :feitian@westos.com #Version : #Description :test scripts #Create_Date :2017-08-08/21/17 ############## read -p "please iput alpha: " ALPHA Max=`echo -n $ALPHA |wc -m` for ((Max;Max>0;Max--)) do LALA=`echo -ne $ALPHA|cut -c $Max` echo -n $LALA done
11.2 while 语句
这里使用while写一个简单的倒计时为1分10s的倒计时脚本
#!/bin/bash ############ #Auther :feitian #Email :feitian@westos.com #Version : #Description :test scripts #Create_Date :2017-08-08/23/17 ############# TIME=10 MIN=1 for((TIME;TIME>=0;TIME--)) do while [ "$TIME" -eq"0" -a "$MIN" -gt "0" ] do echo -n "After $MIN:${TIME} is end " echo -ne "\r \r" sleep 1 ((MIN--)) TIME=59 done while [ "$TIME" -eq"0" -a "$MIN" -eq "0" ] do echo -ne "\r \r" clear echo "Time Out!!" exit 0 done clear echo -n " After $MIN:${TIME} isend " echo -ne "\r \r" sleep 1 done
11.3 if 语句
这里也是用一个脚本来更好的体现
#!/bin/bash ############ #Auther :feitian #Email :feitian@westos.com #Version : #Description :test scripts #Create_Date :2017-08-08/23/17 ############# if [ -z $* ] then echo "please giveme a filename" elif [ -f $* ] then echo "$* is acommon file" elif [ -L $*] then echo "$* is alink" else echo $* is not exist fi
#这里就不在多写了,就是变量的判断和if语句的运用
[root@westosmaim scripts]# sh panduan.sh /mnt/file /mnt/file is a common file 这里写一个进一步的脚本,给定两个文件,一个文件中是用户的名字,另一个文件是用户的密码,必须是一一对应。
#!/bin/bash ############ #Auther :feitian #Email :feitian@westos.com #Version : #Description :test scripts #Create_Date :2017-08-08/23/17 ############# CHECK() { if [ "$#" -ne"2" ] then echo "echo pleasegive me usernemfile and userpasswdfile" elif ["$#" -eq"2" ] then Max_Line1=`wc -l$1|awk -F " " '{print $1}'` Max_Line2=`wc -l$1|awk -F " " '{print $1}'` if ["$Max_Line" -ne "$Max_Line2" ] then echo "Thefile usernemfile don't muth userpasswdfile,please check it" else echo"lala" fi fi } CHECK