Shell脚本
来源:互联网 发布:放大电路 知乎 编辑:程序博客网 时间:2024/06/05 21:18
说明:$符号不能正常显示的地方使用¥代替
1、命名、编写、执行
脚本的名字以.sh作为结尾,比如test.sh
脚本中第一行指定shell的版本,通常使用标准shell,即#!/bin/bash
脚本中使用#为脚本添加注释
脚本编写完成后,使用chmod 755 scriptname命令,赋予执行权限
使用./scriptname parameter1 parameter2… 或sh scriptname parameter1 parameter2 执行脚本
2、常用命令
read命令
作用: 接收键盘输入,与脚本进行交互
格式:read 选项 变量名
选项
-p 输出提示信息
-t 指定等待时间(秒),默认会一直等待用户输入
-n 指定接收的字符数
-s 隐藏输入的数据
eg
read -p “please input your name” -t 10 name 将用户输入的值赋予name
echo命令
echo 字符串 输出字符串或变量的值,默认输出后会换行,且不会识别特殊字符
echo -n 字符串 输出字符串或变量的值,不换行
echo -e 字符串 输出字符串或变量的值,在遇到 特殊字符时需转换,比如\n代表换行
3、常用符号及变量
4、变量分类
●用户自定义变量。
为局部变量,只对当前shell生效
定义 :变量名=变量值 变量名必须以字母或下划线开头,由字母、数字或下划线当变量中含有空格时,需要使用双引号或单引号将变量括起来,变量默认为字符串类型
声明 :declare [+/-] [选项] 变量名
选项: +取消变量属性 -设置变量属性 -i 设置为整型 -a 设置为数组 -r 只读变量
定义数组: arr_name=(value1 value2 ….)或 使用arr_name[index]=value单独为元素赋值
注意:
数组元素放在小括号内,而不是大括号,元素之间使用空格分开,而不是逗号,元素下标从0开始
获取数组元素: {arr_name[index]} 索引号为index的元素 {array_name[*]}数组的所有元素
获取数组长度: {#arr_name[*]}
数值运算:¥(()) 例如: a=1 b=2 c=¥((¥a+¥b))
●环境变量。
为全局变量,对子shell(使用bash进入子shell,使用exit退出子shell)同样生效,需要大写
查看环境变量 : env
设置环境变量:声明新的变量:export 变量名=变量值;将之前变量声明为全局变量: export 变量名
删除环境变量:unset 变量名 (在父shell中定义的环境变量,只能在父shell中删除)
●预定义变量
Bash已经定义好的变量,变量名无法修改,具有固定的作用,比如:¥n、¥*、¥#
5、函数
定义
function function_name{action}
action由shell命令组成,定义中没有参数,可以使用return返回返回值,如果不使用return则默认返回值为最后一条命令执行的结果,同一行中如果有多条命令,则使用分号分开,最好一行只写一条命令。
调用
functionname varname1 varname2….. 函数名后边的参数可以使用¥n进行引用
eg
#!/bin/bashfunction test{echo "$1"echo "$2"}test "hello" "world"
6、条件判断
使用[]可以对条件进行测试,使用[[ ]]可以对多个条件进行判断
eg
[[ -e /root/install.log&&-e /root/install.log.syslog ]]
●按文件类型判断
-e 判断文件是否存在,存在则返回真
-d 判断文件是否存在,并且是否为目录,是则返回真
-f 判断文件是否存在,并且是否为普通文件,是则返回真
格式:[选项 文件]
eg
[-e /root/install.log] 文件存在命令成功执行,返回真
[-e /root/install.log]&&echo “yes”|| echo “no” 如果存在文件则输出yes,否则输出
●按文件权限判断
-r 判断文件是否存在,并且是否拥有读权限,有则返回真
-w 判断文件是否存在,并且是否拥有写权限,有则返回真
-x 判断文件是否存在,并且是否拥有执行权限,有则返回真
格式:[选项 文件]
eg
[-r /root/install.log] 判断文件是否拥有读权限,有则返回真0
●两个文件比较
文件1 -nt 文件2 判断文件1是否比文件2新
文件1 -ot 文件2 判断文件1是否比文件2旧
文件1 -ef 文件2 判断文件1和文件2的i节点是否相同,即是否是同一个文件,是否是硬链接
eg
[newfile -nt oldfile] 返回真
●整数比较
整数1 -eq 整数2 判断是否相等
整数1 -ne 整数2 判断是否不等
整数1 -gt 整数2 判断整数1是否大于整数2
整数1 -lt 整数2 判断整数1是否小于整数2
整数1 -ge 整数2 判断整数1是否大于等于整数2
整数1 -le 整数2 判断整数1是否小于等于整数2
在进行比较时,shell会自动将数据类型转换为数值型
eg
[1 -ge 2]&&echo “yes”|| echo “no” 输出no
●字符串判断
-z 判断字符串是否为空
-n 判断字符串是否不为空
字符串1==字符串2 判断字符串是否相等
字符串1!=字符串2 判断字符串是否不等
eg
a="" [-z "$a"]&&echo "yes"||echo "no"输出yesb=1 c=2 [-z "$b"=="$c"]&&echo "yes"||echo "no" 输出no
●多重判断
判断1 -a 判断2 逻辑与
判断1 -o 判断2 逻辑或
!判断 逻辑非
eg
[-z “$a” -a 1 -ge 2 ]
7、流程控制
注意:条件判断式和中括号之间有空格
7.1单分支if语句
if [ 条件判断式 ];then 程序fi
eg
判断当前用户是否为root
#! /bin/bashtest=$(env|grep USER |cut -d "=" -f 2)if [ "$test"="root" ];then echo "current user is root"fi
判断分区使用率
#!/bin/bashtest=$(df -h |grep sda5 |awk '{print $5}|cut -d "%" -f 1)if [ "$test" -ge "90" ];then echo "/ is full"fi
7.2、双分支if语句
if [ 条件判断式 ];then 程序1else 程序2fi
eg
判断输入是否是一个目录
#!/bin/bashread -t 30 -p "please input derectory:" dirif [ -d "$dir" ];then echo "input is a directory"else echo "input isnot a directory"fi
7.3、多分支if语句
if [ 条件1 ];then 程序elif [ 条件2 ];then 程序 .....else 程序fi
7.4、多分支case语句
case $变量名 in "值1") 程序1 ;; "值2") 程序2 ;; ....... *) 程序 ;; esac
如果变量值为值1,则执行程序1,为值2,则执行程序2,为值3,则执行程序3等等,如果都不是,则执行最后一个程序
eg
#!/bin/bashread -t 30 -p "please input yes or no:" variablecase $variable in "yes") echo "you input is yes" ;; "no") echo "your input is no" ;; *) echo "your input is error" ;;esac
7.5、for循环
语法1
for 变量 in 值1 值2 值3..... do 程序 done
eg
批量解压缩
#!/bin/bashcd /root/test/ls *.tar.gz > ls.logls *.tgz >>ls.logfor i in ¥(cat ls.log) do tar -zxf ¥i &> /dev/null #将执行中显示的信息丢到黑洞 donerm -rf ls.log
语法2
for ((初始值;循环控制条件; 变量变化)) do 程序 done
注意:使用的是双小括号
eg
#!/bin/bash#从1加到100s=0;for((i=1;i<=100;i=i+1)) do s=$(($s+$i)) doneecho "the sum is:$s"
7.6、while循环
while [ 条件判断式 ] do 程序 done
只要条件判断式为真就一直执行
eg
#!/bin/bash#从1加到100i=1s=0while [ $i -le 100 ] do s=$(($s+$i)) i=$(($i+1)) doneecho "the sum is:$s"
7.7、until循环
until [ 条件判断式 ] do 程序 done
当条件判断式为真时,停止执行
eg
i=1s=0until [ $i -ge 100 ] do s=$(($s+$i)) i=$(($i+1)) doneecho "the sum is:$s"
8、调试脚本
检查语法错误
使用-n选项检查脚本中的语法错误,比如sh -n mem.sh
跟踪脚本执行
使用 -x选项执行脚本,比如sh -x mem.sh 1
#!/bin/bashfunction GetMem { MEMUsage=$(ps -o vsz -p $1|grep -v VSZ) ((MEMUsage /= 1000)) echo $MEMUsage }mem=$(GetMem $1)if [ $mem -gt 1600 ] ;then echo “The usage of memory is larger than 1.6G” else echo “The usage of memory is normal” fi
执行结果
++ GetMem 1+++ grep -v VSZ+++ ps -o vsz -p 1++ MEMUsage=' 19356'++ (( MEMUsage /= 1000 ))++ echo 19+ mem=19+ '[' 19 -gt 1600 ']'+ echo $'\342\200\234The' usage of memory is $'normal\342\200\235'“The usage of memory is normal”
+号代表执行的语句,多个+号反映了语句的嵌套
输出语句行号
设置环境变量export PS4=’+
执行结果
++mem.sh:9:: GetMem 1+++mem.sh:4:GetMem: ps -o vsz -p 1+++mem.sh:4:GetMem: grep -v VSZ++mem.sh:4:GetMem: MEMUsage=' 19356'++mem.sh:5:GetMem: (( MEMUsage /= 1000 ))++mem.sh:6:GetMem: echo 19+mem.sh:9:: mem=19+mem.sh:10:: '[' 19 -gt 1600 ']'+mem.sh:13:: echo $'\342\200\234The' usage of memory is $'normal\342\200\235'“The usage of memory is normal”
调试部分脚本
使用set -x和set +x包裹需要调试的脚本,使用sh mem.sh 1 注意 :没有-x选项
#!/bin/bashfunction GetMem { MEMUsage=$(ps -o vsz -p $1|grep -v VSZ) ((MEMUsage /= 1000)) echo $MEMUsage }mem=$(GetMem $1)set -x if [ $mem -gt 1600 ] ;then echo “The usage of memory is larger than 1.6G” else echo “The usage of memory is normal” fiset +x
执行结果
+ '[' 19 -gt 1600 ']'+ echo $'\342\200\234The' usage of memory is $'normal\342\200\235'“The usage of memory is normal”+ set +x
使用bashdb
使用bashdb软件可以进行复杂调试
9、常用脚本
查看系统信息
#!/bin/bashos=$(uname -o)echo "Operateing System Type:$os"os_name=$(cat /etc/issue |grep -e "release")echo "Opreating System Release Version:$os_name"architecture=$(uname -m)echo "Architecture:$os_name"kernel=$(uname -r)echo "Kernel:$kernel"hostname=$(uname -n)echo "Hostname:$hostname"internal_ip=$(hostname -I)echo "InternalIp:$internal_ip"nameserver=$(cat /etc/resolv.conf |egrep "nameserver[ ]+"|awk '{print $2}')echo "NameServer:$nameserver"ping -c 2 www.baidu.com &>/dev/null &&echo "Internet:connected"||echo "Intetnet:disconnected"who > /tmp/whoecho "Loggeg users"&& cat /tmp/whorm -rf /tmp/whosystem_mem_used=$(awk '/MemTotal/{total=$2}/MemFree/{free=$2}/^Cached/{cached=$2}/Buffers/{buffers=$2}END{print (total-free)/1024}' /proc/meminfo)echo "SystemMemoryUsed:$system_mem_used"application_mem_used=$(awk '/MemTotal/{total=$2}/MemFree/{free=$2}/^Cached/{cached=$2}/Buffers/{buffers=$2}END{print (total-free-cached-buffers)/1024}' /proc/meminfo)echo "ApplicationMemoryUsed:$application_mem_used"loadaverage=$(top -n 1|grep "load average"|awk '{print $10,$11,$12}')echo "LoadAverage:$loadaverage"diskaverage=$(df -hP |egrep -v "Filesystem|tmpfs"|awk '{print $1,$5}')echo -e "Diskaverage:\n$diskaverage"
监控CPU负载
#!/bin/bashfunction GetSysCPU { CpuIdle=$(vmstat 1 5|sed -n '3,$p'|awk '{x=x+ $15} END{print x/5}'|awk -F. '{print $1}') CpuNum=$((100-$CpuIdle)) echo $CpuNum }cpu=$(GetSysCPU)echo "The system CPU is $cpu"if [ $cpu -gt 90 ];then echo "The usage of system cpu is larger than 90%" else echo "The usage of system cpu is normal" fi
监控特定进程的cpu利用率
#!/bin/bashfunction GetCpu { CpuValue=$(ps -p $1 -o pcpu |grep -v CPU | awk '{print $1}' | awk -F. '{print $1}') echo $CpuValue }function CheckCpu { PID=$1 cpu=$(GetCpu $PID) if [ "$cpu" -gt 80 ] ;then { echo “The usage of cpu is larger than 80%” } else { echo “The usage of cpu is normal” } fi}temp=$(ps -p $1|grep -v PID)if [ -z "$temp" ];then echo "the process doetn't exist"else CheckCpu $1
监控特定进程的内存使用
#!/bin/bashfunction GetMem { MEMUsage=$(ps -o vsz -p $1|grep -v VSZ) ((MEMUsage /= 1000)) echo $MEMUsage }mem=$(GetMem $1)if [ $mem -gt 1600 ] ;then echo “The usage of memory is larger than 1.6G” else echo “The usage of memory is normal” fi
监控特定分区的磁盘使用率
function GetDiskSpc { if [ $# -ne 1 ] ;then return 1 fi Folder="$1$" DiskSpace=$(df -k |grep $Folder|awk '{print $5}'|awk -F% '{print $1}') echo $DiskSpace } DiskSpace=$(GetDiskSpc $1)echo "The system $Folder disk space is $DiskSpace%"if [ $DiskSpace -gt 90 ];then echo "The usage of system disk($Folder) is larger than 90%"else echo "The usage of system disk($Folder) is normal" fi
查看某个TCP端口或UDP端口是否在监听
#!/bin/bashfunction Listening { TCPListeningnum=$(netstat -an | grep ":$1 "|awk '$1 == "tcp" && $NF == "LISTEN" {print $0}' | wc -l) UDPListeningnum=$(netstat -an | grep ":$1 "|awk '$1 == "udp" && $NF == "0.0.0.0:*" {print $0}' | wc -l) (( Listeningnum=TCPListeningnum+UDPListeningnum)) if [ $Listeningnum == 0 ] ;then echo "0" else echo "1" fi}isListen=$(Listening $1)if [ $isListen -eq 1 ];then echo "The port is listening"else echo "The port is not listening"fi
参考
如何调试bash脚本
- shell脚本
- shell脚本
- shell脚本
- shell脚本
- shell脚本
- shell脚本
- shell脚本
- shell 脚本
- SHELL 脚本
- shell脚本
- shell脚本
- shell 脚本
- shell脚本
- shell脚本
- shell脚本
- shell脚本
- shell脚本
- shell脚本
- ToStringBuilder学习(一):常用方法介绍
- View的事件分发机制
- poj1408 Fishnet
- Java基本类型和引用类型
- git学习笔记~checkout和reset
- Shell脚本
- 2015省赛E简单的图论问题?
- javascript面试题精讲
- WebStrom安装入门心得
- 逃离x86架构-----CPU体系结构CISC与RISC之争
- unity小地图制作和方向导航
- fopen函数和fread函数、fwrite函数
- Erlang 速查表 v1.0
- android对手机通讯录的操作