shell脚本必知会

来源:互联网 发布:淘宝和卖家联系 编辑:程序博客网 时间:2024/06/08 15:40

头部声明规范

#!/bin/bash#Author: wang#Version: 1.0#Date: 2016-05-01#Description:The script displays system informationecho "Greetings. The date and time are $(date)"echo "Your working directory is: $(pwd)"

bash

bash 和source执行脚本的区别

bash会开子shell执行,.和source会在当前shell执行

检测脚本中的语法错误bash -n /path/to/some_script

 调试执行bash -x /path/to/some_script\

显示没条命令的结果及层级

脚本终止

当出现语法错误时脚本会终止执行,命令错误还是继续执行

让脚本可执行

  1. 给执行权限
    1. 用bash目录执行
  2. 放在/bin/bash目录

显示环境变量

  • set(本地变量也会显示)
  • export
  • printenv

环境变量的声明

name='lee'sex=maleexport name sex # 或者用declare -x

常量的声明

name=leereadonly name 或者declare -r name

变量生效范围

  1. ==环境变量只对但前shell及下级shell有效,不会影响父shell==
  2. ==unset的变量只对但前shell及下级shell有效,不会影响父shell==
  3. ==父shell声明export变量后再unset,再重新以普通变量赋值,则子shell不再继承此变量==
  4. == 常量在子shell内无效(readonly 和 declare -r)==

true 与false

为内建命令
false # ?=1  
! false  #
?=0 (==!与false之间有空格,每空格是执行历史命令==)
[ false ] # $?=0

bash位置变量

变量 含义 $0 脚本名 19 位置参数1-9 ${10} 位置参数10 $# 位置参数的个数 “$*” 所有位置参数(作为单个字符串) “$@” 所有位置参数(每个作为单独字符串) ${#*} 传递到脚本中的命令行参数的个数 ${#*} 传递到脚本中的命令行参数的个数 $? 返回值 $$ 脚本进程的PID $- 传递到脚本中的标识 $_ 之前命令的最后一个参数 $! 运行在后台的最后一个作业的进程ID(PID)

删除位置变量
- set –(不可用unset)
- shift n 先进先出,从$1开始删(出栈)

bash中的算术运算

x=100y=200let z=$x+$ylet z=x+yz=$[x+y]z=$[$x+$y]z=$((x+y))z=$(($x+$y))declare -i a=100 #声明int类型declare -i b=200declare -i c=a+b

==expr不能用来赋值,相当于计算器*需要转义==

增强型赋值(要用let赋值)

+=

-=

*=

/=

%=

:let count+=3(先增加3再赋值)

自增,自减:

  • let var+=1
  • let var++
  • let var-=1
  • let var–先减再赋值
  • let –var 先赋值再减

==判断参数是否处理完根据shift执行结果来判断.处理一个shift一个,当最后一个出理完再shift的时候会返回1,因为没有参数拿来处理了==

条件测试

  • test
  • [] ==[ ” ” ]==空字符串为真(变量未定义为假)
  • [[]] 特殊符号*等不用转义

字符串测试

| 变量 | 含义 |
| :—- | :—- |
== |是否等于;

|ascii 码是否大于ascii码 码
< | 是否小于
!= | 是否不等于
=~ |左侧字符串是否能够被右侧的PATTERN所 所 匹配
注意: 此表达式一般用于[[ ]] 中;扩展的正则表达式
[ -z x]z[nx" ]或 [[ -n x]][[1" == "$USER” ]] ==注意等号两边有空格则是判断字符串相等,每空格则是判断是否非空==

[ " " ][ -z " " ][ "b" > "w" ][ "b" \> "w" ][ "btretr" \> "w" ]

== [] 里面用>要转义,字符串大小比较会以第一个字符的ascii码比较,符号字母直接要有空格;=~次符号两边不能有空格==

 数值测试

变量 含义 gt great than lt lower than eq equal ne not equal le lower equal ge great equal

注意:须使用[[]]

#判断用户是否存在 id user1 &> /dev/null && echo the user exist

练习

  1. 编写脚本/root/bin/systeminfo.sh,显示当前主机系统信息,包括主机名,IPv4地址,操作系统版本,内核版本,CPU型号,内存大小,硬盘大小。
 #!/bin/bash                                   ~                               8 echo -e "\033[35m主机名:\033[0m \033[36m `hos ~                                 tname`\033[0m"                                ~                               9 sleep 2                                       ~                              10 echo -e "\033[35m系统版本:\033[0m \033[36m `u ~                                 name -r`\033[0m"                              ~                              11 sleep 1                                       ~                              12 echo -e "\033[35mipv4地址:\033[0m \033[36m `i ~                                 fconfig|grep -w inet|head -1|tr -s ' '|cut -d ~                                 ' ' -f3`\033[0m"                              ~                              13 echo -e "\033[35m内核版本:\033[0m \033[36m `c ~                                 at /etc/redhat-release`\033[0m"               ~                              14 sleep 1                                       ~                              15 echo -e "\033[35mCPU型号:\033[0m \033[36m `ls ~                                 cpu| grep 'Model name'|cut -d: -f2|tr -s ' '` ~                                 \033[0m"                                      ~                              16 sleep 1.5                                     ~                              17 echo -e "\033[35m硬盘空间:\033[0m \033[36m \n ~                                 `df -h|grep -v 'tmpfs'`\033[0m"               ~                              18 sleep 1.5                                     ~                              19 echo -e "\033[35m内存大小:\033[0m \033[36m `f ~                                 ree `\033[0m"
  1. 编写脚本/root/bin/backup.sh,可实现每日将/etc/目录备份到/root/etcYYYY-mm-dd中 中

  2. 编写脚本/root/bin/disk.sh, 显示当前硬盘分区中空间利用率最大的值

  3. 编写脚本/root/bin/links.sh, 显示正连接本主机的每个远程主机的IPv4

  4. 编写脚本/root/bin/sumid.sh ,计算/etc/passwd 文件中
    的第10 个用户和第20 用户的ID 之和

  5. 编写脚本/root/bin/sumspace.sh ,传递两个文件路径作
    为参数给脚本,计算这两个文件中所有空白行之和
  6. 编写脚本/root/bin/sumfile.sh,统计/etc,/var,/usr目录中共有多少个一级子目录和文件
  7. 编写脚本/root/bin/argsnum.sh ,接受一个文件路径作为
    参数;如果参数个数小于1 ,则提示用户“至少应该给一个参
    数”,并立即退出;如果参数个数不小于1 ,则显示第一个参
    数所指向的文件中的空白行数

  8. 编写脚本/root/bin/hostping.sh ,接受一个主机的IPv4
    地址做为参数,测试是否可连通。如果能ping 通,则提示用户
    “该IP 地址可访问” ;如果不可ping 通,则提示用户“该IP地 地
    址不可访问”
     3 、编写脚本/root/bin/checkdisk.sh ,检查磁盘分区空间和inode使用率,如果超过80%,广播通知

存在性及类别测试

变量 含义 -a FIL 同-e -e FILE 文件存在性测试,存在为真,否则为 -b FILE 是否存在且为块设备文件 -c FILE 是否存在且为字符设备文件 -d FILE 是否存在且为目录文件 -f FILE 是否存在且为普通文件 -h FILE 或 -L FILE存在且为符号链接文件 -p FILE 否存在且为命名管道文件 -S FILE 是否存在且为套接字文件 -r FILE 是否存在且刻度 -w FILE 是否存在且可写 -x FILE 是否存在且可执行 -u FILE 是否存在且拥有suid权限 -g FILE 是否存在且拥有sgid权限 -k FILE 是否存在且拥有sticky权限 -s 是否存在且非空 -t fd fd 表示文件描述符是否已经打开且与某终端相关 -N FILE 文件自上一次被读取之后是否被修改过 -O FILE 当前有效用户是否为文件属主 -G 当前有效用户是否为文件属组 -nt newer than, file1 比file2的mtime新 -ot file1比file2的mtile旧 -ef file1是file2的硬链接
lrwxrwxrwx.  1 root   root      7 Mar 21 16:42 lib -> usr/libll -d /usr/libdr-xr-xr-x. 27 root root 4096 Mar 31 03:33 /usr/lib[ -d /lib ] true[989][root@yongge: /]# [ -L /lib ] true[990][root@yongge: /]# [ -h /lib ] true[991][root@yongge: /]# [ -b /lib ] false==注意判断软连接时,会同时判断软连接和软连接指向的文件====权限是以最终权限为判据的==

判断权限之前先判断存在性

[ -e FILE -a -r FILE ]

()和{}中逻辑代码的区别

==()包含的逻辑代码会开子进程执行;{}包含的逻辑直接在父进程执行==
例如如下两个脚本:

# 脚本一[ -e file1 ] || ( echo 'file1 not exit' && exit 2)echo 'continue'# 脚本2:[ -e file1 ] || { echo 'file1 not exit' ; exit 2}echo 'continue'

脚本一中遇到exit只是退出了子进程,所以echo continue会继续执行;脚本2中不会执行{}部分是一个匿名函数,故用分号隔开

双目测试

FILE1 -ef FILE2: FILE1 与FILE2 是否指向同一个设备上
的相同inode
FILE1 -nt FILE2: FILE1 是否新于FILE2
FILE1 -ot FILE2: FILE1 是否旧于FILE2

组合测试条件

- && || !

如:[[ -r FILE ]] && [[ -w FILE ]] 或者[ -r FILE -a -w FILE ]
- -a -o ! (不能使用[[]]进行测试)
[ ! -w /etc/passwd ] 不可写
[ -z “HOSTNAMEoHOSTNAME “==\
“localhost.localdomain” ] && hostname www.magedu.com
[ -f /bin/cat -a -x /bin/cat ] && cat /etc/fstab

设置颜色

格式 echo -e “\033[ 字背景颜色(40-47);文字颜色(30-37)m 字符串\033[0m”

Eg :echo -e “\033[41;36m something here \033[0m”
41 的位置代表底色, 36 的位置是代表字的颜色
字体颜色:30——37
echo -e “\033[30m 黑色字 \033[0m”
  echo -e “\033[31m 红色字 \033[0m”
  echo -e “\033[32m 绿色字 \033[0m”
  echo -e “\033[33m 黄色字 \033[0m”
  echo -e “\033[34m 蓝色字 \033[0m”
  echo -e “\033[35m 紫色字 \033[0m”
  echo -e “\033[36m 天蓝字 \033[0m”
  echo -e “\033[37m 白色字 \033[0m”
  

1. 编写脚本/bin/per.sh, 判断当前用户对指定的参数文件,是否不可读并且不可写2. 编写脚本/root/bin/excute.sh  ,判断参数文件是否为sh后缀的普通文件,如果是,添加所有人可执行权限,否则提示用户非脚本文件3. 编写脚本/root/bin/nologin.sh 和login.sh, 实现禁止和充许普通用户登录系统

参数替换和扩展

表达式 含义 varDEFAULT|var,DEFAULT作为其值 * var=DEFAULT|var,DEFAULT作为其值 * var:DEFAULT|var,,DEFAULT作为其值 * var:=DEFAULT|var,,DEFAULT作为其值 * var+OTHER|var,OTHER, 否则就为null字符串 var:+OTHER|var,OTHER, 否则就为null字符串 var?ERRMSG|var,ERR_MSG* var:?ERRMSG|var,ERR_MSG* ${!varprefix*} 匹配之前所有以varprefix开头进行声明的变量 ${!varprefix@} 匹配之前所有以varprefix开头进行声明的变量

字符串操作

表达式 含义 ${#string} $string的 长度 ${string:position}string,position开始提取子串 ${string:position:length}string,position开始提取长度为$length的子串 ${string#substring} 从 变量string,substring的子串 ${string##substring} 从 变量string,substring的子串 ${string%substring} 从 变量string,substring的子串 ${string%%substring} 从 变量string,substring的子串 ${string/substring/replacement} 使用replacement,substring ${string//substring/replacement} 使 用replacement,substring ${string/#substring/replacement} 如 果stringsubstring, 那么就用replacementsubstring ${string/%substring/replacement} 如果stringsubstring, 那么就用replacementsubstring expr match "$string" '$substring' 匹配stringsubstring* 的长度 expr "$string" : '$substring' 匹 配stringsubstring* 的长度 expr index "$string" $substringstringsubstring的第一个字符出现的位置 expr substr $string $position $lengthstringposition开始提取长度为$length的子串 expr match "$string" '\($substring\)'stringsubstring* expr "$string" : '\($substring\)'stringsubstring* expr match "$string" '.*\($substring\)'stringsubstring* expr "$string" : '.*\($substring\)'stringsubstring*
s=www.baidu.www.com# 删除指定字符(#从头开始匹配删,%从结尾开始匹配删)echo ${s#w*}ww.baidu.www.comecho ${s##w*} #全部删除echo ${s##*.}comecho ${s%.*}www.baidu.wwwecho ${s%%.*}www# 查找替换(支持通配符*?[])echo ${s/www/ttt}ttt.baidu.www.comecho ${s/w/t}tww.baidu.www.comecho ${s//w/t}ttt.baidu.ttt.comecho ${s//*/t}techo ${s//w*/t}techo ${s//./t}wwwtbaidutwwwtcomecho ${s//\./t}wwwtbaidutwwwtcomecho ${s//w./t}wwtbaidu.wwtcomecho ${s/w./t}wwtbaidu.www.comecho ${s/w?/t}tw.baidu.www.comecho ${s//w?/t}ttbaidu.ttcomecho ${s/[a-z]/t}tww.baidu.www.comecho ${s//[a-z]/t}ttt.ttttt.ttt.tttecho ${s/[^a-w]/t}wwwtbaidu.www.comecho ${s//[^a-w]/t}wwwtbaidutwwwtcom# 计算长度的2中方法:echo ${#s}17expr length $s17# 获取包含字符在原串中的索引expr index $s 'www' #获取www第一次出现的位置(从1开始)1

==$substring是一个正 则表达式.==

长度计算

  • ${#var}
  • expr length var

截取

索引截取 ${var:index:length}

匹配截取

替换

  • 只替换第一个 ${var/reg/str}把reg匹配的部分替换成str
  • 全部替换 {var//reg/str}

删除

  • ${var%%reg}删除reg匹配的部分

变量容错

var={name-‘yongge’}若name不存在则把yongge赋值给name
var={name:=’yongge’}若name不存在或者为空则把yongge赋值给name

变量批量赋值

read x y z < /etc/issue

[root@yongge: /root]# read x y z <<<"111 222 333"[root@yongge: /root]# echo $x111[root@yongge: /root]# echo $y222[root@yongge: /root]# echo $z333[root@yongge: /root]# read a b c <<<"$x $y $z"[root@yongge: /root]# echo $a111[root@yongge: /root]# echo $b222[root@yongge: /root]# echo $c333

bash命令执行顺序

  1. 把命令行分成单个命令词
  2. 展开别名
  3. 展开大括号种的声明({}) )
  4. 展开波浪符声明(~) )
  5. 命令替换$() 和 “) )
  6. 再次把命令行分成命令词
  7. 展开文件通配(* 、? 、[abc] 等等)
  8. 准备I/0 重导向(< 、>) )
  9. 运行命令

if语句

if condition;then    actionfiif contionthen    actionfiif condition1;then    action1else    action2fiif condition1then    action1else    action2fi//多条件then不能换行写if condition1;then    action1elif contion2;then    action2fiif condition1;then    action1elif contion2;then    action2else    action3fi

for循环

for i in x;do actiondonefor i;i<n;i++;do    actiondone

unit循环

unit condition;do    actiondone

select循环

select var in list    do        action    done

while 语句

while i<n;do    action    let n--donewhile read line;do    echo $linedone < /etc/passwd

function

语法-: function fname{ }语法二:function fname(){}语法三:fname(){}语法四:{}
1 0