一、Shell概述
1.1 定义
Shell是一个命令行解释器,它接收应用程序/用户命令,然后调用操作系统内核;
Shell还是一个功能强大的编程语言,易编写、易调试、灵活性强。
1.2 Centos的解析器
1.3 bash和sh的关系
二、Shell脚本入门
2.1 脚本格式
脚本以 #!/bin/sh 或者:#!/bin/bash 开头(指定解析器)
2.2 第一个Shell脚本:Hello World
需求:创建一个Shell脚本,输出 Hello World
2.3 脚本的常用执行方式
第一种:采用bash或sh+脚本的相对路径或绝对路径(不用赋予脚本+x权限)
第二种:采用输入脚本的绝对路径或相对路径执行脚本(必须具有可执行权限+x)
(a) 首先要赋予 helloworld.sh 脚本的执行权限(+x)
(b) 执行脚本:相对路径/绝对路径
注意:第一种执行方法,本质是bash解析器帮我们执行脚本,所以脚本本身不需要执行权限;
第二种执行方法,本质是脚本需要自己执行,所以需要具有执行权限。
三、变量
3.1 自定义变量
( a ) 定义变量:变量=值
( b ) 撤销变量:unset 变量
( c ) 声明静态变量:readonly 变量(注意:不能unset)
(d) 备注:等号两侧不能有空格
(e) 变量的值如果有空格,需要使用双引号或单引号括起来
(f) 变量默认类型都是字符串类型,无法直接进行数值运算
3.2 特殊变量
$n
$n (功能描述:n为数字,$0代表该脚本名称,$1-
9
代表第一到第九个参数,十以上的参数,十以上的参数需要用大括号包含,如
9代表第一到第九个参数,十以上的参数,十以上的参数需要用大括号包含,如
9代表第一到第九个参数,十以上的参数,十以上的参数需要用大括号包含,如{10})
$#
$# (功能描述:获取所有输入参数个数,常用于循环)
$* & $@
$*
(功能描述:这个变量代表命令行中所有的参数,
(功能描述:这个变量代表命令行中所有的参数,
(功能描述:这个变量代表命令行中所有的参数,*把所有的参数看成一个整体)
$@
(功能描述:这个变量也代表命令行中所有的参数,不过
(功能描述:这个变量也代表命令行中所有的参数,不过
(功能描述:这个变量也代表命令行中所有的参数,不过@把每个参数区分对待)
补充:
$@ 表示的是参数的数组类型,当有多个参数的时候,每个参数占用一个数组元素;
$* 表示的是参数的字符串类型,当有多个参数的时候,所有参数拼成一个长字符串作为一个参数。
小结:
$$@和
$*在没有双引号括起来的时候,其实是一样的;而当使用双引号括起来的时候,则不同了
$@假定是数组,那么数组为空,也就是没有元素
$*假定是字符串,字符串为空的时候,表空串,但不为空值,所以在遍历的时候,就有一个元素
$?
$?(功能描述:最后一次执行的命令的返回状态。如果这个变量的值为0,证明上一个命令正确执行;如果这个变量的值为非0(具体是哪个数,由命令自己来决定),则证明上一个命令执行不正确了)
四、条件判断
4.1 基本语法
(a) test condition
(b) [ condition ] (注意:condition前后要有空格)
补充:条件非空即为true:[ binbin ] 返回true;[ ] 返回false
4.2 常用判断条件
4.2.1 两个整数之间比较
4.2.2 按照文件权限进行判断
4.2.3 按照文件类型进行判断
五、流程控制
5.1 if判断
案例:输入一个数字,如果是1,则输出:one excellent person;如果是2,则:two excellent person;否则,more excellent person
if [ $1 -eq "1" ]
then
echo "one excellent person"
elif [ $1 -eq "2" ]
then
echo "two excellent person"
else
echo "more excellent person"
fi
备注:(a) [ 条件判断式 ],中括号和条件判断式必须有空格;(b) if 后要有空格
5.2 case语句
案例:输入一个数字,如果是1,则输出:one case statement;如果是2,则:two case statement;否则,more case statement
case $2 in
"1")
echo "one case statement"
;;
"2")
echo "two case statement"
;;
*)
echo "more case statement"
;;
esac
备注:
( a ) case行尾必须为单词“in”,每一个模式匹配必须以右括号“)”结束
( b ) 双分号“;;”表示命令结束,相当于Java中的break
( c ) 最后的“*)”表示默认模式,相当于Java中的default
5.3 for循环
5.3.1 语法一
for (( 初始值;循环控制条件;变量变化 ))
do
xxx
done
需求:从1加到100
备注:运算符:“ ( ( 运算式 ) ) ”或“ ((运算式))”或“ ((运算式))”或“[ 运算式 ]”
e.g:计算 (2+3) * 4的值
echo "***************for 循环***********"
s=0
for((i=0;i<=100;i++))
do
s=$[ $s+$i ]
done
echo "从1加到100的和:"$s
5.3.2 语法二
for 变量 in 值1 值2 值3…
do
xxx
done
实例:打印所有输入参数
for i in $*
do
echo $i" person:Urbane Binbin"
done
5.3.3 $*和 $@的区别
$* 和 $@都表示传递给函数或脚本的所有参数,不被双引号“”包含时,都以$1
2
…
2 …
2…n的形式输出所有参数。
实例:
echo "*************for 循环二***********"
for i in $*
do
echo $i" person:Urbane Binbin"
done
echo "***********不被双引号包含*********"
for j in $@
do
echo $j" person:Urbane Binbin"
done
当它们被双引号“”包含时,$*会将所有的参数作为一个整体,以$1 $2 …
$n的形式输出所有参数;“ $@ ”会将各个参数分开,以“ $1 ” “ $2 ”…” $n”的形式输出所有参数
echo "***********被双引号包含***********"
for i in "$*"
# $*中的所有参数看成是一个整体,所以这个for循环只会执行一次
do
echo $i" person:Urbane Binbin"
done
for j in "$@"
# $@中的每个参数都看成是独立的,所以“$@”中有几个参数,就会循环几次
do
echo $j" perosn:Urbane Binbin"
done
六、函数
6.1 系统函数
6.1.1 basename
basename [string / pathname] [suffix] (功能描述:basename命令会删掉所有的前缀包括最后一个(‘/’)字符,然后将字符串显示出来。
选项:suffix为后缀,如果suffix被指定了,basename会将pathname或string中的suffix去掉
6.1.2 dirname
dirname 文件绝对路径 (功能描述:从给定的包含绝对路径的文件名中去除文件名(非目录的部分),然后返回剩下的路径(目录的部分))
6.2 自定义函数
[ function ] funname[()]
{
Action;
[return int;]
}
funname
实例:计算两个输入参数的和
echo "***********自定义函数***********"
function sum()
{
s=0
s=$[ $1 + $2 ]
echo "$s"
}
read -p "请输入自定义函数sum()的第一个参数:" n1;
read -p "请输入自定义函数sum()的第二个参数:" n2;
# 调用
sum $n1 $n2;
备注:必须在调用函数地方之前,先声明函数,shell脚本是逐行运行。不会像其它语言一样先编译
七、read读取控制台输入
read(选项)(参数)
选项:
-p:指定读取值时的提示符;
-t:指定读取值时等待的时间(秒)
参数:变量:指定读取值的变量名
echo "********read读取控制台输入********"
read -t 7 -p "请在7秒内输入你的名字:" NAME
echo $NAME
超过7秒,自动跳出
八、学以致用
function showhelp()
{
echo "###################################!!! you must input at least two params !!!#####################################################################"
echo "#Usage: [sh `basename $0` kill_by_runtime|-t minutes] show info with filename's ascending order ,eg: sh `basename $0` kill_by_runtime 180"
echo "#Usage: [sh `basename $0` kill_by_vcores|-v cores_nums] show info with size's ascending order,eg: sh `basename $0` kill_by_vcores 30"
echo "##################################################################################################################################################"
}
#首先判断输入参数的个数是否符合要求
if [ $# -ne 2 ]; then
#如果传递进来的参数个数不等于2,则记录错误并退出
showhelp
#退出
exit 1
fi
# 当前时间
see_current_time=`date +'%Y-%m-%d %H:%M:%S'`
# 当前时间戳
current_time_temp=`date +'%s%N'`
current_time=$[$current_time_temp/1000000]
# 指定输出部分日志到outfile
outfile='./moniter_on_yarn.log'
echo "======== running results: =========" >> $outfile
echo "======== current_time: ============="$see_current_time >> $outfile
echo "======== current_timestamp: ========"$current_time >> $outfile
function origin()
{
sudo kinit -kt /etc/security/keytabs/hdfs.keytab hdfs
# 获取在运行的任务
app_list=`sudo yarn application -list | grep -w RUNNING | awk '{print $1}' | grep application_`
for app in ${app_list[@]}
do
echo "======== active application: ========"${app} >> $outfile
# 获取:Application Report
app_status=`sudo yarn application -status ${app}`
# 获取:Application Start-Time
start_time=$( expr "$app_status" : '.*\([0-9]\{13\}\).*' )
echo "======== application start time: ========"$start_time >> $outfile
# 任务开始时间与当前时间做差
((diff_time=$current_time-$start_time))
echo "======== application have run time: ========"$diff_time >> $outfile
echo "======== limit value application have run time: ========"$1 >> $outfile
if [ $diff_time -gt $1 ]
then
echo '======== sudo yarn application -kill ========'$app>> $outfile
else
echo '======== not need kill application ========'$app>> $outfile
fi
#if [ $diff_time -gt $1 ];then
# result=`sudo yarn application -kill ${app}`
# echo '======== sudo yarn application -kill ========'$app>> $outfile
# break
#fi
done
}
case "$1" in
kill_by_runtime|-t)
kill_by_runtime $2
;;
asc|-a)
asc $2
;;
kill_by_vcores|-v)
kill_by_vcores $2
;;
*)
showhelp
exit 1
esac
exit 0