一、基础语法
1. 简介
shell语言是一门解释性语言,可简单到使用文本编辑器编写,不需要编译,在linux环境中运行,是用户与操作系统交互的一种媒介
常用的shell:
- Bourne Shell(/usr/bin/sh或/bin/sh)
- Bourne Again Shell(/bin/bash)
- C Shell(/usr/bin/csh)
- K Shell(/usr/bin/ksh)
- Shell for Root(/sbin/sh)
查看shell:
echo $SHELL
#结果:/bin/bash
2. 规范
- shell脚本的命名一般使用英文大小写,以sh为后缀
- 首行以 !#/bin/bash 开头
- 变量不能以数字,特殊符号开头,可以使用下划线,不能使用减号-
3. 变量
使用$引用变量,分为系统变量,环境变量,用户自定义变量
3.1 系统变量
$0 #当前脚本的名称
$n #当前脚本的第n个参数,n=1,2,…9
$* #当前脚本的所有参数(不包括程序本身)
$# #当前脚本的参数个数(不包括程序本身)
$? #单个命令执行后返回的状态,用于检查上一个命令执行是否成功,返回0表示执行成功
$$ #进程的PID号
3.2 环境变量
全局生效
$PATH #命令所示路径,以冒号为分割;
$HOME #打印用户家目录;
$SHELL #显示当前Shell类型;
$USER #打印当前用户名;
$ID #打印当前用户id信息;
$PWD #显示当前所在路径;
$TERM #打印当前终端类型;
$HOSTNAME #显示当前主机名;
$PS1 #定义主机命令提示符的;
$HISTSIZE #历史命令大小,可通过 HISTTIMEFORMAT 变量设置命令执行时间;
$RANDOM #随机生成一个 0 至 32767 的整数;
$HOSTNAME #主机名
可在/etc/profile.d/目录创建文件,把软件home目录在文件中创建变量,使用source /etc/profile.d/文件名.sh生效,常见需要配置的有 java,maven环境
3.3 用户自定义变量
用户在脚本中创建的变量,方便维护和管理,只在当前脚本中生效
示例:
#!/bin/bash
a=4
b=20
#加法运算
echo `expr $a + $b`
#减法运算
echo `expr $a - $b`
#乘法运算 注意*号前面要加反斜杠\
echo `expr $a \* $b`
#除法运算
echo `expr $a / $b`
#运算的另外两种写法
c=$((1 + 2))
echo ${c}
d=$[2 - 1]
echo ${d}
4. 流程控制语句
4.1 if条件语句
# 单分支语句
if [条件表达式];then
语句1
fi
# 双分支if语句
if [条件表达式];then
语句1
else
语句2
fi
# 多支条件语句
if [条件表达式1];then
语句1
elif [条件表达式2];then
语句2
elif [条件表达式3];then
语句3
fi
逻辑判断运算符:
-f #判断文件是否存在 eg: if [ -f filename ];
-d #判断目录是否存在 eg: if [ -d dir ];
-eq #等于,应用于整型比较 equal;
-ne #不等于,应用于整型比较 not equal;
-lt #小于,应用于整型比较 letter;
-gt #大于,应用于整型比较 greater;
-le #小于或等于,应用于整型比较;
-ge #大于或等于,应用于整型比较;
-a #双方都成立(and) 逻辑表达式 –a 逻辑表达式;
-o #单方成立(or) 逻辑表达式 –o 逻辑表达式;
-z #空字符串;
-x #是否具有可执行权限
|| #单方成立;
&& #双方都成立表达式。
示例:
#!/bin/bash
if [ 2 -gt 1 ];then
echo "yes!"
else
echo "no!"
fi
4.2 for循环语句
#写法1,在一行
for 变量名 in 取值列表;do 命令;done
#写法2,代码换行不需要;
for 变量名 in 取值列表
do
命令
done
#写法3,使用(())双括号,可以支持C语言的一些命令
for((i=1;i<=5;i++));do echo $i;done
示例:
#!/bin/bash
for filename in `ls`
do
if [ -d $filename ];then
echo "yes!"
else
echo "no!"
fi
done
#!/bin/bash
for number in $(seq 1 5)
do
echo $number
done
shell脚本中执行命令使用``
seq 1 5 表示从1开始,到5结束
4.3 while循环语句
# 一般用于循环文件
while [表达式]
do
语句1
done
示例:
#示例 1:在死循环中,满足条件终止循环
N=0
while true; do
let N++
if [ $N -eq 5 ]; then
break
fi
echo $N
done
#结果: 1 2 3 4
#示例 2:举例子说明 continue 用法
N=0
while [ $N -lt 5 ]; do
let N++
if [ $N -eq 3 ]; then
continue
fi
echo $N
done
#结果: 1 2 4
#示例 3: 打印 1-100 数字
i=0
while ((i<=100))
do
echo $i
i=`expr $i + 1`
done
#结果:略
break 是终止循环
continue 是跳出当前循环
4.4 case选择语句
case 模式名 in
模式 1)
命令
;;
模式 2)
命令
;;
*)
不符合以上模式执行的命令
esac
示例:
#!/bin/bash
PS3="Select a number: "
while true; do
select mysql_version in 5.1 5.6 quit;
do
case $mysql_version in
5.1)
echo "mysql 5.1"
break
;;
5.6)
echo "mysql 5.6"
break
;;
quit)
exit
;;
*)
echo "Input error, Please enter again!"
break
esac
done
done
select 是一个类似于 for 循环的语句
select语句一般用于选择,常用于选择菜单的创建,可以配合PS3来做打印菜单的输出信息,其语法格式以select…in do开头,done结尾
5. 函数
定义:
function 函数名(){
命令序列
[return x] #使用return或exit可以显示的结束函数
}
#或者
函数名 (){
命令序列
[return x] #使用return或exit可以显示的结束函数
}
直接写 函数中调用函数 直接写函数名
同名函数 后一个生效
调用函数一定要先定义
只要先定义了调用的 其他函数定义顺序无关
调用函数:
函数名 [参数1][参数2]
函数体不能写参数,调用参数时,在函数名后按顺序写参数
返回值:
return表示退出函数并返回一个退出值,脚本中可以用$?变量显示该值
函数一结束就取返回值,因为$?变量只返回执行的最后一条命令的退出状态码
退出状态码必须是0~255,超出时值将为除以256取余;避免方法:可以使用echo打印返回值,函数外使用$(函数名)接收
示例:
#!/bin/bash
function add() {
echo $(($1+$2))
echo `expr $1 + $2`
}
add 1 2
#!/bin/bash
#使用递归计算阶乘
fact() {
if [ $1 -eq 1 ] ;then
echo 1
else
local temp=$[$1 - 1]
local result=$(fact $temp )
echo $[$1 * $result]
fi
}
##############main###############
read -p"请输入一个正整数:" num
last=`fact $num`
echo "$num的阶乘的结果为:$last"
6. 数组
定义:
# 数组是相同类型的元素按一定顺序排列的集合。
格式:array=(元素 1 元素 2 元素 3 ...)
用小括号初始化数组,元素之间用空格分隔。
定义方法 1:初始化数组 array=(a b c)
定义方法 2:新建数组并添加元素 array[下标]=元素
定义方法 3:将命令输出作为数组元素array=($(command))
示例:
#方法 1:
#!/bin/bash
NUM=(1 2 4 6 90 8 4)
for ((i=0;i<${#NUM[*]};i++)); do
echo ${NUM[$i]}
done
#方法 2:
#!/bin/bash
NUM=(1 2 4 6 90 8 4)
for NUM1 in ${NUM[*]}; do
echo $NUM1
done
二、常用脚本记录
1. 批量创建用户并设置密码
#!/bin/bash
USER_LIST=$@
USER_FILE=./user.info
for USER in $USER_LIST;do
if ! id $USER &>/dev/null; then
PASS=$(echo $RANDOM |md5sum |cut -c 1-8)
useradd $USER
echo $PASS | passwd --stdin $USER &>/dev/null
echo "$USER $PASS" >> $USER_FILE
echo "$USER User create successful."
else
echo "$USER User already exists!"
fi
done
2. 查看占用资源过高的进程
#!/bin/bash
echo "-------------------CUP占用前10排序--------------------------------"
ps -eo user,pid,pcpu,pmem,args --sort=-pcpu |head -n 10
echo "-------------------内存占用前10排序--------------------------------"
ps -eo user,pid,pcpu,pmem,args --sort=-pmem |head -n 10
3. 一键多台机器执行命令
#! /bin/bash
for i in h1 h2 h3 h4 h5 h6
do
echo --------- $i ----------
ssh $i "$*"
done
常用于查看集群的服务或者资源情况:jps,df -h,free -g等
4. 修改文件内容后一键同步多台机器
#!/bin/bash
#1 获取输入参数个数,如果没有参数,直接退出
pcount=$#
if((pcount==0)); then
echo no args;
exit;
fi
#2 获取文件名称
p1=$1
fname=`basename $p1`
echo fname=$fname
#3 获取上级目录到绝对路径
pdir=`cd -P $(dirname $p1); pwd`
echo pdir=$pdir
#4 获取当前用户名称
user=`whoami`
#5 循环
for host in h1 h2
do
echo ------------------- $host --------------
rsync -av $pdir/$fname $user@$host:$pdir
done
常用于分布式集群安装时,安装包的分发和配置文件内容的同步
5. 磁盘挂载
#! /bin/bash
disk=${1} #磁盘目录,例如:/dev/sde/
mountdir=${2} #需要挂载的目录,例如:/mnt/app/
mkfs -t ext4 -F ${disk}
mkdir -p ${mountdir}
mount ${disk} ${mountdir}
echo "UUID=$(blkid ${disk} | cut -d "\"" -f 2) ${mountdir} ext4 defaults 1 2" >> /etc/fstab
mount -a