fun_name(){
指令。。。
return n
}
function fun_name(){
指令。。。
return n
}
a、格式
fun_name
b、注意事项
(i)不要带小括号。
(ii)函数定义和函数体必须在要执行的函数名的前面,因为shell的执行是从上向下执行的。
a、格式
fun_name 参数1 参数2 。。。
b、注意事项
(i)在函数体中可以使用位置参数($1,$2..$n,$#,$*,$?,$@)做为函数的参数。
(ii)父脚本的参数则临时被函数的参数所掩盖或变隐藏。
(iii)位置参数$0比较特殊,仍然表示父脚本的名称。
(iv)当函数执行完成后,原来的命令行参数会恢复。
(v)return的功能和工作方式与shell中的exit相同,用于跳出函数。
(vi)return会返回一个退出给调用的程序。
(vii)在函数体中使用exit会跳出shell,终止整个shell脚本。
a、只定义函数,不调用,则无结果。
vi /services/scripts/myFun01.sh
#!/bin/sh
myFun01(){
echo "I amLinux"
}
sh /services/scripts/myFun01.sh
#<--结果为空,没有任何输出
b、函数调用在前,定义在后,则报错commandnot found。
vi /services/scripts/myFun01.sh
#!/bin/sh
myFun01
myFun01(){
echo "I amLinux"
}
sh /services/scripts/myFun01.sh
myFun01.sh: line 2: myFun01: command not found
c、调用函数加小括号,则报错syntaxerror: unexpected end of file。
vi /services/scripts/myFun01.sh
#!/bin/sh
myFun01(){
echo "I amLinux"
}
myFun01()
sh /services/scripts/myFun01.sh
myFun01.sh: line 6: syntax error: unexpected end of file
d、正确调用。
vi /services/scripts/myFun01.sh
#!/bin/sh
myFun01(){
echo "I amLinux"
}
myFun01
sh /services/scripts/myFun01.sh
I am Linux
vi /services/scripts/fun_defined.sh
#!/bin/sh
myFun01(){
echo "I ammyFun01"
}
myFun02(){
echo "I ammyFun02"
}
vi /services/scripts/fun_exec.sh
#!/bin/sh
[ -f fun_defined.sh ] && . ./fun_defined.sh || exit 1
myFun01
myFun02
sh fun_exec.sh
I am myFun01
I am myFun02
vi /services/scripts/myFun03.sh
#!/bin/sh
myFun03(){
echo "I am Linux。You are $1"
}
myFun03 abc
sh /services/scripts/myFun03.sh
I am Linux。Youare abc
vi /services/scripts/myFun04.sh
#!/bin/sh
myFun04(){
echo "I am myFun04。You are $1"
}
myFun04 $1
sh /services/scripts/myFun04.sh Tom
I am myFun04。Youare Tom
vi /service/scripts/fun_check_web.sh
#!/bin/sh
httpcode=0
getHttpCode(){
httpcode=`curl -I -s -w "%{http_code}" -o /dev/null $1`
if [ $http_code -ne 200 ]
then
echo " Web is error."
return 1
else
echo " Web isOK."
fi
return 0
}
getHttpCode $1
ehco $?
echo $httpcode
sh fun_check_web.sh http://www.baidu.com
Web is OK.
0
200
sh fun_check_web.sh http://www.baidu.com123
Web is error.
1
000
a、思路
(i)MySQL启动命令:
单实例:mysqld_safe --user-mysql &
多实例:mysqld_safe--defaults-file=/data/3306/my.cnf &
(ii)MySQL停止命令
单实例:mysqladmin -uroot -p'123456'shutdown
多实例:mysqladmin -uroot -p'123456' -S/data/3306/mysql.sock shutdown
b、要求
一个start函数调用启动命令,一个stop函数调用停止命令,一个restart函数调用stop函数和start函数。
c、单实例启动脚本
vi /services/scripts/singleDBStart.sh
#!/bin/sh
. /etc/init.d/functions
basedir=/application/mysql/
datadir=/application/mysql/data/
function usage(){
echo "$0{start|stop|restart}"
exit 1
}
[ $# -ne 1 ] && usage
function start_mysql(){
$basedir/bin//mysqld_safe--datadir="$datadir" --user=mysql &
if [ $? -eq 0 ]
then
action "startmysql" /bin/true
else
action "startmysql" /bin/false
fi
}
function stop_mysql(){
mysqladmin -uroot-p'123456' shutdown
if [ $? -eq 0 ]
then
action "stopmysql" /bin/true
else
action "stopmysql" /bin/false
fi
}
if [ "$1" == "start" ]
then
start_mysql
elif [ "$1" == "stop" ]
then
stop_mysql
elif [ "$1" == "restart" ]
then
stop_mysql
start_mysql
else
usage
fi
sh singleDBStart.sh start
start mysql [ OK ]
sh singleDBStart.sh stop
stop mysql [ OK ]
mysql -uroot -p
mysql>
d、多实例启动脚本:查看多实例/data/3306/mysql
cat /data/3306/mysql
#!/bin/sh
#init
port=3306
mysql_user="root"
mysql_pwd="wddgmy"
CmdPath="/application/mysql/bin"
mysql_sock="/data/${port}/mysql.sock"
#startup function
function_start_mysql()
{
if [ ! -e"$mysql_sock" ];then
printf "StartingMySQL...\n"
/bin/sh${CmdPath}/mysqld_safe --defaults-file=/data/${port}/my.cnf 2>&1 >/dev/null &
else
printf "MySQL is running...\n"
exit
fi
}
#stop function
function_stop_mysql()
{
if [ ! -e"$mysql_sock" ];then
printf "MySQL isstopped...\n"
exit
else
printf "StopingMySQL...\n"
${CmdPath}/mysqladmin-u ${mysql_user} -p${mysql_pwd} -S /data/${port}/mysql.sock shutdown
fi
}
#restart function
function_restart_mysql()
{
printf "RestartingMySQL...\n"
function_stop_mysql
sleep 2
function_start_mysql
}
case $1 in
start)
function_start_mysql
;;
stop)
function_stop_mysql
;;
restart)
function_restart_mysql
;;
*)
printf "Usage:/data/${port}/mysql {start|stop|restart}\n"
esac
cp /services/scripts/singleDBStart.sh /etc/init.d/sigleMySQL
vi /etc/init.d/sigleMySQL
#!/bin/sh
# chkconfig: 2345 21 60
# description: sigleMySQL start and mysql stop scripts
. /etc/init.d/functions
basedir=/application/mysql/
datadir=/application/mysql/data/
......
chkconfig --add sigleMySQL
chkconfig sigleMySQL on
chkconfig --list sigleMySQL
sigleMySQL 0:off 1:off 2:on 3:on 4:on 5:on 6:off
case "字符串变量" in
值1) 指令1...
;;
值2|值3|值4) 指令2...
;;
*) 指令...
esac
a、给字符串加颜色
vi /services/scripts/echo-color01.sh
echo -e "\033[30m BlackFont : this is blackfont \033[0m"
echo -e "\033[31m RedFont : this is redfont \033[0m"
echo -e "\033[32m GreenFont : this is greenfont \033[0m"
echo -e "\033[33m YellowFont : this is yellowfont \033[0m"
echo -e "\033[34m BlueFont : this is bluefont \033[0m"
echo -e "\033[35m PurpleFont : this is purplefont \033[0m"
echo -e "\033[36m SkyBlueFont: this is skybluefont\033[0m"
echo -e "\033[37m WhiteFont : this is whitefont \033[0m"
vi /services/scripts/echo-color02.sh
#!/bin/sh
RED_COLOR='\E[1;31m'
GREEN_COLOR='\E[1;32m'
YELLOW_COLOR='\E[1;33m'
BLUE_COLOR='\E[1;34m'
PINK_COLOR='\E[1;35m'
RES='\E[0m'
echo -e "${RED_COLOR}========red color=========${RES}"
echo -e "${YELLOW_COLOR}======yellow color=========${RES}"
echo -e "${BLUE_COLOR}========blue color=========${RES}"
echo -e "${GREEN_COLOR}=======green color=========${RES}"
echo -e "${PINK_COLOR}========pink color=========${RES}"
b、完整脚本
vi /services/scripts/fruitmenu.sh
#!/bin/sh
RED_COLOR='\E[1;31m'
GREEN_COLOR='\E[1;32m'
YELLOW_COLOR='\E[1;33m'
BLUE_COLOR='\E[1;34m'
RES='\E[0m'
menu(){
cat < ========================== 1 apple 2 pear 3 banana 4 exit ============================= END } while true do menu read -p "please ipunt your choice: " -t 10 fruit case "$fruit" in 1) echo -e"${RED_COLOR} apple ${RES}" ;; 2) echo -e"${GREEN_COLOR} pear ${RES}" ;; 3) echo -e"${YELLOW_COLOR} banana ${RES}" ;; 4) exit 0 ;; *) echo "no fruit youchoose" ;; esac done a、要求 (i)使用read或传参实现 (ii)以传参为例,在脚本命令行传2个参数,第1个参数是内容,第2个参数是颜色 b、传参脚本 vi /services/scripts/textcolor.sh #!/bin/sh RED_COLOR='\E[1;31m' GREEN_COLOR='\E[1;32m' YELLOW_COLOR='\E[1;33m' BLUE_COLOR='\E[1;34m' RES='\E[0m' if [ $# -ne 2 ];then echo "Usage $0content {red|yellow|blue|green}" exit fi case "$2" in red|RED) echo -e"${RED_COLOR} $1 ${RES}" ;; green|GREEN) echo -e"${GREEN_COLOR} $1 ${RES}" ;; yellow|YELLOW) echo -e"${YELLOW_COLOR} $1 ${RES}" ;; blue|BLUE) echo -e"${BLUE_COLOR} $1 ${RES}" ;; *) echo "you inputcolor is not exits" echo "Usage $0content {red|yellow|blue|green}" ;; esac sh textcolor.sh apple red apple sh textcolor.sh apple green apple sh textcolor.sh apple yellow apple sh textcolor.sh apple blue apple c、函数脚本 vi /services/scripts/textcolor_fun.sh #!/bin/sh plus_color(){ RED_COLOR='\E[1;31m' GREEN_COLOR='\E[1;32m' YELLOW_COLOR='\E[1;33m' BLUE_COLOR='\E[1;34m' RES='\E[0m' case "$2" in "red") echo -e"${RED_COLOR} $1 ${RES}" ;; "green") echo -e"${GREEN_COLOR} $1 ${RES}" ;; "yellow") echo -e"${YELLOW_COLOR} $1 ${RES}" ;; "blue") echo -e"${BLUE_COLOR} $1 ${RES}" ;; *) echo "you inputcolor is not exits" echo $1 ;; esac } plus_color $1 $2 sh textcolor_fun.sh apple red apple a、手动启动rsync服务进行测试 lsof -i :873 rsync --daemon Failed to parse config file: /etc/rsyncd.conf touch /etc/rsyncd.conf rsync --daemon lsof -i :873 COMMAND PID USER FD TYPE DEVICE SIZE/OFF NODE NAME rsync 2837 root 4u IPv4 15548 0t0 TCP *:rsync (LISTEN) rsync 2837 root 5u IPv6 15549 0t0 TCP *:rsync (LISTEN) pkill rsync lsof -i :873 b、思路 使用pkill rsync命令来停止rsync并不好,也不规范,最好是通过pid文件来停止rsync服务。同时,如果使用端口或进程进行判断程序是否启动或关闭时,在放到/etc/init.d/下或chkconfig进行管理时,容易出现错误,无法正确执行。 vi /etc/rsyncd.conf pid file = /var/run/rsyncd.pid lock file = /var/run/rsyncd.lock log file = /var/log/rsyncd.log pkill rsync lsof -i :873 rsync --daemon cat /var/run/rsyncd.pid 3026 c、完整脚本 vi /services/scripts/rsyncd.sh #!/bin/sh . /etc/init.d/functions pidfile="/var/run/rsyncd.pid" start_rsync(){ if [ -f $pidfile ];then echo "rsync isrunning" else rsync --daemon action "rsyncstart" /bin/true fi } stop_rsync(){ if [ -f $pidfile ];then kill -USR2 `cat$pidfile` rm -f ${pidfile} action "rsync isstopped" /bin/true else action "rsync notrunning, already been stopped." /bin/false fi } case "$1" in start) start_rsync RETVAL=$? ;; stop) stop_rsync RETVAL=$? ;; restart) stop_rsync sleep 2 start_rsync RETVAL=$? ;; *) echo "USAGE: $0{start|stop|restart}" exit 1 ;; esac exit $RETVAL scripts]# sh rsyncd.sh stop rsync not running, already been stopped. [ FAILED ] sh rsyncd.sh stop rsync not running sh rsyncd.sh start rsync start [ OK ] sh rsyncd.sh start rsync is running, already been stopped. [ FAILED ] sh rsyncd.sh stop rsync is stopped [ OK ] sh rsyncd.sh restart rsync not running, already been stopped. [ FAILED ] rsync start [ OK ] d、加入chkconfig进行管理 cp /services/scripts/rsyncd.sh /etc/init.d/rsyncd chmod +x /etc/init.d/rsyncd vi /etc/init.d/rsyncd #!/bin/sh # chkconfig: 2345 31 61 # description: rsync start and stop scripts . /etc/init.d/functions pidfile="/var/run/rsyncd.pid" start_rsync(){ ... esac exit $RETVAL chkconfig --add rsyncd chkconfig rsyncd on chkconfig --list rsyncd rsyncd 0:off 1:off 2:on 3:on 4:on 5:on 6:off cp /services/scripts/singleDBStart.sh/services/scripts/MySQLStart_case.sh vi /services/scripts/MySQLStart_case.sh #!/bin/sh . /etc/init.d/functions basedir=/application/mysql/ datadir=/application/mysql/data/ function usage(){ echo "$0{start|stop|restart}" exit 1 } [ $# -ne 1 ] && usage function start_mysql(){ $basedir/bin//mysqld_safe--datadir="$datadir" --user=mysql & if [ $? -eq 0 ] then action "startmysql" /bin/true else action "startmysql" /bin/false fi } function stop_mysql(){ mysqladmin -uroot-p'123456' shutdown if [ $? -eq 0 ] then action "stopmysql" /bin/true else action "stopmysql" /bin/false fi } case "$1" in start) start_mysql ;; stop) stop_mysql ;; restart) stop_mysql start_mysql ;; *) usage ;; esac sh MySQLStart_case.sh start start mysql [ OK ] sh MySQLStart_case stop stop mysql [ OK ] mysql -uroot -p mysql> while 条件 do 指令。。。 done until条件 do 指令。。。 done cat a.log | while read line do done while read line do done < a.log exec < a.log while read line do done vi /services/scripts/while01.sh #!/bin/sh while true do uptime sleep 2 #休眠2秒,usleep 1000000也是休眠1秒,单位是微秒 done sh while01.sh 22:19:01 up 3:34, 3 users, load average: 0.01, 0.07, 0.12 22:19:03 up 3:34, 3 users, load average: 0.01, 0.07, 0.12 a、方法一 vi /services/scripts/while02.sh #!/bin/sh i=1 sum=0 while (( i < 101 )) do (( $sum + $i )) (( i++ )) done echo "sum = " $sum sh while02.sh sum = 5050 b、方法二 vi /services/scripts/while02_02.sh #!/bin/sh i=1 sum=0 while [ $i -le 100 ] do let sum=sum+i let i=i+1 done echo "sum = " $sum sh while02_02.sh sum = 5050 vi /services/scripts/while03.sh #!/bin/sh i=10 while ((i>0)) do echo $i ((i--)) done sh while03.sh 10 9 8 7 6 5 4 3 2 1 a、思路 单位换算,统一单位,尽量用整数来计算。所以10元=1000分,1角5分=15分。 b、脚本 vi /services/scripts/while04.sh #!/bin/sh sum=1000 while ((sum >= 15)) do ((sum=sum-15)) echo "yu e is$sum" done echo "yu e bu zhu, qing chong zi" a、nginx日志内容 cat /application/nginx/logs/bbs_access.log 192.168.158.111 - - [18/Mar/2017:04:52:39 +0800] "GET /HTTP/1.1" 200 12 "-" "Mozilla/5.0 (Windows NT6.1) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/54.0.2824.2Safari/537.36" "-" 192.168.158.111 - - [18/Mar/2017:04:52:39 +0800] "GET/favicon.ico HTTP/1.1" 404 570 "http://bbs.abc.org/""Mozilla/5.0 (Windows NT 6.1) AppleWebKit/537.36 (KHTML, like Gecko)Chrome/54.0.2824.2 Safari/537.36" "-" 192.168.158.111 - - [18/Mar/2017:04:52:39 +0800] "GET/favicon.ico HTTP/1.1" 404 - "http://bbs.abc.org/""Mozilla/5.0 (Windows NT 6.1) AppleWebKit/537.36 ( KHTML, like Gecko) Chrome/54.0.2824.2 Safari/537.36""-" b、脚本 vi /services/scripts/while05.sh #!/bin/sh sum=0 i=0 while read line do i=$(echo $line|awk '{print$10}') if expr $i + 0&>/dev/null then ((sum=sum+i)) fi done < /application/nginx/logs/bbs_access.log echo $sum sh while05.sh 582 sh -x while05.sh + sum=0 + i=0 + read line ++ echo 192.168.158.111 - - '[18/Mar/2017:04:52:39' '+0800]''"GET' / 'HTTP/1.1"' 200 12 '"-"' '"Mozilla/5.0''(Windows' NT '6.1)' AppleWebKit/537.36 '(KHTML,' like 'Gecko)'Chrome/54.0.2824.2 'Safari/537.36"' '"-"' ++ awk '{print $10}' + i=12 + expr 12 + 0 + (( sum=sum+i )) + read line ++ echo 192.168.158.111 - - '[18/Mar/2017:04:52:39' '+0800]''"GET' /favicon.ico 'HTTP/1.1"' 404 570'"http://bbs.abc.org/"' '"Mozilla/5.0' '(Windows' NT '6.1)'AppleWebKit/537.36 '(KHTML,' like 'Gecko)' Chrome/54.0.2824.2'Safari/537.36"' '"-"' ++ awk '{print $10}' + i=570 + expr 570 + 0 + (( sum=sum+i )) + read line ++ echo 192.168.158.111 - - '[18/Mar/2017:04:52:39' '+0800]''"GET' /favicon.ico 'HTTP/1.1"' 404 -'"http://bbs.abc.org/"' '"Mozilla/5.0' '(Windows' NT '6.1)'AppleWebKit/537.36 '(' ++ awk '{print $10}' + i=- + expr - + 0 + read line ++ echo KHTML, like 'Gecko)' Chrome/54.0.2824.2'Safari/537.36"' '"-"' ++ awk '{print $10}' + i= + expr + 0 + read line + echo 582 582 a、思路 crond定时任务,只能精确到分钟,无法到秒级,所以只能通过循环来实现。脚本完成后,放入rc.local文件中,让脚本开机自启动运行。 b、脚本 vi /services/scripts/while06.sh #!/bin/sh while true do rsync -az/data/3306/mysql-bin* [email protected]::backup--password-file=/etc/rsync.password sleep 10 done sh while06.sh & c、开机自启动 echo "/bin/sh /services/scripts/while06.sh &" >>/etc/rc.local (1)while循环的特长是执行守护进程以及希望循环不退出,用于频率小于1分钟的循环处理。其它的while循环几乎都可以用for循环替代。 (2)case语句可以用if语句替换,一般在系统启动脚本传入少量固定规则字符串时用case,其它判断多用if。 (3)if和for语句是最常用的,其次是while(守护进程),再就是case(服务启动脚本) for 变量名 in 变量取值列表 do 指令。。。 done 说明:“in 变量取值列表”可以省略,当省略时,默认为$@($@表示获取当前执行的shell的所有参数)。也就是for i 相当于for i in "$@" for((exp1;exp2;exp3)) do 指令。。。 done vi /services/scripts/for01.sh #!/bin/sh for n in 5 4 3 2 1 # 也可以用for n in {5..1} do echo $n done vi /services/scripts/for02_autoStart.sh #!/bin/sh LANG=en for name in `chkconfig --list | grep 3:on | awk '{print $1}'` do chkconfig $name off done for name in sshd crond rsyslog network sysstat do chkconfig $name on done vi /services/scripts/for03_add.sh #!/bin/sh sum=0 for i in {1..100} # 也可以for ((i=0;i<=100;i++)) do ((sum=sum+i)) done echo $sum vi /services/scripts/for04_createFiles.sh #!/bin/sh for ((i=1;i<11;i++)) do touch oldboy_${i}.html done sh for04_createFiles.sh ll -rw-r--r-- 1 root root 0Jun 4 22:26 oldboy_1.html -rw-r--r-- 1 root root 0Jun 4 22:26 oldboy_10.html -rw-r--r-- 1 root root 0Jun 4 22:26 oldboy_2.html -rw-r--r-- 1 root root 0Jun 4 22:26 oldboy_3.html -rw-r--r-- 1 root root 0Jun 4 22:26 oldboy_4.html -rw-r--r-- 1 root root 0Jun 4 22:26 oldboy_5.html -rw-r--r-- 1 root root 0Jun 4 22:26 oldboy_6.html -rw-r--r-- 1 root root 0Jun 4 22:26 oldboy_7.html -rw-r--r-- 1 root root 0Jun 4 22:26 oldboy_8.html -rw-r--r-- 1 root root 0Jun 4 22:26 oldboy_9.html a、方法一 vi /services/scripts/for05_rename.sh #!/bin/sh cd /services/scripts/for for n in `seq 10` do mv oldboy_${i}.htmllinux_${i}.HTML done b、方法二 vi /services/scripts/for05_rename.sh #!/bin/sh cd /services/scripts/for for f in `ls *.html` do #mv $f `echo $f | sed 's#oldboy#linux#g' |sed 's#html#HTML#g'` mv $f `echo $f | sed's#oldboy\(.*\).html#linux\1.HTML#g'` done a、思路和技术点 (i)数字前面加0 数字前面加0,有多种方法。可参参考http://oldboy.blog.51cto.com/2561410/788422 最常用的是seq的-w参数 seq -w 10 01 02 03 04 05 06 07 08 09 10 (ii)无交互式设置密码 echo aaa | passwd --stdin test b、脚本 vi /services/scripts/for06_createUsers01.sh #!/bin/sh for n in `seq -w 10` do useradd oldboy$n && echo "root$n" | passwd--stdin oldboy$n #useradd oldboy$n -p "root$n" #也可以这样创建用户时直接设置密码但/etc/shadow中为明文 done a、随机数 (i)echo $RAMDOM:一般为5位数以下 echo $RAMDOM 1634 echo $RANDOM 13621 echo $RANDOM 18892 echo $RANDOM 620 (ii)RAMDOM加上一个8位数10000000:echo$((RANDOM+10000000)) echo $((RANDOM+10000000)) 10030175 echo $((RANDOM+10000000)) 10012580 echo $((RANDOM+10000000)) 10016722 (iii)echo $RAMDOM后md5sum生成的字符串取任意8位: echo $RANDOM | md5sum | cut -c 1-8 785c4f64 echo "`date`$RANDOM" | md5sum | cut -c 1-8 #以时间为种子取随机数 adba4d85 b、脚本 vi /services/scripts/for07_createUsers02.sh #!/bin/sh for n in `seq -w 10` do pass=`echo $RANDOM | md5sum | cut -c 1-8` useradd oldboy$n && echo "$pass" | passwd--stdin oldboy$n echo -e "oldboy$n\t $pass ">> pass.txt done echo $RANDOM 18682 openssl rand -base64 8 QFN20JhyWCI= openssl rand -base64 10 YJzbf9BJjm+4lg== date +%s%N 1496592770592461116 head /dev/urandom | cksum 1232898784 2017 cat /proc/sys/kernel/random/uuid 9e1960ac-69c9-4917-bbe5-d1926bafaae0 mkpasswd -l 8 So5;a9i mkpasswd --help mkpasswd [args] [user] where arguments are: -l # (length of password,default = 9) -d # (min # of digits,default = 2) -c # (min # of lowercasechars, default = 2) -C # (min # of uppercasechars, default = 2) -s # (min # of special chars,default = 1) -v (verbose, show passwdinteraction) -p prog (program to setpassword, default = passwd) 命令 说明 break n n表示跳出循环的层数,如果省略n则表示跳出整个循环 continue n n表示退出到第n层继续循环,如果省略n则表示跳过本次循环,忽略剩余代码,进入下一次循环 exit n 退出当前shell程序,n为返回值。n也可以省略,再下一个shell里通过$?来接收这个n的值 return n 用于在函数里做为函数的返回值,用于判断函数执行是否正确 vi break01.sh #!/bin/sh for ((i=0;i<=5;i++)) do if [ $i -eq 3 ];then break fi echo $i done echo "OK" sh break01.sh 0 1 2 OK vi continue01.sh #!/bin/sh for ((i=0;i<=5;i++)) do if [ $i -eq 3 ];then continue fi echo $i done echo "OK" sh break01.sh 0 1 2 4 5 OK vi exit01.sh #!/bin/sh for ((i=0;i<=5;i++)) do if [ $i -eq 3 ];then exit fi echo $i done echo "OK" sh break01.sh 0 1 2 vi ipconfig.sh #!/bin/sh for ((i=1;i<17;i++)) do if [ $i -eq 10 ];then continue fi ifconfig eth0:$i 192.168.2.$i/24 up done vi ping01.sh #!/bin/sh for n in {1..254} do ping -c1 192.168.1.$n >/dev/null 2>&1 if [ $? -eq 0 ] then echo "192.168.1.$n is up " >> /tmp/uplist.log else echo "192.168.1.$n is down " >> /tmp/downlist.log fi done vi ddos.sh #!/bin/sh while true do awk '{print $1}' access.log|grep -v"^$"|sort|uniq -c >/tmp/tmp.log exec
while read line do ip=`echo $line|awk '{print $2}'` count=`echo $line|awk '{print $1}'` if [ $count -gt 3 ] && [ `iptables-L -n |grep "$ip"|wc -l` -lt 1 ] then iptables -I INPUT -s $ip -j DROP echo "$line is dropped" >>/tmp/droplist.log fi done sleep 5 done a、安装系统时精简安装包(最小化安装) b、配置yum源 c、禁用开机不需要的启动的服务 d、优化系统内核参数/etc/sysctl.conf e、增加系统文件描述符、堆栈等配置 f、禁止root远程登陆,修改SSH端口为特殊端口,禁止DNS,禁止空密码 g、有外网IP的要配置防火墙,公对外开启需提供服务的端口,配置或关闭SELinux h、清除无用的默认用户和组(非必须),添加运维成员用户 i、锁定敏感文件,如/etc/passwd(非必须) j、配置时间同步 k、配置sudo,对普通用户权限精细控制 array=(value1 value2 value3 ...) array=($(ls等命令)) array=([key1]=value1 [key2]=value2...) array[下标1]=value1 array[下标2]=value2 declare -a array echo ${#array[@]}或echo ${#array[*]} echo ${array[下标]} echo ${array[@]}或echo${array[*]} #与获取数组长度相比,没有#号 数组的赋值是直接通过数据名[下标]就可以对其进行引用赋值。如果下标不存在,则会自动添加一个新的数组元素,如查存在就覆盖原来的值。 array[下标]=value4 通过unset 数组名[下标]就可以清除对应的元素,如不带下标,则删除整个数组。就相当于unset 变量,可以理解为把数组名当变量在使用。 unset array[1] unset array a、截取指定长度的子串 array[@或*]:开始下标: 截取长度 b、从指定下标截取到结尾 array[@或*]:开始下标 array[@或*]/需替换的内容/替换内容 array=(1 2 3) echo ${#array[@]} 3 echo ${#array[*]} 3 echo ${array[0]} 1 echo ${array[1]} 2 echo ${array[2]} 3 echo ${array[*]} 1 2 3 echo ${array[@]} 1 2 3 a、为数组array新增一个元素 array[3]=4 b、查看数组所有元素 echo ${array[@]} 1 2 3 4 c、修改数组第一个元素的值 array[0]=test d、查看数组所有元素 echo ${array[*]} test 2 3 4 a、删除数组array第一个元素 unset array[0] echo ${array[*]} 2 3 4 echo ${#array[*]} 2 # <--数组长度为2 echo ${array[0]} # <--下标为0的元素,已经不存在了,下标从1开始了 echo ${array[1]} 2 b、删除数组array unset array echo ${array[*]} # <--为空 array=(1 2 3 4 5) echo ${array[@]:2:2} 3 4 echo ${array[@]:2} 3 4 5 array=(1 2 3 4 5) echo ${array[@]/2/test} 1 test 3 4 5 echo ${array[@]} 1 2 3 4 5 array1=(${array[@]/2/test}) echo ${array1[@]} 1 test 3 4 5 pwd /services/scripts ls a1.log a2.log a3.log a4.log a5.log array2=($(ls)) echo ${#array2[*]} 5 echo ${array2[0]} a1.log echo ${array2[1]} a2.log for f in ${array2[*]};do echo $f;done a1.log a2.log a3.log a4.log a5.log array=( aa bb cc ) for ((i=0;i<${#array[*]};i++)) do echo "This is num $i,then content is ${array[$i]}" done array=(1 3 3) array=($(ls)) a、打印所有元素 ${array[*]} b、打印数组长度 ${#array[*]} c、打印单个元素 ${array[i]} 1、各类监控脚本。如:内存、磁盘、端口、URL监控报警 2、如果监控网站目录文件是否被篡改,以及站点目录被篡改后如何批量恢复 3、如何开发各类服务rsync、nginx、mysql等启动及停止专业脚本 4、如何开发MySQL主从同步监控报警以及自动化处理不同步的脚本 5、一键配置mysql多实例,一键配置mysql主从同步,一键部署脚本 6、监控http/MySQL/rsync/nfs等服务是否正常生产脚本 7、一键软件安装以及优化,lamp、lnmp、一键安装,一键安装数据库,优化配置主从 8、MySQL多实例启动脚本,分库,分表自动化备份脚本 9、监控网络连接数,以及根据webPV分IP脚本 10、监控网站pv以及流量。并对流量信息进行统计 11、监控web服务器URL地址的脚本,可以批量以及通用 12、系统的基础优化,一键优化脚本 13、清理系统垃圾文件(过期备份)脚本 14、tcp连接状态统计 15、批量创建用户并设置随机8位密码 16、获取服务器的信息,批量分文件 cat if.sh #!/bin/bash if [$1-lt$2]#<--[和$1之间缺少空格 then echo "Yes,$1islessthan$2" exit fi shif.sh12 if.sh:line2:[1:commandnotfound#<--把[1当成一个命令了,提示命令没有找到 cat if.sh #!/bin/bash if [ $1-lt$2#<--[]应成对出现,但缺少右边的] then echo "Yes,$1islessthan$2" exit fi shif.sh12 if.sh:line2:[:missing`]'#<--但缺少右边的] cat if.sh #!/bin/bash if[$1-lt$2] then echo "Yes,$1islessthan$2" exit #<--缺少if结束的fi shif.sh12 if.sh:line6:syntaxerror:unexpectedendoffile#<--语法错误,未预期的文件结尾。 a、重视书写习惯、开发规范和开发制度,尽量减少脚本调试的难度,提升开发效率 b、基本语法要熟悉,才能利用好调试 c、开发时,思路要清晰,将复杂的脚本简单化,分段实现 d、将重复的内容,最好写成函数 从windows编辑的脚本到linux下时,有时候会有格式问题,存在一些不可见字符,导致脚本运行时报错。由于是不可见字符,用眼睛看代码时,又不容易发现问题。所以,从windows迁移到linux上的脚本或者不是自已写的脚本,一律要用dos2unix命令格式化处理后再运行。例:下面脚本是从windows开发的,在linux中显示的结果,每行结尾处多了^M cat -vwhile-debug-test.sh #!/bin/sh^M i=1^M sum=0^M while((i<=100))^M do^M ((sum=sum+i))^M ((i++))^M done^M echo $sum^M dos2unix while-debug-test.sh dos2unix:convertingfilewhile-debug-test.shtoUNIXformat.. 在指定位置插入echo命令,进行输出,并在语句后面加上exit命令,不执行echo后面的语句,这样就可以逐段排查了(写法:echo$var;exit)。如下例: vi/services/scripts/webSiteCheck.sh #!/bin/sh path=/server/scripts while true do f=`md5sum -c $path/md5sum.db2>/dev/null|grepFAILED|wc-l` n=`cat $path/check_site_filenumber.log|wc-l` findtext=`find /application/nginx/html/-type f>$path/new_site.log` log=/tmp/check.log [ !-f$log ]&&touch$log if[ $f-ne0 ]||[ `cat$path/new_site.log|wc-l`-ne$n ] then echo "`md5sum-c md5sum.db2>/dev/null|grepFAILED`">$log echo "`md5sum -c md5sum.db2>/dev/null|grepFAILED`"#调试,echo 输出 exit#<--调试,退出,不执行后面的语句 diff $path/check_site_filenumber.log$path/new_site.log>>$log mail -s "siteistampered$(date)"[email protected]<$log fi sleep180 done sh-n while01.sh #<--正确,无任何提示,脚本也未执行 sh-n if.sh if.sh:line6:syntaxerror:unexpectedendoffile#<--有错误提示,脚本也未执行 sh-v while02.sh #!/bin/sh i=1 sum=0 while(($i<101)) do sum=$(($sum+$i)) i=$(($i+1)) done echo "sum="$sum#<--文件内容 sum=5050#<--文件执行的结果 sh -x while01.sh +true +uptime +sleep2 bash-x将会调试脚本全部内容,但有时,我们不想调试全部脚本,只想调试部分脚本,这就需要set命令了。如脚本调用了系统函数,但系统函数不会有错误,我们不需要调试,这时就可以用set-x和set+x来指定要调试的作用域了。 -n:读命令,但不执行 -v:显示读取的所有行 -x:显示所有命令及其参数 viwhile02.sh #!/bin/sh i=1 sum=0 set -x#<--调试开始位置 while(($i<101)) do sum=$(($sum+$i)) i=$(($i+1)) done set +x#<--调试结束位置 echo "sum="$sum sh while02.sh#<--不需要用sh-x(2)示例2:开发一个给指定内容加指定颜色的脚本
(3)示例3:利用case来开发类似系统启动rsync服务的脚本(可参考系统的rpcbind和nfs脚本)
(4)示例4:将前面shell函数的示例6:MySQL启动脚本由函数改为case来实现
三、while循环和until条件句
1、语法格式
(1)while语法
(2)until语法(应用场合不多见,了解就行)
2、while读取文件内容
(1)方法一
(2)方法二
(3)方法三
3、示例
(1)示例1:(while)每隔2秒记录一次系统负载情况,屏幕输出
(2)示例2:使用while语句计算1+2+..+100的值
(3)示例3:使用while语句竖向打印10,9,8,...1
(4)示例4:手机充值10元,每发一条短信扣1角5分,当余额低于1角5分不能发短信,提示余额不足,请充值。用while实现
(5)示例5:计算nginx日志中的所有行的访问字节数的总和
(6)示例6:以守护进程方式,每10秒,实现一次rsync mysqlbinlog推送
4、条件句小结
四、for循环
1、语法格式
(1)for循环结构
(2)C语言型语法的for循环结构
2、示例
(1)示例1:通过for循环打印5 4 3 2 1
(2)示例2:通过for循环只保留crond、sshd、rsyslog、network,关闭其它开机自启动,
(3)示例3:通过for循环计算1+2+..+100
(4)示例4:创建10个文件,文件名中包含oldboy,结尾是1到10,扩展名为html
(5)示例5:通过for循环将上述文件名中的oldboy全部改为linux,扩展名改为大写HTML
(6)示例6:通过for循环批量创建10个系统账号oldboy01到oldboy10,密码不能相同
(7)示例7:通过for循环批量创建10个系统账号oldboy01到oldboy10,密码为随机8位字符串
五、随机数的6种获取方法
1、方法一:RANDOM
2、方法二:openssl
3、方法三:date
4、方法四:urandom
5、方法五:uuid
6、方法六:expect的mkpasswd方法
六、循环的控制
1、break、continue、exit和return的对比
2、示例
(1)示例1:break跳出整个循环体,执行循环体外后面的语句
(2)示例2:continue当前循环,执行下一次循环
(3)示例3:exit退出shell,不在执行程序体中任何语句
(4)示例4:用shell脚本给服务器配置临时别名IP,并可以随进撤销配置的所有IP。IP段为192.168.2.1-192.168.2.16,其中192.168.2.10不能配置。
(5)示例5:判断当前局域网网络里,当前在线用户的IP有哪些?
(6)示例6:判断是否有DDOS攻击
七、一键优化脚本
1、一键优化的思维思想
(1)要知道在哪些优化点
(2)每个优化点,如何优化?
(3)针对每个优化点,在命令行完成单条测试
2、示例1:一键优化Linux系统的脚本
(1)优化点
3、示例2:检查一键优化是否成功的脚本
八、Shell数组
1、定义
(1)方法一(常用)
(2)方法二(常用)
(3)方法三
(4)方法四
(5)方法五
2、数据的操作
(1)获取数组长度
(2)打印单个数组元素:数组下标从0开始
(3)打印数组全部元素
(4)数组的赋值
(5)数组的删除
(6)数组的截取(与变量子串的替换相似)
(7)数组的替换(与变量子串的替换相似,该操作临时生效,不会改就原数组内容,类似sed)
3、示例
(1)示例1:定义数组
(2)示例2:获取数组array的长度
(3)示例3:打印数组array中单个的元素
(4)示例4:打印数组array中所有的元素
(5)示例5:数组赋值
(6)示例6:删除数组
(7)示例7:数组的截取
(8)示例8:数组的替换
(9)示例9:方法二方式定义数组的相关操作
(10)示例10:定义数组并打印
4、数组小结:常用功能
(1)数组定义
(2)数组打印
九、运维要求必会的脚本开发
十、Shell脚本的调试
1、常见脚本错误
(1)if条件句的条件表达式中中括号[]两边缺少空格
(2)if条件句的条件表达式中应成对出现的符号,缺失一个
(3)if条件句缺少结尾的fi
2、调试技巧
(1)调试要求
(2)技巧1:使用dos2unix命令处理来自windows下开发的脚本
(3)技巧2:使用echo命令调试
3、bash的调试参数
(1)-n参数:不执行脚本,仅查询脚本是否存在语法问题,如果有错误,则给出错误提示
(2)-v参数:在执行脚本时,先将脚本的内容输出到屏幕上,然后再执行脚本,如果有错误,则给出错误提示
(3)-x参数:将执行的脚本内容和输出显示到屏幕上(最常用的参数)
4、使用set命令调试部分脚本内容(缩小调试的作用域)
(1)参数
(2)示例