shell脚本介绍
- shell是一种脚本语言 和传统的开发语言比较,会比较简单
- shell有自己的语法;可以使用逻辑判断、循环等语法
- 可以自定义函数,目的就是为了减少重复的代码
- shell是系统命令的集合
- shell脚本可以实现自动化运维,能大大增加我们的运维效率
shell脚本结构和执行
- 开头需要加#!/bin/bash
- 以#开头的行作为解释说明
- 脚本的名字以.sh结尾,用于区分这是一个shell脚本
- 执行方法有两种
- chmod +x 1.sh; ./1.sh
- bash 1.sh
- 查看脚本执行过程 bash -x 1.sh
- 查看脚本是否语法错误 bash -n 1.sh
实践操作:
- 创建一个shell文件夹,并切入到文件夹中
[root@aminglinux ~]# mkdir shell [root@aminglinux ~]# cd shell/ [root@aminglinux shell]#
- 写shell脚本:#! /bin/bash //第一行必须这么写,固定格式,作用就是脚本若是在当台机器上去执行,可以不加这一行也没关系,因为它知道下面若干条的命令能在这台机器上去执行,去解析
[root@aminglinux shell]# vi 1.sh #!/bin/bash echo "abc" w ls
- 执行脚本——>sh 01.sh
[root@aminglinux shell]# sh 1.sh abc 15:17:34 up 5:30, 1 user, load average: 0.00, 0.01, 0.05 USER TTY FROM LOGIN@ IDLE JCPU PCPU WHAT root pts/0 192.168.222.1 09:48 6.00s 0.12s 0.05s w 1.sh
- 在当前终端里,把01.sh中的#! /bin/bash 去掉后在执行脚本,会看到得到的结果相同,不会出现任何的问题,这就说明这台机器是能识别里面一条一条的命令的,去运行这里面的命令;但若是换一台机器,就不一定能执行了
- 在第一行,文件头指定 #!/bin/bash ,接下来要运行的命令是通过哪一个解释器来操作的,通常都是 /bin/bash 解释器来执行的
- 给01.sh文件一个执行权限
[root@aminglinux shell]# chmod a+x 1.sh
- 执行shell脚本 ./01.sh 能这样执行,说明这些命令被解析了,被/bin/bash认识了
[root@aminglinux shell]# ./1.sh abc 15:21:19 up 5:33, 1 user, load average: 0.08, 0.03, 0.05 USER TTY FROM LOGIN@ IDLE JCPU PCPU WHAT root pts/0 192.168.222.1 09:48 7.00s 0.10s 0.00s w 1.sh
- /bin/bash也是一条命令, /bin/bash 和 /bin/sh 是同一个文件
[root@aminglinux shell]# ll /bin/bash -rwxr-xr-x. 1 root root 960472 8月 3 2017 /bin/bash [root@aminglinux shell]# ll /bin/sh lrwxrwxrwx. 1 root root 4 6月 10 04:03 /bin/sh -> bash
- 1.sh文件内容就是被/bin/bash所解析的;若没有 /bin/bash ,可以使用 /bin/bash 1.sh去执行
[root@aminglinux shell]# /bin/bash 1.sh abc 15:26:49 up 5:39, 1 user, load average: 0.00, 0.01, 0.05 USER TTY FROM LOGIN@ IDLE JCPU PCPU WHAT root pts/0 192.168.222.1 09:48 1.00s 0.12s 0.01s w 1.sh
- 若是在shell脚本中在写入第二遍 #号开头的行, 就表示解释说明的作用
- 脚本的一般都是以.sh结尾,是为了区分这是一个shell脚本,否则需要打开这个文件,才知道是shell脚本
运行shell脚本有两种方法
- 一种是sh 01.sh运行shell脚本
- 另一种方法:
- 先 chmod a+x 1.sh 给文件加一个执行权限
- 再 ./1.sh 去执行
- 这里的 ./ 就相当于一个相对路径,相对当前一个路径
- 也可以使用绝对路径去执行脚本 /root/shell/01.sh ,其实就是找到这个文件去执行
[root@aminglinux shell]# /root/shell/1.sh abc 15:29:52 up 5:42, 1 user, load average: 0.16, 0.05, 0.06 USER TTY FROM LOGIN@ IDLE JCPU PCPU WHAT root pts/0 192.168.222.1 09:48 0.00s 0.13s 0.00s w 1.sh
- -x,就是显示脚本执行的过程
- 每一个加号,表示一个操作步骤
[root@aminglinux shell]# sh -x 1.sh + echo abc abc + w 15:32:10 up 5:44, 1 user, load average: 0.02, 0.03, 0.05 USER TTY FROM LOGIN@ IDLE JCPU PCPU WHAT root pts/0 192.168.222.1 09:48 2.00s 0.14s 0.01s w + ls 1.sh
- 查看脚本是否有错误 sh -n 1.sh
- 若是没有任何的输出,那么脚本则没有错误
- sh -n 1.sh命令是检测是否存在语法错误
[root@aminglinux shell]# sh -n 1.sh
date命令用法
- date +%Y-%m-%d, date +%y-%m-%d 年月日
- date +%H:%M:%S = date +%T 时间
- date +%s 时间戳
- date -d @1504620492
- date -d "+1day" 一天后
- date -d "-1 day" 一天前
- date -d "-1 month" 一月前
- date -d "-1 min" 一分钟前
- date +%w, date +%W 星期
date命令用法实践
- date命令,会显示当前系统时间日期
[root@aminglinux ~]# date 2018年 07月 29日 星期日 15:44:05 CST
-
date命令,在shell中用处非常大;对文件后缀增加一个时间,以便后期管理。
LANG=en //date命令显示的时间就是英文的 LANG=zh_CN.UTF-8 //date命令显示的时间是中文的
-
date +%Y-%m-%d, date +%y-%m-%d 年月日
[root@aminglinux ~]# LANG=en 切换为英文显示 [root@aminglinux ~]# date Wed Jul 11 23:01:05 CST 2018 [root@aminglinux ~]# date +%Y 2018 四位的年 [root@aminglinux ~]# date +%y 18 两位的年 [root@aminglinux ~]# date +%m 07 月份 [root@aminglinux ~]# date +%M 51 分钟 [root@aminglinux ~]# date +%d 29 日期 [root@aminglinux ~]# date +%D 07/29/18 直接标记年月日,不过格式比较特殊 [root@aminglinux ~]# date +%Y%m%d 20180729 年月日 [root@aminglinux ~]# date +%F 2018-07-29 年月日,这种带横杠的
- 常见时间单位
[root@aminglinux ~]# date +%w 0 表示周几 [root@aminglinux ~]# date +%W 30 今年的第几周,今年的第28周 [root@aminglinux ~]# date +%h Jul 英文的月份 [root@aminglinux ~]# date +%H 15 小时 [root@aminglinux ~]# date +%S 26 秒 [root@aminglinux ~]# date +%s 1532850869 这是一个时间戳,距离1970总共过去多少秒
- 时间其他标记方法:date +%H:%M:%S = date +%T 时间
[root@aminglinux ~]# date +%T 15:56:18 [root@aminglinux ~]# date +%H:%M:%S 15:56:39
- 显示日历 cal命令,查看到日期
[root@aminglinux ~]# cal July 2018 Su Mo Tu We Th Fr Sa 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31
- 标记之前的日期
- 比如:在做nginx日志切割的时候,到了凌晨切割日志,到了零点零分切割的日志是前一天的日志。所以把日志加一个时间标记的话,应标记为昨天的日期
学会用date标记之前的日期
- day、month、year、hour、min后面可以加 s 可以不加 s
- 减号- 表示之前的日期,加号 + 表示从今往后的日期
- date -d "-1 day" +%F 显示前一天的日期
- date -d "-1 month" +%F 显示上个月的日期
- date -d "-1 years" +%F 显示上一年的日期
- date -d "+1 hour" +%T 显示下一小时
- date -d "+1 min" +%T 显示下一分钟
[root@aminglinux ~]# date -d "-1 day" Sat Jul 28 16:01:23 CST 2018 [root@aminglinux ~]# date -d "-1 day" +%F 2018-07-28 [root@aminglinux ~]# date -d "-1 month" +%F 2018-06-29 [root@aminglinux ~]# date -d "-1 year" +%F 2017-07-29 [root@aminglinux ~]# date -d "+1 hour" +%T 17:02:53 [root@aminglinux ~]# date -d "+1 min" +%T 16:04:02
- 时间戳 date +%s
- 另一种表现方法,表示时间戳
- date -d @1532850869就是@后跟时间戳
[root@aminglinux ~]# date +%s 1532851512 [root@aminglinux ~]# date -d @1532851512 Sun Jul 29 16:05:12 CST 2018
- 若想在linux系统中,把具体的日期换算成时间戳的时候,可以使用date +%s -d "2018-07-29 16:08:00"
[root@aminglinux ~]# date +%s -d "2018-07-29 16:08:00" 1532851680 [root@aminglinux ~]# date -d @1532851680 Sun Jul 29 16:08:00 CST 2018
shell脚本中的变量
-
shell脚本中的变量:是某个字符串使用频繁,或者字符串长度长,可以使用变量才代替,提高代码编写的效率。
-
在条件语句中常使用到变量:
if [$a -gt 10];then 语句; fi //a就是变量
- 引用命令结果时用变量:
n='wc -l 1.txt' //wc统计行数命令的结果,赋值给变量n
- 用户交互脚本中,使用变量:
read -p "input a number : " n; echo $n //把输入的数值,赋值给变量n
- 系统的内置变量:
$0,$1,$2,$3等 //$0表示脚本本身,$1、$2代表命令的第1个参数、第2个参数,如此类推。$#代表参数个数
- 数序运算中使用变量:
a=1 b=2 c=$(($a+$b)) //c=$[$a+$b] 这种写法也行
shell脚本中的逻辑判断
- 格式1:if 条件 ; then 语句; fi
- 格式2:if 条件; then 语句; else 语句; fi
- 格式3:if …; then … ;elif …; then …; else …; fi
- 逻辑判断表达式:if [ $a -gt $b ]; if [ $a -lt 5 ]; if [ $b -eq 10 ]等 -gt (>); -lt(<); -ge(>=); -le(<=);-eq(==); -ne(!=) 注意到处都是空格
- 可以使用 && || 结合多个条件
- if [ $a -gt 5 ] && [ $a -lt 10 ]; then
- if [ $b -gt 5 ] || [ $b -lt 3 ]; then
shell脚本中的逻辑判断实战
- for语句循环 :for 变量 in 条件(值范围); do 语句 ;done
[root@aminglinux ~]# for i in `seq 1 5`;do echo $i;done 1 2 3 4 5 [root@aminglinux ~]# for i in `seq 1 5` > do > echo $i > done 1 2 3 4 5
- if语句格式1:if 条件 ; then 语句; fi //如果条件满足,输出ok
[root@aminglinux shell]# vim if1.sh #!/bin/bash a=5 if [ $a -gt 3 ] then echo OK fi [root@aminglinux shell]# sh if1.sh OK
- if语句格式2:if 条件; then 语句; else 语句; fi //如果条件满足,输出ok,如果条件不满足,输出nook
[root@aminglinux shell]# cp if1.sh if2.sh [root@aminglinux shell]# vim if2.sh a=1 if [ $a -gt 3 ] then echo OK else echo nook fi [root@aminglinux shell]# sh -x if2.sh + a=1 + '[' 1 -gt 3 ']' + echo nook nook
- if语句格式3:if …; then … ;elif …; then …; else …; fi //如果不满足条件1,满足条件2,输出条件2,不满足则输出nook,
[root@aminglinux shell]# vim if3.sh [root@aminglinux shell]# cat if3.sh #! /bin/bash a=6 if [ $a -lt 5 ] then echo "a<5" elif [ $a -gt 5 ] && [ $a -lt 9 ] then echo "5<a<9" else echo "a>9" fi [root@aminglinux shell]# sh -x if3.sh + a=6 + '[' 6 -lt 5 ']' + '[' 6 -gt 5 ']' + '[' 6 -lt 9 ']' + echo '5<a<9' 5<a<9
逻辑判断表达式
- if [ $a -gt $b ] 表示,大于
- if [ $a -lt 5 ] 表示,小于
- if [ $b -eq 10 ] 表示,等于10
- -ne(!=) 表示,不等于
- -ge(>=) 表示,大于等于
- -le(<=) 表示,小于等于
可以使用 && || 结合多个条件
- if [ $a -gt 5 ] && [ $a -lt 10 ]; then
- if [ $b -gt 5 ] || [ $b -lt 3 ]; then
- if文件目录属性判断
- if 判断文件、目录属性
- [ -f file ] 判断是否是普通文件,且存在
- [ -d file ] 判断是否是目录,且存在
- [ -e file ] 判断文件或者目录是否存在
- [ -r file ] 判断文件是否可读
- [ -w file ] 判断文件是否可写
- [ -x file ] 判断文件是否可执行
文件目录属性判断实战
-
[ -f file ]判断是否是普通文件,且存在
-
[root@aminglinux shell]# vim file1.sh
-
[root@aminglinux shell]# cat file1.sh
-
#! /bin/bash
-
f="/tmp/aminglinux1"
-
if [ -f $f ]
-
then
-
echo $f exist
-
else
-
touch $f
-
fi
-
[root@aminglinux shell]# sh -x file1.sh //第一次执行,会创建该文件
-
+ f=/tmp/aminglinux1
-
+ '[' -f /tmp/aminglinux1 ']'
-
+ touch /tmp/aminglinux1
-
[root@aminglinux shell]# sh -x file1.sh //第二次执行,会提示该文件已存在
-
+ f=/tmp/aminglinux1
-
+ '[' -f /tmp/aminglinux1 ']'
-
+ echo /tmp/aminglinux1 exist
-
/tmp/aminglinux1 exist
-
[ -d file ] 判断是否是目录,且存在
[root@aminglinux shell]# vim file2.sh [root@aminglinux shell]# cat file2.sh #! /bin/bash f="/tmp/aminglinuxd" if [ -d $f ] then echo $f exist else mkdir $f fi [root@aminglinux shell]# sh -x file2.sh + f=/tmp/aminglinuxd + '[' -d /tmp/aminglinuxd ']' + mkdir /tmp/aminglinuxd [root@aminglinux shell]# sh -x file2.sh + f=/tmp/aminglinuxd + '[' -d /tmp/aminglinuxd ']' + echo /tmp/aminglinuxd exist /tmp/aminglinuxd exist
- [ -e file ] 判断文件或目录是否存在
- 目录和文件都可以touch 的,touch的目的是 如果这个文件或目录不存在,它会创建这个文件,如果这个文件或目录存在了,在touch 就会更改这个文件的三个 time
[root@aminglinux shell]# vim file3.sh [root@aminglinux shell]# cat file3.sh #! /bin/bash f="/tmp/aminglinux1" if [ -e $f ] then echo $f exist else touch $f fi [root@aminglinux shell]# sh -x file3.sh + f=/tmp/aminglinux1 + '[' -e /tmp/aminglinux1 ']' + echo /tmp/aminglinux1 exist /tmp/aminglinux1 exist [root@aminglinux shell]# ll /tmp/ total 0 -rw-r--r-- 1 root root 0 Jul 29 17:23 aminglinux1
- [ -r file ] 判断文件是否可读
[root@aminglinux shell]# vim file4.sh [root@aminglinux shell]# cat file4.sh #! /bin/bash f="/tmp/aminglinux1" if [ -r $f ] then echo $f readable fi [root@aminglinux shell]# sh file4.sh /tmp/aminglinux1 readable
- [ -w file ] 判断文件是否可写
- [ -x file ] 判断文件是否可执行
[root@aminglinux shell]# !vim vim file4.sh [root@aminglinux shell]# sh file4.sh /tmp/aminglinux1 writeadable [root@aminglinux shell]# !vim vim file4.sh [root@aminglinux shell]# sh file4.sh [root@aminglinux shell]# //因为文件 没有执行权限,所以没有输入出
- 并且 &&
f="/tmp/aminglinux1" [ -f $f ] && rm -f $f //前一条命令执行成功才会继续执行之后的命令 等同于下面的表达方式 if [ -f $f ] then rm -rf $f fi
- 或者 ||
f="/tmp/aminglinux1" [ -f $f ] || touch $f //前面命令不成功时,执行后面的命令 if [ ! -f $f ] // “!”表示了如果这条命令不成功,就往下执行 then touch $f fi
if 特殊用法
-
if [ -z "$a" ] 这个表示当变量a的值为空时会怎么样
-
if [ -n "$a" ] 表示当变量a的值不为空
-
if grep -q '123' 1.txt; then 表示如果1.txt中含有'123'的行时会怎么样
-
if [ ! -e file ]; then 表示文件不存在时会怎么样
-
if (($a<1)); then …等同于 if [ $a -lt 1 ]; then…
-
中不能使用<,>,==,!=,>=,<=这样的符号
-
-n 判断变量的时候,需要用""双引号引起来,若是文件的时候,则不需要用双引号引起来
[root@aminglinux shell]# ls 1.sh file1.sh file2.sh file3.sh file4.sh if1.sh if2.sh if3.sh [root@aminglinux shell]# if [ -n 1.sh ]; then echo ok; fi ok [root@aminglinux shell]# if [ -n "$b" ]; then echo $b; else echo "b is null"; fi //当变量为空时时输出 b is null
- grep -wq 其中-w 后跟一个单词,-q仅仅做一个过滤
[root@aminglinux shell]# grep -w 'zabbix' /etc/passwd //查看zabbix用户是否存在 zabbix:x:996:993:Zabbix Monitoring System:/var/lib/zabbix:/sbin/nologin [root@aminglinux shell]# if grep -wq 'zabbix' /etc/passwd; then echo "zabbix exist"; fi //-q ,表示把grep -w的值过滤掉 zabbix exist
- if ! 取反值
[root@aminglinux shell]# if ! grep -wq 'zabbix' /etc/passwd; then echo useradd zabbix; fi //当没有zabix用户时创建用户,因zabbix用户存在,所以没有输出; [root@aminglinux shell]#
- if [ ! -e file ]; then 表示文件不存在时会怎么样
- if (($a<1)); then …等同于 if [ $a -lt 1 ]; then…
- 中不能使用<,>,==,!=,>=,<=这样的符号 一个等于号= 是赋值
case判断
-
shell脚本案例:
-
脚本目的是 输入一个数字,然后用脚本去判断这个数字的范围
[root@aminglinux shell]# vim case.sh #!/bin/bash #判断是否输入有数值,空直接结束整个文本 read -p "Please input a number: " n #read 让用户输出一些字符串;赋值给最后一个变量;这里的赋值是“n” if [ -z "$n" ] //变量n 为空 then echo "Please input a number." exit 1 // 知识点 1 fi #n1将输入的数值清空数字,检查变量是否为空,如果不为空,就证明输入有其他的字符,告知用户,请输入一个数字 n1=`echo $n|sed 's/[0-9]//g'` //确定,n变量是否为数字 if [ -n "$n1" ] then echo "Please input a number." exit 1 fi if [ $n -lt 60 ] && [ $n -ge 0 ] then tag=1 elif [ $n -ge 60 ] && [ $n -lt 80 ] then tag=2 elif [ $n -ge 80 ] && [ $n -lt 90 ] then tag=3 elif [ $n -ge 90 ] && [ $n -le 100 ] then tag=4 else tag=0 fi case $tag in 1) echo "not ok" ;; 2) echo "ok" ;; 3) echo "ook" ;; 4) echo "oook" ;; *) echo "The input value exceeds the calculation range.The number range is 0-100." ;; esac
- read -p " Please input a number: " n //shell中与用户交互输入数值
[root@aminglinux shell]# read -p " Please input a number: " n Please input a number: 100 //n赋值 100,输出为100 [root@aminglinux shell]# echo $n 100
shell 中 exit0 exit1 的区别:
- exit(0):正常运行程序并退出程序;
- exit(1):非正常运行导致退出程序;
- exit 0 可以告知你的程序的使用者:你的程序是正常结束的。如果 exit 非 0 值,那么你的程序的使用者通常会认为你的程序产生了一个错误。
- 在 shell 中调用完你的程序之后,用 echo $? 命令就可以看到你的程序的 exit 值。在 shell 脚本中,通常会根据上一个命令的 $? 值来进行一些流程控制。
for循环
- 语法:for 变量名 in 条件; do …; done
案例1
- 1+2+3..+100的和
- sum 第一次作为变量的时候,是0;当进入for循环里面的时候,每运算一次,sum变量就会改变一次,直至$i 结束;最后输出结果 $sum
- 在做加减法的时候,[ ] 方括号里面不需要加空格
[root@aminglinux shell]# vim for1.sh [root@aminglinux shell]# cat for1.sh #!/bin/bash sum=0 for i in `seq 1 100` #seq 1到100个数字 do sum=$[$sum+$i] echo $i done echo $sum [root@aminglinux shell]# sh -x for1.sh + sum=0 ++ seq 1 100 + for i in '`seq 1 100`' + sum=1 + echo 1 1 ...... + for i in '`seq 1 100`' + sum=5050 + echo 100 100 + echo 5050 5050
for循环案例2
- 文件列表循环
- 列出所有 etc目录下的子目录
[root@aminglinux shell]# vim for2.sh [root@aminglinux shell]# cat for2.sh #!/bin/bash cd /etc/ for a in `ls /etc/` do if [ -d $a ] then ls -d $a fi done
[root@aminglinux shell]# for a in `seq 1 3`; do echo $a; done 1 2 3 [root@aminglinux shell]# for a in 1 2 3; do echo $a; done 1 2 3
- for 循环的时候会以 空格 或者 回车做为分隔符
while循环
- 语法 while 条件; do … ; done
案例1
- 每隔1分钟检查一下系统负载,当系统的负载大于10的时候,发一封邮件(监控脚本)
- 最小单元是任务计划 cron
[root@aminglinux shell]# vim while1.sh [root@aminglinux shell]# cat while1.sh #!/bin/bash while : # 冒号 : 表示死循环的意思,或者1,或者 true都是死循环 do load=`w|head -1|awk -F 'load average: ' '{print $2}'|cut -d. -f1` if [ $load -gt 10 ] then /usr/local/sbin/mail.py xxx@163.com "load high" "$load" fi sleep 30 #休眠30秒,因为检查系统负载,不需要一直去检查,过一会再看 done [root@yong-01 shell]# sh -x while1.sh + : ++ w ++ head -1 ++ awk -F 'load average:' '{print $2}' ++ cut -d. -f1 + load=' 0' + '[' 0 -gt 10 ']' + sleep 30 若想这种脚本不意外的终止,可以打开screen,在screen跑脚本
知识点
- w //查看系统负载 ;
- uptime 可以直接显示 w 系统负载的第一行,就可以省去 head -1
- head -1 //取第一行
- awk -F 'load average: ' '{print $2}' // 以'load average: '分隔,输出第二段
- cut -d . -f1 // 以 . 分隔 取第一段
while循环案例2
- 在循环过程过,需要用户输入一个数字;输入的不是数字,是数字,输入为空;回应相应的结果
[root@aminglinux shell]# vim while2.sh [root@aminglinux shell]# cat while2.sh #!/bin/bash while : do read -p "Please input a number: " n if [ -z "$n" ] then echo "you need input sth." continue #continue 重新回到循环 fi n1=`echo $n|sed 's/[0-9]//g'` if [ -n "$n1" ] then echo "you just only input numbers." continue fi break #break 退出循环 done echo $n
break跳出循环
- break 常用于循环语句中
- 跳出整个循环语句,直接结束所有循环
[root@aminglinux shell]# vim break.sh [root@aminglinux shell]# cat break.sh #!/bin/bash for i in `seq 1 5` do echo $i if [ $i -eq 3 ] #比较数字,用-eq ;若是比较的是字符串,那需要用 == then break fi echo $i done echo AAA
[root@aminglinux shell]# sh -x break.sh ++ seq 1 5 + for i in '`seq 1 5`' + echo 1 1 + '[' 1 -eq 3 ']' + echo 1 1 + for i in '`seq 1 5`' + echo 2 2 + '[' 2 -eq 3 ']' + echo 2 2 + for i in '`seq 1 5`' + echo 3 3 + '[' 3 -eq 3 ']' + break + echo AAA AAA
continue结束本次循环
- 忽略continue之下的代码,直接进行下一次循环
[root@aminglinux shell]# vim continue.sh [root@aminglinux shell]# cat continue.sh #!/bin/bash for i in `seq 1 5` do echo $i if [ $i -eq 3 ] then continue fi echo $i done echo AAA
[root@aminglinux shell]# sh continue.sh 1 1 2 2 3 4 4 5 5 AAA
exit退出整个脚本
- exit直接结束退出整个脚本
- 可以定义退出的数值,可以用于确定脚本运行到什么地方的时候,结束
[root@aminglinux shell]# vim exit.sh [root@aminglinux shell]# cat exit.sh #!/bin/bash for i in `seq 1 5` do echo $i if [ $i -eq 3 ] then exit fi echo $i done echo AAA [root@aminglinux shell]# sh exit.sh 1 1 2 2 3