




版权说明:本文档由用户提供并上传,收益归属内容提供方,若内容存在侵权,请进行举报或认领
文档简介
【移动应用开发技术】简单的Shell脚本
shell脚本的基本结构以及如何执行[root@localhost
script]#
cat
1.sh
#!/bin/bash
#The
first
shell
script
#Writen
by
Justin
2015-01-07
date
echo
"Hello
World"
[root@localhost
script]#
./1.sh
-bash:
./1.sh:
Permission
denied
[root@localhost
script]#
sh
1.sh
Wed
Jan
7
05:15:38
CST
2015
Hello
World
[root@localhost
script]#
chmod
+x
1.sh
[root@localhost
script]#
./1.sh
Wed
Jan
7
05:15:50
CST
2015
Hello
World
[root@localhost
script]#
sh
-x
1.sh
+
date
Wed
Jan
7
07:29:29
CST
2015
+
echo
'Hello
World'
Hello
World
[root@localhost
script]#以上为一个简单的shell脚本和执行,Shell脚本通常都是以.sh
为后缀名,不是说不带.sh就不是脚本,“#!/bin/bash”
它代表的意思是,该文件使用的是bash语法,其中#表示该行是注释,叹号“!”告诉shell运行叹号之后的命令并用文件的其余部分作为输入,也就是运行/bin/bash并让/bin/bash去执行shell程序的内容。后面跟一些该脚本的相关注释内容以及作者和创建日期或者版本等等,这些注释并非必须的,可以省略掉,但是不建议省略。因为随着你工作时间的增加,你写的shell脚本也会越来越多,如果有一天你回头查看你写的某个脚本时,很有可能忘记该脚本是用来干什么的以及什么时候写的,所以写上注释是有必要的。Shell脚本的执行很简单,直接”shfilename“
即可,也可以加一个执行权限,直接使用’./filename’
执行这个脚本。另外使用sh命令去执行一个shell脚本的时候是可以加-x选项来查看这个脚本执行过程,也可以在脚本里写上set-x或者set-xv,这样只执行脚本时候就会显示执行的每条命令,这样有利于我们调试这个脚本哪里出了问题。使用-n可以检查是否有错误[root@localhost
src]#
sh
-n
install-tomcat.sh
install-tomcat.sh:
line
72:
syntax
error:
unexpected
end
of
file
[root@localhost
src]#使用-vx调试脚本每行代码原始命令(无+的):-v的效果代码执行时的情况(带+),包括运算结果,逻辑判断结果,变量赋值等等:-x的效果syntaxerror:unexpectedendoffile:如果是在windows环境下编写的shell脚本上传到linux下需要把dos文件转换成unix文件格式,否则会出现报错:syntaxerror:unexpectedendoffile:dos格式文件传输到unix系统时,会在每行的结尾多一个^M,而linux下的是没有的[root@localhost
~]#
cat
-A
linux.txt
linux$
windows$
[root@localhost
~]#
cat
-A
windows.txt
windows^M$
linux
最后一行行末没有换行符;
[root@localhost
~]#
[root@localhost
~]#vimwindows.txt末尾提示[noeol]120L,2532C信息,'noeol'就是'noend-of-line',即“没有行末结束符”,vimwindows.txt,不做任何修改直接:wq保存退出换行符已经追加上去,如果提示
"dos.txt"[dos]120L,2532C
字样,表示是一个[dos]格式文件,如果是MAC系统的,会显示[MAC],因为文件格式的原因有时会导致我们的unix程序,或者shell程序出现错误,那么需要把这些dos文件格式转换成unix格式,方法是
vi
dos.txt
:setfileformat=unix
:w
这样文件就转换成unix格式文件了,或者使用dos2unix
yum-yinstall
dos2unix
dos2unixfilename.sh如果还是报错syntaxerror:unexpectedendoffile检查语法出现中文乱码的问题此问题是因执行定时任务时没有去获取系统的环境变量,导致了中文乱码。在shell脚本开始的时候加下命令:exportLANG="en_US.UTF-8"#!/bin/sh
export
LANG="en_US.UTF-8"crontab里脚本不执行手动执行脚本正常,加入到crontab里后脚本不执行,这是因为crontab没有读取环境变量,脚本中的部分命令不是用的绝对路径无法找到,可以在脚本开头读取环境变量或者所有命令使用绝对路径[
-f
~/.bash_profile
]
&&
.
~/.bash_profile
[
-f
/etc/profile]
&&
.
/etc/profileshell脚本中的变量$?是显示最后命令的退出状态,0表示没有错误,其他表示有错误$$ Shell本身的PID(ProcessID)$! Shell最后运行的后台Process的PID$- 使用Set命令设定的Flag一览$#是传给脚本的参数个数$0是脚本本身的名字$1是传递给该shell脚本的第一个参数$2是传递给该shell脚本的第二个参数$$是脚本运行的当前进程ID号$*是以一个单字符串显示所有向脚本传递的参数,与位置变量不同,参数可超过9个$@:是传给脚本的所有参数的列表,即被扩展为"$1""$2""$3"等;最后一个参数:${@:-1}$*:是以一个单字符串显示所有向脚本传递的参数,与位置变量不同,参数可超过9个,即被扩展成"$1c$2c$3",其中c是IFS的第一个字符;${!#}、${@:-1}输出最后一个参数${@:$#-1:1}
倒数第二个参数[root@localhost
script]#
cat
2.sh
#!/bin/bash
#This
script,we
will
use
variables.
#Write
by
Justin
2015-01-07
x=`date
+%H:%M:%S`
echo
"the
script
begin
at
$x"
echo
"The
script
end
after
2
seconds"
sleep
2
y=`date
+%H:%M:%S`
echo
"The
script
end
at
$y"
[root@localhost
script]#
sh
2.sh
the
script
begin
at
14:22:08
The
script
end
after
2
seconds
The
script
end
at
14:22:10
[root@localhost
script]#脚本中调用了命令date所以使用了反引号,在调用变量时需要加上符号$,这个和在shell中定义变量是一致的。[root@localhost
script]#
cat
3.sh
#!/bin/bash
a=1
b=2
sum=$[$a+$b]
echo
"sum
is
$sum"
[root@localhost
script]#
sh
3.sh
sum
is
3
[root@localhost
script]#数学计算要用’[]’括起来并且外头要带一个’$’。[root@localhost
script]#
cat
4.sh
#!/bin/bash
echo
"please
input
a
number:"
read
x
echo
"please
input
another
number:"
read
y
sum=$[$x+$y]
echo
"The
sum
of
tow
number
is:$sum"
[root@localhost
script]#
sh
4.sh
please
input
a
number:
3
please
input
another
number:
5
The
sum
of
tow
number
is:8
[root@localhost
script]#
sh
-x
4.sh
+
echo
'please
input
a
number:'
please
input
a
number:
+
read
x
3
+
echo
'please
input
another
number:'
please
input
another
number:
+
read
y
5
+
sum=8
+
echo
'The
sum
of
tow
number
is:8'
The
sum
of
tow
number
is:8
[root@SAMBA1
infa_shared]#
echo
`date
+"%Y-%m-%d
%H:%M:%S"`
>
read-only.txt
[root@SAMBA1
infa_shared]#
cat
read-only.txt
2015-11-25
15:56:56
[root@SAMBA1
infa_shared]#
y=`date
+"%Y-%m-%d
%H:%M:%S"`
[root@SAMBA1
infa_shared]#
echo
$y
2015-11-25
15:58:27
[root@SAMBA1
infa_shared]#Shell脚本可以和用户交互。这就用到了read命令了,它可以从标准输入获得变量的值,后跟变量名。”readx”表示x变量的值需要用户通过键盘输入得到。我们可以直接使用read-p来代替echo的作用[root@localhost
script]#
cat
5.sh
#!/bin/bash
read
-p
"please
input
a
number:"
x
;x前有个空格
read
-p
"please
input
another
number:"
y
sum=$[$x+$y]
echo
"The
sum
of
tow
number
is:$sum"
[root@localhost
script]#
sh
-x
5.sh
+
read
-p
'please
input
a
number:'
x
please
input
a
number:3
+
read
-p
'please
input
another
number:'
y
please
input
another
number:5
+
sum=8
+
echo
'The
sum
of
tow
number
is:8'
The
sum
of
tow
number
is:8
[root@localhost
script]#”/etc/init.d/iptablesrestart“
前面的/etc/init.d/iptables
就是一个shell脚本,后面”restart”是了shell脚本的预设变量。上面例子我们可以通过设置预设变量[root@localhost
script]#
cat
5.sh
#!/bin/bash
sum=$[$1+$2]
echo
"The
sum
of
tow
number
is:$sum"
echo
"$0"
[root@localhost
script]#
sh
-x
5.sh
3
5
+
sum=8
+
echo
'The
sum
of
tow
number
is:8'
The
sum
of
tow
number
is:8
+
echo
'5.sh'
5.sh
[root@localhost
script]#$1和$2就是shell脚本的预设变量,其中$1的值就是在执行的时候输入的3,而$2的值就是执行的时候输入的5,一个shell脚本的预设变量是没有限制的,$0代表的是脚本本身的名字。set-x与set+x指令用于脚本调试。set是把它下面的命令打印到屏幕set-x是开启set+x是关闭set-o是查看(xtrace),set去追中一段代码的显示情况。set
-x
/usr/local/bin/sendEmail
-s
"$SMTP_Server"
-xu
"$username"
-xp
"$password"
-f
"$from_email_address"
-t
"$to_email_address"
-u
"$message_subject_utf8"
-m
"$message_body_utf8"
-o
message-content-type=text
-o
message-charset=utf-8shell脚本中的算术运算sum=$[$x+$y]sum=$[$x+1]
#xy是变量shell脚本中的逻辑判断if判断语句:1)不带else格式:if
判断语句;thencommandfi[root@localhost
script]#
cat
if1.sh
#!
/bin/bash
read
-p
"please
input
your
score:"
a
if
((a<60));then
echo
"You
didn't
pass
the
exam.you
score
is
$a"
fi
[root@localhost
script]#
sh
if1.sh
please
input
your
score:33
You
didn't
pass
the
exam.you
score
is
33
[root@localhost
script]#上面出现了
((a<60))这样的形式,这是shell脚本中判断数值大小特有的格式,用一个小括号或者不用都会报错,请记住这个格式,在判断数值大小除了可以用”(())”的形式外,还可以使用”[]”。但是就不能使用>,<,=,!=这样的符号了,要使用
-lt
(小于),-gt
(大于),-le
(小于等于),-ge
(大于等于),-eq
(等于),-ne
(不等于),这种类型在while循环中使用多常见错误:[$Sum-ne0]:line5:[:-ge:unaryoperatorexpected$Sum为空,那么就成了[
-ge"0"]了,显然[和"0"不相比较并且缺少了[符号,所以报了这样的错误。解决办法:赋值前加declare-irate=0declare命令可用来声明变量并设置变量的属性,还可以可用来显示shell函数。语法:declare[+/-][rxi][变量名称=设置值]或declare-f参数说明:+/-"-"可用来指定变量的属性,"+"则是取消变量所设的属性。-f函数,declare-f列出所有在此脚本前面已定义的函数出来;declare-ffunction_name列出指定的函数-F
仅打印函数名字-r将变量设置为只读:declare-rvar1x指定的变量会成为环境变量,可供shell以外的程序来使用。-i
声明变量为整数:declare-inumber-a
声明变量为数组:declare-aindices-x
声明一个变量作为脚本的环境变量而被导出,declare-xvar3;declare-xvar3=373declare命令允许在声明变量类型的时候同时给变量赋值:declare-irate=0rate+=1
#整数声明后,不需要使用'let'.let命令用于指定算术运算,即letexpretion,用于执行一个或多个表达式,使用let执行运算时,变量名之前不需要添加$。如果表达式中包含了空格或其他特殊字符,则必须引起来。例如:a=1b=2letresult=a+becho$resulta=2let"a+=1"let″val=a|b″
如果不括起来,Shell会把命令行letval=a|b中的“|”看成管道符,将其左右两边看成不同的命令,因而无法正确执行利用(())执行数学运算。使用(())执行算数运算时,变量名之前可以加$,也可不加$。利[]执行数学运算。使用[]执行算数运算时,变量名之前可以加$,也可不加$。let表达式支持++,--的操作,但是不支持++a--a这样前缀a=a+1;
//即最普通的写法,将a的值加1再赋给aa+=1;
//相当于a=a+1;a++;
//是先将a的值赋给一个变量,再自增,例如:b=a++等同于b=a;a=a+1;++a;
//是先自增,再把a的值给一个变量,例如:b=++a等同于
a=a+1;b=a;2)带有else格式:if
判断语句
;thencommandelsecommandfi[root@localhost
script]#
cat
if1.sh
#!
/bin/bash
read
-p
"please
input
your
score:"
a
if
((a<60));then
echo
"You
didn't
pass
the
exam.you
score
is
$a"
else
echo
"GOOD!
You
passed
the
exam,you
score
is
$a."
fi
[root@localhost
script]#
sh
if1.sh
please
input
your
score:67
GOOD!
You
passed
the
exam,you
score
is
67.
[root@localhost
script]#
sh
if1.sh
please
input
your
score:33
You
didn't
pass
the
exam.you
score
is
33
[root@localhost
script]#linux-gnv2:/opt/FlashServer/flashserver
#
cat
restart.sh
#!/bin/bash
x=`ps
-ef|grep
'flashserver'|grep
-v
grep|grep
-v
nohup|awk
-F
"
"
$2}'`
y=`ps
-ef|grep
'flashserver'|grep
-v
grep|grep
-v
nohup|wc
-l`
if
[
$y
-ge
1
]
then
sudo
kill
-9
$x
sleep
2
else
echo
"no
service
exist"
fi
nohup
./flashserver
>/dev/null
&
y=`ps
-ef|grep
'flashserver'|grep
-v
grep|grep
-v
nohup|wc
-l`
sleep
1
if
[
$y
-ge
1
]
then
echo
"start
service
success"
else
echo
"start
service
fail"
fi
linux-gnv2:/opt/FlashServer/flashserver
#[root@QuoteService
Release]#
cat
RestartQuoteServer.sh
#!/bin/bash
x=`pgrep
QuotePlatform`
y=`ps
-ef|grep
'QuotePlatform'|grep
-v
grep|wc
-l`
z="/usr/local/QuoteService/make/Release"
if
[
$y
-ge
1
];then
kill
-9
$x
sleep
2
yy=`ps
-ef|grep
'QuotePlatform'|grep
-v
grep|wc
-l`
#pgrep
QuotePlatform是变量,每次应用都需要重新定义变量,不重新定义就是第一次赋予的值
if
[
$yy
-le
0
];then
echo
"QuotePlatform
server
is
not
running!"
cd
$z
nohup
./QuotePlatform
>/dev/null
&
sleep
3
yyy=`ps
-ef|grep
'QuotePlatform'|grep
-v
grep|wc
-l`
if
[
$yyy
-ge
1
];then
echo
"QuotePlatform
service
successfully
started!"
else
echo
"QuotePlatform
service
startup
failed!
"
fi
else
echo
"Kill
QuotePlatform
service
is
failed!"
fi
else
echo
"QuotePlatform
server
is
not
running!"
cd
$z
nohup
./QuotePlatform
>/dev/null
&
sleep
3
yyyy=`ps
-ef|grep
'QuotePlatform'|grep
-v
grep|wc
-l`
if
[
$yyyy
-ge
1
];then
echo
"QuotePlatform
service
successfully
started!"
else
echo
"QuotePlatform
service
startup
failed!
"
fi
fi多判断条件:同时满足三个文件大小[root@localhost
src]#
cat
test.sh
#!/bin/bash
nagiossize=`du
-k
nagios-plugins-1.4.16.tar.gz|awk
$1}'`
nrpesize=`du
-k
nrpe-2.15.tar.gz|awk
$1}'`
zabbixsize=`du
-k
zabbix-2.2.2.tar.gz|awk
$1}'`
if
[
$zabbixsize
-ge
14200
]
&&
[
$nagiossize
-ge
2000
]
&&
[
$nrpesize
-ge
400
];then
echo
"download
is
successful"
else
echo
"download
is
failed"
fi
[root@localhost
src]#
sh
test.sh
download
is
successful
[root@localhost
src]#
-a或者and或者&&
if((a>b))&&((a<c))
if[$a>$b]&&[$a<$c]]
if[$a-gt$b-a$a-lt$c]
-o或者or或者||
if((a>b))||((a<c))
if[$a>$b]||[$a<$c]
if[$a-gt$b-o$a-lt$c]
3)带有elif格式:if[expression1]then
Statement(s)tobeexecutedifexpression1istrueelif[expression2]then
Statement(s)tobeexecutedifexpression2istrueelif[expression3]then
Statement(s)tobeexecutedifexpression3istrueelse
Statement(s)tobeexecutedifnoexpressionistruefi哪一个expression的值为true,就执行哪个expression后面的语句;如果都为false,那么不执行任何语句。[root@localhost
script]#
cat
if1.sh
#!
/bin/bash
read
-p
"please
input
your
score:"
a
if
((a<60));then
echo
"You
didn't
pass
the
exam.you
score
is
$a"
elif
((a>60))
&&
((a<85));then
echo
"GOOD!
You
passed
the
exam,you
score
is
$a."
else
echo
"Very
Good!
You
score
is
$a,it's
very
hight!"
fi
[root@localhost
script]#
sh
if1.sh
please
input
your
score:33
You
didn't
pass
the
exam.you
score
is
33
[root@localhost
script]#
sh
if1.sh
please
input
your
score:77
GOOD!
You
passed
the
exam,you
score
is
77.
[root@localhost
script]#
sh
if1.sh
please
input
your
score:99
Very
Good!
You
score
is
99,it's
very
hight!
[root@localhost
script]#逻辑运算符&&
表示“并且”,
||
表示“或者”。判断文件(夹)是否存在注意:单引号和双引号的区别。单引号告诉shell忽略所有特殊字符,而双引号忽略大多数,但不包括$、\、`,即双引号保有变量的内容,但单引号内仅能是一般字符,而不会有特殊符号。#!/bin/bash
myPath="/usr/local/src/dir/test"
myFile="/usr/local/src/access.log"
#这里的-d参数判断$myPath是否存在,注意[]前后空格
if
[
-d
"$myPath"
];then
cd
"$myPath"
tar
-cvf
myPath.tar
*
else
mkdir
-p
/usr/local/src/dir/test
echo
"$myPath
is
created"
touch
/usr/local/src/dir/test/1
touch
/usr/local/src/dir/test/2
touch
/usr/local/src/dir/test/3
fi#!/bin/bash
myPath="/usr/local/src/dir/test"
myFile="/usr/local/src/access.log"
#这里的-f参数判断$myPath是否存在
if
[
!
-f
"$myFile"
];then
touch
"$myFile"
echo
"test"
>
"$myFile"
else
cat
"$myFile"
fi#!/bin/bash
#这里的-x参数判断$myPath是否存在并且有可执行权限
if
[
!
-x
'/usr/local/src/'
];then
chmod
+x
/usr/local/src/
ll
-d
/usr/local/src/
else
cd
"$myPath"
&&
tar
-cvf
tar.tar
/usr/local/src/*
tar
-tvf
tar.tar
fi
#!/bin/bash
MyFile=`command
-v
ntpdate`
if
[
!
-x
"$MyFile"
];then
yum
-y
install
ntp
cat
>>
/var/spool/cron/root
<<
EOF
0
*/12
*
*
*
/usr/sbin/ntpdate
EOF
/sbin/hwclock
--systohc
/etc/init.d/crond
restart
else
cat
>>
/var/spool/cron/root
<<
EOF
0
*/12
*
*
*
/usr/sbin/ntpdate
EOF
/sbin/hwclock
--systohc
/etc/init.d/crond
restart
fi#!/bin/bash
#两个变量判断是否相等
if
[
"$var1"
==
"$var2"
];
then
echo
'$var1
eq
$var2'
else
echo
'$var1
not
eq
$var2'
fi其他参数:[-aFILE]如果FILE存在则为真。[-bFILE]如果FILE存在且是一个块特殊文件则为真。[-cFILE]如果FILE存在且是一个字特殊文件则为真。[-dFILE]如果FILE存在且是一个目录则为真。[-eFILE]如果FILE存在则为真。[-fFILE]如果FILE存在且是一个普通文件则为真。[-gFILE]如果FILE存在且已经设置了SGID则为真。[-hFILE]如果FILE存在且是一个符号连接则为真。[-kFILE]如果FILE存在且已经设置了粘制位则为真。[-pFILE]如果FILE存在且是一个名字管道(F如果O)则为真。[-rFILE]如果FILE存在且是可读的则为真。[-sFILE]如果FILE存在且大小不为o则为真。[-tFD]如果文件描述符FD打开且指向一个终端则为真。[-uFILE]如果FILE存在且设置了SUID(setuserID)则为真。[-wFILE]如果FILE如果FILE存在且是可写的则为真。[-xFILE]如果FILE存在且是可执行的则为真。[-OFILE]如果FILE存在且属有效用户ID则为真。[-GFILE]如果FILE存在且属有效用户组则为真。[-LFILE]如果FILE存在且是一个符号连接则为真。[-NFILE]如果FILE存在andhasbeenmod如果iedsinceitwaslastread则为真。[-SFILE]如果FILE存在且是一个套接字则为真。[FILE1-ntFILE2]如果FILE1hasbeenchangedmorerecentlythanFILE2,or如果FILE1existsandFILE2doesnot则为真。[FILE1-otFILE2]如果FILE1比FILE2要老,或者FILE2存在且FILE1不存在则为真。[FILE1-efFILE2]如果FILE1和FILE2指向相同的设备和节点号则为真。[-oOPTIONNAME]如果shell选项“OPTIONNAME”开启则为真。[-zSTRING]“STRING”的长度为零则为真。[-nSTRING]“STRING”的长度为非零o则为真。注意:STRING如果时变量,需要时用双引号或者使用"[[]]",否则当STRING为空值时就变成了[STRING],shell会把它当作[-n]来处理。[STRING1==STRING2]如果2个字符串相同。“=”maybeusedinsteadof“==”forstrictPOSIXcompliance则为真。[STRING1!=STRING2]如果字符串不相等则为真。[STRING1<STRING2]如果“STRING1”sortsbefore“STRING2”lexicographicallyinthecurrentlocale则为真。[STRING1>STRING2]如果“STRING1”sortsafter“STRING2”lexicographicallyinthecurrentlocale则为真。判断文件是否存在特定字符串grep-q
[root@finchina
~]#
cat
a.txt
nihao
nihaooo
hello
[root@finchina
~]#
if
grep
-q
hellooooo
a.txt
;then
echo
'hello
is
exist';else
echo
'hello
is
not
exist';fi
hello
is
not
exist
[root@finchina
~]#case判断语句格式:case
变量
invalue1)command;;value2)command;;value3)command;;*)command;;esac上面的结构中,不限制value的个数,*则代表除了上面的value外的其他值,case行尾必须为单词“in”,每一个模式必须以右括号“)”结束。双分号“;;”表示命令序列结束。匹配模式中可是使用方括号表示一个连续的范围,如[0-9];使用竖杠符号“|”表示或。最后的“*)”表示默认模式,当使用前面的各种模式均无法匹配该变量时,将执行“*)”后
的命令序列。[root@localhost
script]#
cat
case.sh
#!/bin/bash
read
-p
"please
input:"
n
case
$n
in
[0-9]*)
echo
"You
input
a
number:$n"
;;
[a-z]*|[A-Z]*)
echo
"You
input
a
letter:$n"
;;
*)
echo
"You
input
is
not
a
digital
or
not
characters:$n"
;;
esac
[root@localhost
script]#
sh
case.sh
please
input:111112222
You
input
a
number:111112222
[root@localhost
script]#
sh
case.sh
please
input:afdfdaf
You
input
a
letter:afdfdaf
[root@localhost
script]#
sh
case.sh
please
input:**(*
You
input
is
not
a
digital
or
not
characters:**(*
[root@localhost
script]#case脚本常用于编写系统服务的启动脚本,例如/etc/init.d/iptables中就用到了read命令:read命令接收标准输入(键盘)的输入,或其他文件描述符的输入(后面在说)。得到输入后,read命令将数据放入一个标准变量中。语法read(选项)(参数)主要参数:-t
等待时间,eg、read-t5-p"pleaseenteryourname:"nameread
-t
5
-p
"please
enter
your
name:"
name-p允许在read命令行中直接指定一个提示read
-p
"Enter
your
name:"
name
echo
"hello
$name,
welcome
to
my
program"-n计算输入字符数
read
-n1
-p
"Do
you
want
to
continue
[Y/N]?"
answer指示read命令只要接受到一个字符就退出。只要按下一个字符进行回答,read命令立即接受输入并将其传给变量。无需按回车键#!/bin/bash
read
-n1
-p
"Do
you
want
to
continue
[Y/N]?"
answer
case
$answer
in
Y
|
y)
echo
"fine
,continue";;
N
|
n)
echo
"ok,good
bye";;
*)
echo
"error
choice";;
esac
exit
0-s选项能够使read命令中输入的数据不显示在监视器上(实际上,数据是显示的,只是read命令将文本颜色设置成与背景相同的颜色)。read
-s
-p
"Enter
your
password:"
passshell脚本中的循环for循环结构
:for
变量名
in
循环的条件;
docommanddone或for((初始语句;执行条件;增量));docommanddone执行顺序:1、初始语句
2、执行条件是否符合?
3、循环体
4、增加增量
初始化语句只在循环开始前执行一次,每次执行循环体时要先判断是否符合条件,如果循环条件还会true,则执行循环体,在执行迭代语句。所以对于for循环,循环条件总比循环体多执行一次。[root@localhost
script]#
cat
for.sh
#!/bin/bash
#for
i
in
`seq
0
5`
#这里是反引号
#for
i
in
{0..5}
for
i
in
0
1
2
3
4
5
do
echo
$i
done
[root@localhost
script]#
sh
for.sh
0
1
2
3
4
5
[root@localhost
script]#
cat
for.sh
#!/bin/bash
for
i
in
`tail
-5
/etc/passwd`
do
x=`echo
$i|awk
-F':'
$1"\t"$7}'`
echo
$x
done
[root@localhost
script]#
cat
for.sh
#!/bin/bash
for
i
in
`cat
/etc/passwd`
do
x=`echo
$i|awk
-F':'
$1"\t"$7}'`
echo
$x
done
[root@localhost
script]#
cat
for.sh
#!/bin/bash
for
i
in
$(cat
/etc/passwd)
do
x=`echo
$i|awk
-F':'
$1"\t"$7}'`
echo
$x
done
[root@localhost
script]#
[root@localhost
script]#
sh
for.sh
tcpdump
/sbin/nologin
[root@localhost
script]#
cat
for.sh
#禁止udp对外发包
#!/bin/bash
dns=`grep
-i
nameserver
/etc/resolv.conf|awk
$NF}'`
for
i
in
$dns
do
iptables
-A
OUTPUT
-p
udp
-d
$i
--dport
53
-j
ACCEPT
done
iptables
-A
OUTPUT
-p
udp
-j
DROP
service
iptables
save
[root@Zabbix
~]#
sh
for.sh
iptables:
Saving
firewall
rules
to
/etc/sysconfig/iptables:[
OK
]
[root@Zabbix
~]#seq05
表示从0到5的一个序列,seq默认从0开始,[root@localhost
script]#
cat
for.sh
#!/bin/bash
for
((i=1;i<=19;i++))
do
if((i%3==0));then
echo
$i
fi
done
[root@localhost
script]#
sh
for.sh
3
6
9
12
15
18
[root@localhost
script]#for语法循环有点像C语法,但记得双括号循环控制break/continue
break和continue都是用来控制循环结构的,主要是停止循环。
break用于完全结束一个循环,跳出循环体,不再执行后面循环,breakn表示"从里向外"打断第n个循环,默认值为break1,也就是打断当前的循环。
continue只是跳过当次循环中剩下的语句,但是会继续执行下一次循环。continuen表示继续从哪一层(从里向外计算)的循环,默认值为continue1,也就是继续当前的循环。[root@localhost
src]#
cat
for.sh
#!/bin/bash
for
((i=7000;i<8101;i++))
do
if
[
$i
-ge
7101
]
&&
[
$i
-le
7999
];then
continue
else
echo
$i
fi
done
[root@localhost
src]#这里执行的结果是输出7000-7100、8000-8100,当循环到7101时候continue会终止这次7101的循环,后面一次类推,如果continue换成break的话只输出7000-7100,当循环到7101时候if判断为真,执行break跳出当前循环,如果这里for的外面还有一个循环体系,要跳出该循环体系的话使用break2;一次类推break3while循环格式:while
条件;docommanddone[root@localhost
script]#
cat
while.sh
#!/bin/bash
min=1
max=20
#while
(($min<=$max))
while
[
$min
-le
$max
]
;[后面、]前面有个空格
do
echo
$min
min=$[$min+1]
done
[root@localhost
script]#
sh
while.sh
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
[root@localhost
script]#.循环控制语句
#break命令不执行当前循环体内break下面的语句从当前循环退出.
#continue命令是程序在本循体内忽略下面的语句,从循环头开始执行while逐行读取文件WhilereadLINEwhile循环中执行效率最高,最常用的方法:WhilereadLINEdoecho$LINEdone
<$FILENAME}[root@token1
git]#
cat
while.sh
#!/bin/bash
ls
-l
/app/git|grep
-v
total|awk
$NF}'
>
/tmp/git.txt
while
read
line
do
cd
/app/git/$line
git
add
.
git
commit
-am
"add
new
repo
$line"
git
remote
rm
origin
git
remote
add
origin
git@43:$line.git
git
push
origin
master
done
<
/tmp/git.txt
[root@token1
git]#或者[root@token1
git]#
cat
while.sh
#!/bin/bash
ls
-l
/app/git|grep
-v
total|awk
$NF}'
>
/tmp/git.txt
cat
/tmp/git.txt|while
read
line
do
cd
/app/git/$line
git
add
.
git
commit
-am
"add
new
repo
$line"
git
remote
rm
origin
git
remote
add
origin
git@43:$line.git
git
push
origin
master
done
[root@token1
git]#对循环重定向的输入可适用于循环中的所有需要从标准输入读取数据的命令;对循环重定向的输出可适用于循环中的所有需要向标准输出写入数据的命令;当在循环内部显式地使用输入或输出重定向,内部重定向覆盖外部重定向。read通过输入重定向,把file的第一行所有的内容赋值给变量line,循环体内的命令一般包含对变量line的处理;然后循环处理file的第二行、第三行。。。一直到file的最后一行。还记得while根据其后的命令退出状态来判断是否执行循环体吗?是的,read命令也有退出状态,当它从文件file中读到内容时,退出状态为0,循环继续惊醒;当read从文件中读完最后一行后,下次便没有内容可读了,此时read的退出状态为非0,所以循环才会退出。whilereadline只读一行或者最后一行读不到[root@Super
remote-excet]#
cat
remote-excet_ipfile.sh
for
ip
in
`cat
$2`
do
/usr/local/bin/sshpass
-p
123
ssh
-n
-o
StrictHostKeyChecking=no
-tt
root@$ip
'uptime'
done
[root@Super
remote-excet]#原因是循环里ssh进入了另一个进程,导致输入中断。while中使用重定向机制,$2文件中的信息都已经读入并重定向给了整个while语句。所以当我们在while循环中再一次调用read语句,就会读取到下一条记录。问题就出在这里,ssh语句正好会读取输入中的所有东西,而for就没这个问题了Tips:如果脚本你是直接在windows下通过记事本类工具编写传到linux上给了执行权限后使用./来执行发现无法执行,而通过sh就可以[root@localhost
src]#
chmod
+x
linux_nagios_client.sh
[root@localhost
src]#
./linux_nagios_client.sh
-bash:
./linux_nagios_client.sh:
/bin/bash^M:
bad
interpreter:
No
such
file
or
directory
[root@localhost
src]#
sh
linux_nagios_client.sh
Loaded
plugins:
fastestmirror,
product-id,
subscription-manager
This
system
is
not
registered
to
Red
Hat
Subscription
Management.
You
can
use
subscription-manager
to
register.
Loading
mirror
speeds
from
cached
hostfile
Setting
up
Group
Process出现上面错误的原因之一是脚本文件是DOS格式的,即每一行的行尾以\r\n来标识,使用vim编辑器打开脚本,运行::setff?可以看到DOS或UNIX的字样.使用setff=unix把它强制为unix格式的,然后存盘退出,即可.切换用户并执行命令#!/bin/bash
su
-
oracle
<<
EOF
salplus
/
as
sysdba
startup
exit
EOF
#su
-
oracle
-c
"salplus
/
as
sysdba
&&
startup"
lsnrctl
start添加脚本运行的日志有时候脚本运行我们希望看到运行的记录情况,这时候我们可以在脚本里定义将运行的结果写入到日志里。在脚本开头定义日志信息#!/bin/bash
LOGFILE="/var/log/sendEmail.log"
:>"$LOGFILE"
exec
1>>"$LOGFILE"
exec
2>&1注意:添加以上行后所有标准输出信息都重定向到/var/log/sendEmail.log文件中,界面中无法看到输出信息,如果有交互的操作也无法看到提示信息,此时应避免这种方式exec1:0(stdin,标准输入)、1(stdout,标准输出)、2(stderr,标准错误输出)冒号在shell中表示空指令:>file
清空文件file的内容设定缺省值(:=):1.1未定义时,生成缺省值,:${VAR:=DEFAULT}
当变量VAR没有声明或者为NULL时,将VAR设置为默认值DEFAULT。如果不在前面加上:命令,那么就会把${VAR:=DEFAULT}本身当做一个命令来执行,报错是肯定的。
1.2空值时,有冒号就生成缺省值;
1.3有值时,不覆盖.缺省值(:-):
2.1未定义时,原变量str不会变;返回值var可覆盖;
2.2空值时,变量str不会变;
2.3有值时,不覆盖.覆盖缺省值(:+):3.1未定义时,原变量str,返回值var不会变;
3.2空值时,原变量str不会变;
3.3有值时,覆盖变量str的缺省值注意:1.=,-有值时,原变量不变,只有:+才能覆盖;2.+,-无值时,原变量str仍为空.如果需要把信息打印屏幕同时写入日志可以使用mkfifo来实现#!/bin/bash
export
LANG="en_US.UTF-8"
error_log='/tmp/error_log.log'
info_log='/tmp/info_log.log'
:>"$error_log"
:>"$info_log"
rm
-rf
/tmp/info.fifo
rm
-rf
/tmp/error.fifo
#exec
1>>"$info_log"
#exec
2>>"$error_log"
mkfifo
/tmp/info.fifo
mkfifo
/tmp/error.fifo
cat
/tmp/info.fifo
|
tee
-a
"${info_log}"
&
exec
1>/tmp/info.fifo
cat
/tmp/error.fifo
|
tee
-a
"${error_log}"
&
exec
2>/tmp/error.fifo
date
"+%Y-%m-%d
%H:%M:%S"
>
$error_log
date
"+%Y-%m-%d
%H:%M:%S"
>
$info_log
#####################################mkfifoinfo.fifomkfifoerror.fifo#创建管道文件catinfo.fifo|tee-ainfo.log&exec1>info.fifo
#把执行过程输出到info文件中caterror.fifo|tee-aerror.log&exec2>error.fifo
#把报错输出到error文件中printf"\015"
#结束从管道文件中获取信息自定义函数当我们要在脚本中多次使用相同一组命令时,可以将这组命令定义成一个函数来调用。注意:所有函数在使用前必须定义。这意味着必须将函数放在脚本开始部分,直至shell解释器首次发现它时,才可以使用。调用函数仅使用其函数名即可。shell中函数的定义格式如下:函数名(){
#function
函数名(){
可在函数名前加上关键字function
command1
command2
...
commandN
[
return
value
]
}例如:[root@localhost
~]#
cat
function.sh
#!/bin/bash
function
test(){
echo
"This
is
your
first
shell
function!"
}
echo
"Function
begin..."
test
echo
"Function
begin..."
[root@localhost
~]#
sh
function.sh
Function
begin...
This
is
your
first
shell
function!
Function
begin...
[root@localhost
~]#
echo
$?
0
[r
温馨提示
- 1. 本站所有资源如无特殊说明,都需要本地电脑安装OFFICE2007和PDF阅读器。图纸软件为CAD,CAXA,PROE,UG,SolidWorks等.压缩文件请下载最新的WinRAR软件解压。
- 2. 本站的文档不包含任何第三方提供的附件图纸等,如果需要附件,请联系上传者。文件的所有权益归上传用户所有。
- 3. 本站RAR压缩包中若带图纸,网页内容里面会有图纸预览,若没有图纸预览就没有图纸。
- 4. 未经权益所有人同意不得将文件中的内容挪作商业或盈利用途。
- 5. 人人文库网仅提供信息存储空间,仅对用户上传内容的表现方式做保护处理,对用户上传分享的文档内容本身不做任何修改或编辑,并不能对任何下载内容负责。
- 6. 下载文件中如有侵权或不适当内容,请与我们联系,我们立即纠正。
- 7. 本站不保证下载资源的准确性、安全性和完整性, 同时也不承担用户因使用这些下载资源对自己和他人造成任何形式的伤害或损失。
最新文档
- 江西省上饶市广丰县2025届四下数学期末检测试题含解析
- 产业经济学与2025年相关知识考试试卷及答案
- 2025年特殊教育教师资格考试试题及答案
- 2025年文化产业管理职业能力测评试卷及答案
- 咸阳师范学院《免疫与病原生物学实验Ⅲ》2023-2024学年第二学期期末试卷
- 九州职业技术学院《学术英语阅读与写作》2023-2024学年第一学期期末试卷
- 2025年英语专业八级考试试卷及答案
- 潜江市2024-2025学年初三中考模拟最后一卷生物试题含解析
- 辽宁省东港地区市级名校2025年初三3月中考适应性调研考试数学试题试卷含解析
- 高端私人直升机航拍影像作品版权授权及收益分成协议
- 中国铁路沈阳局集团有限公司招聘笔试真题2023
- 2024-2025学年上学期武汉小学语文六年级期末模拟试卷
- 2025届中考英语二轮复习常考题型专练:完形填空(含解析)
- 【MOOC】当代社会中的科学与技术-南京大学 中国大学慕课MOOC答案
- CAD教程-AutoCAD2024全套教程
- 2024年贵州省贵阳市中考地理试卷(附答案)
- (完整版)水利部考试历年真题-水利基础知识试题集
- 《常州红梅公园》课件
- 上海市2024年中考化学真题(含答案)
- 光伏发电工程总承包合同
- 教师管理条例
评论
0/150
提交评论