c语言字符串对比equse,shell脚本

Shell脚本

Shell的简介:

Shell是一个命令解释器,它在操作系统的最外层,负责直接与用户对话,把用户的输入解释给操作系统,并处理各种各样的操作系统的输出结果,输出到屏幕上返回给用户,这种对话方式可以是交互式的也可以是非交互式的。

Shell脚本在运维工作中的作用地位

Shell脚本很擅长处理纯文本类型的数据,而Linux中几乎所有的配置文件、日志文件(如:NFS、rsync、httpd、Nginx、lvs等)都是纯文本类型的文件。因此,如果学好shell脚本语言,就可以利用他在Linux系统中发挥巨大作用。

Shell脚本语言的种类

在UNIX和LINUX中主要有两大类shell

1)Bourne shell(包括sh,ksh,bash)

Bourne shell (sh)

Kor n shell (ksh)

Bourne Again shell (bash)

POSIX shell (sh)

2)C shell(包括csh,tcsh)

C shell (csh)

TENEX/TOPS Cshell (tcsh)

Shell脚本语言是弱类型语言,较为通用的shell有标准的Bourne shell(sh)和C shell (csh)。其中Bourne shell(sh)已经被bash shell取代。

查看系统的SHELL:

[root@xuexi ~]# cat /etc/shells

/bin/sh

/bin/bash

/sbin/nologin

/bin/dash

/bin/tcsh

/bin/csh

其他运维人员常用的脚本语言种类:

1) PHP

PHP是网页程序,也是脚本语言。更专注于web页面的开发,列如:dedecms,discus.也可以处理系统日志,配置文件等。

2) Perl

Perl脚本语言比shell强大的多,2010前很火,语法灵活、复杂,实现方式很多,不易读,团队协作困难。

3)Python

近几年很火,可以做脚本开发,也可以实现web开发。中等以上企业都要求会Python。

Shell与PHP、Perl、Python语言的区别和优势:

Shell的优势在于处理操作系统底层的业务,因为有大量的命令为它做支持,2000多个命令都是shell编程的有力支持,特别是grep,awk,sed等;例如:一键软件安装、优化,监控报警脚本,常规的业务应用,shell开发更简单便捷,符合运维的大原则。

PHP、Python优势在于开发运维工具,web界面的管理工具,以及web业务的开发等。

常见操作系统默认shell

Linux是Bourne Again shell (bash)

Solaris和FreeBSD是Bourne shell (sh)

AIX下是Korn shell (ksh)

HP-UX是POSIX shell (sh)

Shell脚本的建立和执行:

1) 脚本的开头

一个规范的shell脚本的第一行会指出由哪个程序(解释器)来执行脚本中的内容,在Linux bash编程中为:

#!/bin/bash或#!/bin/sh

其中开头的“#!”又称为幻数,在执行bash脚本的时候,内核会根据“#!”后的解释器来确定该有哪个程序解释脚本中的内容。注:这一行必须在每个脚本顶端的第一行,如果不是第一行则是注释。

2) Sh和bash的区别:

Sh是bash的一个软连接,标准写法是#!/bin/bash,但实际上都一样。

[root@xuexi ~]# ll /bin/sh

lrwxrwxrwx. 1 root root 4 Aug 31 06:13 /bin/sh -> bash

[root@xuexi bin]# bash --version

bash –version(bash的版本信息。)

GNU bash, version 4.1.2(1)-release (x86_64-redhat-linux-gnu)

Copyright (C) 2009 Free Software Foundation, Inc.

License GPLv3+: GNU GPL version 3 or later

This is free software; you are free to change and redistribute it.

There is NO WARRANTY, to the extent permitted by law.

printf "\033]0;%s@%s:%s\007" "${USER}" "${HOSTNAME%%.*}" "${PWD/#$HOME/~}"

3) 脚本注释:

在Linux中#后面的是注释,加注释既是方便自己也是方便别人,特别是关键位置,加上注释便于阅读脚本。

Shell脚本的执行:

当shell脚本以非交互式(文件方式)运行时,它会先查看环境变量ENV,该变量指定了一个环境文件(通常是.bashrc,.bash_profile,/etc/profile,/etc/bashrc等)然后从该环境变量文件开始执行,当读取ENV文件后,shell才开始执行shell脚本中的内容。

Crond定时任务需要将系统的环境变量重新定义。

Shell脚本的执行通常采用以下的三种方式:

1) bash 脚本名 或 sh 脚本名

2) 全路径/脚本名 或 ./脚本名(相对路径在当前路径下,注:用这种方法文件必须有可执行权限。)

3) Source 脚本名 或 . 脚本名 #注意“.”点号(注;这种方法运行脚本,脚本中的环境变量会影响到系统的环境变量)。

Shell脚本开发基本规范及习惯:

1) 开头指定脚本解释器。

2) 开头加版本版权等信息。

3) 脚本中不用中文注释

4) 脚本以.sh为扩展名

5) 代码书写优秀习惯。

1) 成对的符号内容要一次写出来,防止遗漏。如:”” ‘’ [] {}等

2) {}中括号里两端有空格,书写时可先预留出来再写内容。

3) 流程控制语句一次书写完,在添加内容,如:

If语句格式:

If 条件内容

Then

内容

fi

for循环一次写完

for

do

done

4) 通过缩进让代码易读。

环境变量:

环境变量用于定义shell的运行环境,保证shell命令的正确执行,shell通过环境变量来确定登录用户名、命令路径、终端类型、登陆目录等,所有的环境变量都是系统全局变量,可用于子进程中,这包括编辑器。Shell脚本和各种应用(定时任务特殊需重新定义)。

环境变量可以在命令行中定义,但用户退出时这些变量值也会丢失,因此最好在用户的家目录下的.bash_profile文件中或全局变量/etc/profile,/etc/bashrc文件或者/etc/profile.d/中定义。这样每次用户登录时这些变量值都会被初始化。

传统上,所有的环境变量均为大写。环境变量应用于用户进程前,必须用export命令导出。

环境变量可用在创建他们的shell和从该shell派生的任意子shell或进程中,他们通常被称为全局变量以区别局部变量。

用env可以查看系统定义的环境变量

设置全局环境变量:(命令行定义,用户退出或重启系统则不再生效)

1) export 变量名=value

2) 变量名=value; export 变量名

3) Declare -x 变量名=value

永久生效应将上述内容添加到环境变量的配置文件中。

显示和取消变量:

1)用echo 或 printf $变量名(printf意思:format and print data

[root@xuexi ~]# echo $USER

root

[root@xuexi ~]# printf "$USER\n"(\n换行的意思)

root

2)用env(printenv)或set显示默认的环境变量。

[root@xuexi ~]# env

HOSTNAME=xuexi

SELINUX_ROLE_REQUESTED=

TERM=xterm

SHELL=/bin/bash

HISTSIZE=1000

SSH_CLIENT=192.168.0.18 63285 22

SELINUX_USE_CURRENT_RANGE=

SSH_TTY=/dev/pts/0

USER=root

3)用unset 变量名 取消变量值

局部变量:

定义本地变量:

本地变量在用户当前的shell的脚本中使用,例如,本地变量OLDBOY取值为ett098,这个值只在用户当前shell生存期中有意义。如果在shell中启动另一个进程或退出,本地变量OLDBOY值将无效。

1)普通字符串变量定义:

变量名=value

变量名=’value’

变量名=”value”

Shell中变量名的要求:一般是字母,数字,下划线组成。字母开头。

[root@xuexi ~]# a=192.168.1.1

[root@xuexi ~]# b='192.168.1.1'

[root@xuexi ~]# c="192.168.1.1"

[root@xuexi ~]# echo "a=$a"

a=192.168.1.1

[root@xuexi ~]# echo "b=$b"

b=192.168.1.1

[root@xuexi ~]# echo "c=${c}"

c=192.168.1.1

小结:连续普通字符串内容,赋值给变量,内容是什么,变量打印就输出什么。

[root@xuexi ~]# a=192.168.1.1-$a

[root@xuexi ~]# b='192.168.1.1-$a'

[root@xuexi ~]# c="192.168.1.1-$a"

[root@xuexi ~]# echo "a=$a"

a=192.168.1.1-192.168.1.1

[root@xuexi ~]# echo "b=$b"

b=192.168.1.1-$a

[root@xuexi ~]# echo "c=${c}"

c=192.168.1.1-192.168.1.1-192.168.1.1

上述实例中,第一种a变量的方式是直接定义变量内容,内容一般为简单连续的数字、字符串、路径名等。

第二种b变量的方式是通过单引号定义变量,这个方式的特点是:输出变量时引号是什么就输出什么,即使内容中包含变量也会把变量名原样输出,此法适合定义显示纯字符串。

第三种c变量方式是通过双引号定义变量。这个方式的特点:输出变量时双引号里的变量会经过解析后输出该变量内容,而不是把引号中变量名原样输出,适合于字符串中附带有变量的内容的定义。

笔者习惯:数字不加引号,其他默认加双引号。

Grep过滤实例:

[root@xuexi ~]# vim a.txt

[root@xuexi ~]# O=testchars

[root@xuexi ~]# grep $O a.txt

testchars

[root@xuexi ~]# grep '$O' a.txt

[root@xuexi ~]# grep "$O" a.txt

testchars

awk过滤实例:

[root@xuexi ~]# ETT=123

[root@xuexi ~]# awk 'BEGIN {print "$ETT"}'

$ETT

[root@xuexi ~]# awk 'BEGIN {print '$ETT'}'

123

[root@xuexi ~]# awk 'BEGIN {print $ETT}'

[root@xuexi ~]# ETT='abc'(双引号一样)

[root@xuexi ~]# awk 'BEGIN {print '$ETT'}'

[root@xuexi ~]# awk 'BEGIN {print $ETT}'

[root@xuexi ~]# awk 'BEGIN {print "$ETT"}'

$ETT

[root@xuexi ~]# awk 'BEGIN {print "'$ETT'"}'

abc

[root@xuexi ~]# awk 'BEGIN {print '"$ETT"'}'

[root@xuexi ~]#

Sed过滤实例:

[root@xuexi ~]# vim a.txt

[root@xuexi ~]# sed -n '/$USER/p' a.txt

[root@xuexi ~]# sed -n "/$USER/p" a.txt

root

[root@xuexi ~]# sed -n /$USER/p a.txt

root

自定义普通字符串变量的建议:

1) 内容是纯数字(没空格),定义方式可以不加引号(单或双),例如:

O=123

M=yes

2) 没特殊情况,字符串一般用双引号定义,特别是多个字符串中间有空格时,例如:

U=“This is pen”

Y=” my god”

3) 变量内容需要原样输出时,用(‘’)单引号

P=’U’

变量的命名规范:

1)变量命名要统一,使用全部大写字母,如APACHE_ERRNUM;语义要清晰,能够正确表达变量内容的含义,过长的英文单词可采用前几个字符代替,多个单词连接使用“”号连接,引用时,做好以${APACHE_ERR_NUM }加大括号或“${APACHE_ERR_NUM }”外面加双引号方式引用变量;

2)避免无含义字符或数字

小结:定义变量多模仿系统的定义,规范的定义写法:

1) OLDBOYAge=1

2) oldboy_age=1

3) oldboyAgeSex=1(驼峰语法)

把命令作为变量定义方法:实例:

[root@xuexi ~]# CMD=$(date +%F)

[root@xuexi ~]# echo $CMD

2018-01-08

[root@xuexi ~]# CMD=date +%F

[root@xuexi ~]# echo $CMDbr/>2018-01-08

Shell特殊变量

1.位置变量:

$0获取当前执行的shell脚本的文件名,包括脚本路径。

$n获取当前执行的shell脚本的第n个参数值,n=1…9,当n为0时表示脚本的文件名,如果n大于9用大括号括起来${10}.

$#获取当前执行的shell脚本后面传参的参数的总个数。

$?获取执行上一个指令的返回值(0为成功,非0为失败)这个很有用。

$?返回值:0为成功,2为权限被拒,1~125表示运行失败,脚本命令,系统命令错误或参数传递错误,126是找到该命令,但无法执行,127表示找不到命令,>128表示命令被系统强制结束。

$*获取当前shell的所有参数,将所有的命令行参数视为单个字符串,相当于“$1$2$3….”注意与$#的区别。

$@这个程序的所有参数“$1””$2””$3”......,这是讲参数传递给其他程序的最佳方式,因为他会保留所有内嵌在每个参数里的任何空白。

$$获取当前shell的进程号(PID).

$!执行上一个指令的PID。

$_在此之前执行的命令或脚本的最后一个参数。

$0实例:

[root@xuexi ~]# cat d.sh

echo $0

[root@xuexi ~]# sh d.sh

d.sh

[root@xuexi ~]# cat d.sh

dirname $0

basename $0

[root@xuexi ~]# sh pwd/d.sh

/root

d.sh

$n实例:

[root@xuexi ~]# cat d.sh

$1 $2 $3 $4 $5 $6 $7 $8 $9 $10 $11 $12 $13 $14 $15

[root@xuexi ~]# sh d.sh {a..z}

a b c d e f g h i j k l m n o

$#实例:

[root@xuexi ~]# cat d.sh

echo $1 $2 $3 $4 $5 $6 $7 $8 $9 ${10} ${11} ${12} ${13} ${14} ${15}

echo $#

[root@xuexi ~]# sh d.sh {a..z}

a b c d e f g h i j k l m n o

26

[root@xuexi ~]# cat d.sh

[ $# -ne 2 ] && {

echo "muse two"

exit 1(1相当于赋值给$?)

}

echo "ok"

[root@xuexi ~]# sh d.sh qq

muse two

[root@xuexi ~]# sh d.sh qq uuu

ok

注:在脚本调用,一般用exit 0,函数retrun 0.控制命令及脚本的返回值http://oldboy.blog.51cto.com/2561410/1175971 (linux下set和eval的使用案例)

${value:-word}:如果value未定义,则变量值为word

${value:?”not defined”}:如果变量value为赋值,则会显示-bash:value: not defined

If条件句:

单分支结构:

语法:

If[条件]

Then

指令

fi

If[条件]

指令

fi

实例:

[root@xuexi ~]# cat if.sh

#!/bin/bash

file="a.txt"

dir="/server/scripts"

#no1

if [ ! -d $dir ]

then

mkdir -p $dir

fi

#no2

if [ ! -f $file ]

then

touch $dir/$file

fi

ls -l $dir/$file

[root@xuexi ~]# sh if.sh

-rw-r--r--. 1 root root 43 Dec 7 19:11 /server/scripts/a.txt

内存小于100M发邮件报警实例:

[root@xuexi ~]# cat cache.sh

#!/bin/bash

cache=free -m|awk 'NR==3 {print $NF}'

if [ $cache -lt 900 ]

then

echo "cache <900"|mail -s "cache" root

fi

多分支结构:

If 条件

Then

指令

elif 条件

then

指令

else

指令

if

实例:

[root@xuexi ~]# cat bijiao.sh

#!/bin/bash

expr $1 + 0 &>/dev/null

value=$?

expr $2 + 0 &>/dev/null

value1=$?

if [ $value -ne 0 -o $value1 -ne 0 ]

then

echo "Please re-enter"

exit 1

fi

if [ $1 -eq $2 ]

then

echo "$1 = $2"

elif [ $1 -lt $2 ]

then

echo "$1 < $2"

else

echo "$1 > $2"

fi

exit 0

检测MySQL启动是否正常,启动了给个提示,没启动就用脚本启动实例:

[root@xuexi ~]# cat listen.sh

#!/bin/bash

Port=lsof -i :3306|grep mysql|wc -l

if [ $Port -eq 1 ]

then

echo "MySQL is running"

else

/etc/init.d/mysqld start

fi

远程:http://oldboy.blog.51cto.com/2561410/942530

WEB服务监控:

[root@xuexi ~]# cat web.sh

#!/bin/bash

Port=lsof -i :80|grep httpd|wc -l

if [ $Port -ne 6 ]

then

/etc/init.d/httpd start

else

echo "Httpd is running"

fi

方法2:

[root@xuexi ~]# cat web1.sh

#!/bin/bash

value=curl -I 127.0.0.1|awk 'NR==1'|awk '{print $(NF-1)}' &>/dev/null

if [ $value -ne 200 ]

then

/tec/init.d/httpd start

else

echo "Httpd is running"

fi

web服务判断条件:

[root@xuexi ~]# lsof -i :80|wc -l(判断条件大于1即可)

7

[root@xuexi ~]# nmap 192.168.0.40 -p 80|grep open|wc -l(判断条件等于1即可)

1

[root@xuexi ~]# ps -ef|grep httpd|wc -l(判断条件大于2即可)

7

[root@xuexi ~]# curl -I -s 192.168.0.40|head -1|awk '{print $2}'(判断条件等于200即可)

200

[root@xuexi ~]# wget --spider --timeout=3 --tries=2 192.168.0.40 &>/dev/null

[root@xuexi ~]# echo $?(判断条件等于0即可)

0

测试语句:

【语法说明】:

格式一:test

格式二:[]

格式三:[[]]

说明

格式一和格式二是等价的

格式一实例:(可以man test了解详情)

[root@xuexi ~]# test -f file && echo "1" || echo 0

0

[root@xuexi ~]# test -f a.log && echo "1" || echo 0

1

加上!是非的意思;取反:

[root@xuexi ~]# test ! -f a.log && echo "1" || echo 0

0

[root@xuexi ~]# test ! -f file && echo "1" || echo 0

1

格式二实例:

[root@xuexi ~]# [ ! -f file ] && echo "1" || echo 0

1

[root@xuexi ~]# [ -f file ] && echo "1" || echo 0

0

[root@xuexi ~]# [ -f a.log ] && echo "1" || echo 0

1

[root@xuexi ~]# [ ! -f a.log ] && echo "1" || echo 0

0

格式三:实例:

[root@xuexi ~]# [[ ! -f a.log ]] && echo "1" || echo 0

0

[root@xuexi ~]# [[ -f a.log ]] && echo "1" || echo 0

1

[root@xuexi ~]# [[ -f file ]] && echo "1" || echo 0

0

[root@xuexi ~]# [[ ! -f file ]] && echo "1" || echo 0

1

文件测试操作符:

常用文件测试操作符:

-f 文件 file 若文件存在且为普通文件则真。

-d 文件 directory 若文件存在且为目录文件则真。

-s 文件 size 若文件存在且不为空(文件大小非0)则真。

-e 文件 exist 若文件存在并且是普通文件则真,要区别-f

-r 文件 read 若文件存在且可读则真

-w 文件 write 若文件存在且可写则真

-x 文件 excute 若文件存在且可执行则真

-L 文件 link 若文件存在且为链接文件则真

f1 -nt f2 newer than 若文件f1比文件f2新则真

f1 -ot f2 older than 若文件f1比文件f2旧则真

字符串测试操作符:

字符串测试操作符的作用:比较两个字符串是否相同、字符串长度是否为零,字符串是否被为NULL(注:bash区分零长度字符串和空字符串)等。

“=”比较两个字符串是否相同,与==等价,如if [ “$a”=”$b” ],其中$a这样的变量最好用””号括起来,因为如果中间有空格,*等符号就可能出错了,当然更好的方法是[ “${a}”=”${b}” ].“!=”取反的意思。

常用字符串测试操作符:

-z“字符串” 若串长度为0则真,-z可以理解为zero

-n“字符串” 若串长度不为0则真,-z可以理解为no zero

“串1”=“串2” 若字符串1等于字符串2则真,可用“==”代替“=”

“串1”!=“串2” 若字符串1不等于字符串2则真,不可用“!==”代替“!=”

字符串测试操作提示符提示:

1)-n比较字符串长度是否不为零,如果不为零则为真,如:[ -n “$myvar” ]

2) -z比较字符串是否等于零,如果等于零则为真,如:[ -z “$myvar” ]

特别注意,对于以上表格中的字符串测试操作符号,如:[ -n “$myvar” ],要把字符串用“”引起来。

4) 字符串比较,比较符号两端最好都有空格,多参考系统脚本。

[root@xuexi ~]# sed -n '30,31p' /etc/init.d/network

Check that networking is up.

[ "${NETWORKING}" = "no" ] && exit 6

整数二元比较操作符:

在[]中使用的比较符 在(())和[[]]中使用的比较符 说明

-eq = equal的缩写,相等

-ne != not equal的缩写,不相等

-gt > 大于 greater than

-ge >= 大于等于greater equal

-lt < 小于类似less than

-le <= 小于等于less equal

逻辑操作符:

在[]中使用的逻辑操作符 在[[]]中使用的逻辑操作符 说明

-a && and 与,两端都为真,则真

-o || or 或,两端有一个为真则真

! ! not 非,相反则为真。

监控web服务器是否正常:

端口:

本地:ss,netstat,lsof

远程:telnet,nmap,nc

本地进程数:

Header(http code)curl -I 返回值200就OK.

URL(wget,curl),模拟用户的方式。

PHP,Java写监控的程序,模拟用户的方式

最常用是端口和URL或监控程序的结合。

Apache的启动脚本(简单的)

[root@xuexi ~]# cat start_apache.sh

#!/bin/bash

. /etc/init.d/functions

a=$1

b=$2

apache=/etc/init.d/httpd

if [ -n "$b" ]

then

echo "USAGE:$0 {start|stop|restart}"

exit 1

fi

if [ "$a" = "start" ]

then

then

$apache $a &>/dev/null

action "starting apache" /bin/true

elif [ "$a" = "stop" ]

then

$apache $a &>/dev/null

action "stopping apache" /bin/true

elif [ "$a" = "restart" ]

then

$apache graceful &>/dev/null

action "restarting nginx" /bin/true

else

echo "USAGE:$0 {start|stop|restart}"

fi

exit 0

Shell函数:

函数的作用:简单的说函数的作用就是把程序里多次调用的相同的代码的部分,定义成一份,然后起个名字,所有的调用都只用这个名字就可以了,修改代码时,只需要改变函数体内的泰马即可。

优势:

1) 把相同的程序段定义成函数,可以较少程序代码量。

2) 增加程序的可读,易读性。

3) 实现程序的功能模块化。

Shell函数语法:

语法格式:

简单的语法:

函数名(){

指令…

Return n

}

规范的语法:

Function 函数名(){

指令…..

Return n

}

Shell的执行方法:

1) 直接执行函数名:

函数名

注意:

a. 执行函数时,不要带小括号。

b. 函数定义及函数体必须在要执行的函数名前面定义,shell的执行从上到下按行执行的。

2) 带参数的函数执行方法:

函数名 参数1 参数2

函数带参数的说明:

1) 在函数体中位置变量($1,$2,$3,$#,$*,$?以及$@)都可以是函数的参数。

2) 父脚本的参数则临时地被函数参数所掩盖或隐藏。

3) $)比较特殊,它仍是父脚本的名称。

4) 当函数完成时,原来的命令行参数会恢复。

5) 在shell函数里面,return命令的功能与工作方式与exit相同,用于跳出函数。

6) 在shell函数里使用exit会终止整个shell脚本。

7) Return语句会返回一个退出值给调用的程序。

Mysql启动脚本实例:

[root@xuexi ~]# cat startmysql.sh

#!/bin/bash

function mysql(){

/bin/sh /application/mysql/bin/mysqld_safe

}

function stopmysql1(){

/application/mysql/bin/mysqladmin -u root shutdown &>/dev/null

if [ $? -eq 0 ]

then

action "stopping mysql" /bin/true

else

action "stopping mysql" /bin/false

fi

}

. /etc/init.d/functions

if [ "$1" = "start" ]

then

mysql &>/dev/null &

if [ $? -eq 0 ]

then

action "starting mysql" /bin/true

else

action "starting mysql" /bin/false

fi

elif [ "$1" = "stop" ]

then

stopmysql1

elif [ "$1" = "restart" ]

then

stopmysql1 &>/dev/null

if [ $? -eq 0 ]

then

action "stopping mysql" /bin/true

else

action "stopping mysql" /bin/false

fi

mysql &>/dev/null &

if [ $? -eq 0 ]

then

action "starting mysql" /bin/true

else

action "starting mysql" /bin/false

fi

else

echo "usage:{start|restart|stop}"

fi

当型循环和直到型循环:

while条件句语法:

while 条件

do

指令…

Done

until 条件句语法:(使用不多,了解,直到循环)

until 条件

do

指令…

done

防止脚本执行中断的方法:

1) 执行脚本 &(后台运行脚本)

2) Screen命令

3) Nohup 脚本路径/脚本名 &

进程管理命令:

Bg:后台运行 fg:挂起程序 jobs:显示后台程序 kill/killall/pkill:杀死进程 crontab:设置定时 ps:查看进程 pstree:显示进程状态树 top:显示进程(动态) nice:改变优先权 nohup:用户退出系统之后继续工作 pgrep:查找匹配条件的进程 strace:跟踪一个进程的系统调用情况 ltrace:跟踪程序调用库函数的情况 vmstat:报告虚拟内存统计信息

While循环实例:计算100内之和:

[root@xuexi ~]# cat while1.sh

#!/bin/bash

i=1

sum=0

while [ $i -le 100 ]

do

sum=$(expr $sum + $i)

let i++

done

echo "$sum"

while循环小结:

1) while循环的特长是执行守护进程以及我们希望循环不退出持续执行,用于频率小于1分钟循环处理(crond),其他的while循环几乎都可以被我们即将要讲for循环代替。

2) case语句可以替换if语句,一般在系统启动脚本传入少量固定规则字符串,用case,其他判断多用if.

3) 一句话,if,for语句最常用,其次while(守护进程),case(服务启动脚本)。

For循环结构:

1.for循环结构语法:

For 变量名 in 变量取值列表

Do

指令

done

2.C语言型for循环结构语法:

For((exo1;exp2;exp3))

do

指令

done

用for循环实现将文件名中的oldboy全部改成linux,并且扩展名改成大写,for循环的循环体不能出现oldboy字样。实例:

[root@xuexi ~]# ls /oldboy/

oldboy_10.html oldboy_2.html oldboy_4.html oldboy_6.html oldboy_8.html

oldboy_1.html oldboy_3.html oldboy_5.html oldboy_7.html oldboy_9.html

[root@xuexi ~]# vim for2.sh

[root@xuexi ~]# sh for2.sh

[root@xuexi ~]# ls /oldboy/

linux_10.HTML linux_2.HTML linux_4.HTML linux_6.HTML linux_8.HTML

linux_1.HTML linux_3.HTML linux_5.HTML linux_7.HTML linux_9.HTML

[root@xuexi ~]# cat for2.sh

#!/bin/bash

cd /oldboy/

for i in ls

do

mv $i $(echo $i|sed 's#oldboy(.)html#linux\1HTML#g')

done

批量创建10个系统账户并设置密码(密码不態相同。)

[root@xuexi ~]# cat for.sh

#!/bin/bash

for i in seq -w 10

do

useradd oldboy$i&&\

echo "root$i"|passwd --stdin oldboy$i

done

批量创建10个系统账户并设置密码(密码不態相同且是随机数。)

[root@xuexi ~]# cat for.sh

#!/bin/bash

. /etc/init.d/functions

for i in seq -w 10

do

passwd=$(echo "$RANDOM"|md5sum|cut -c 1-8)

useradd oldboy$i&&\

echo "passwd"|passwd --stdin oldboy$i &>/dev/null &&\

action "chenggong" /bin/true

echo -e "oldboy$i\t $passwd" >>/oldboy/a.txt

done

break continue exit对比;

命令 说明

Break n n 表示跳出循环的层数,如果省略n表示跳出整个循环。

Continue n n表示退出到第n层继续循环,如果省略n表示跳过本次循环,忽略本次循环剩余代码,进入循环的下一次循环。

Exit n 退出当前shell程序,n表示返回值,n也可以省略,再下一个shell里通过$?接收这个n值。

Return n 用于在函数里,作为函数的返回值,用于判断函数执行是否正确。

Shell数组介绍

平时的定义a=1,b=2,c=3,变量如果多了,再一个一个定义很费劲,并且取变量的也费劲。

简单的说,数组就是相同数据类型的元素按一定顺序排列的集合。

数组就是把有限类型相同的变量用一个名字命名,然后用编号区分他们的变量的集合,这个名字成为数组名,编号成为数组下标。组成数组的各个变量成为数组的分量,也称为数组的元素,有时也称为下标变量。

数组的定义与增删改查:

格式1:

Array=(value1 value2 value3)

1) 数组的定义

[root@xuexi ~]# array=(1 2 3)

2) 获取数组的长度

[root@xuexi ~]# echo ${#array[@]}

3

[root@xuexi ~]# echo ${#array[]}

3

3) 打印数组的元素

[root@xuexi ~]# echo ${array[0]}

1

[root@xuexi ~]# echo ${array[1]}

2

[root@xuexi ~]# echo ${array[2]}

3

用for循环打印出字符数小于6的单词实例:

I am oldboy teacher welcome to oldboy training class

方法1:

[root@xuexi ~]# sh for4.sh

I

am

to

class

[root@xuexi ~]# cat for4.sh

#!/bin/bash

array=(I am oldboy teacher welcome to oldboy training class)

for i in $(echo ${array[@]})

do

if [ ${#i} -lt 6 ]

then

echo "$i"

fi

done

方法2:

[root@xuexi ~]# sh for4.sh

I

am

to

class

[root@xuexi ~]# cat for4.sh

#!/bin/bash

for i in I am oldboy teacher welcome to oldboy training class

do

if [ ${#i} -lt 6 ]

then

echo "$i"

fi

done

监控web站点目录(/var/html/www)下所有文件是否被恶意篡改(内容被改了),如果有就打印所改动的文件名(发邮件,定时任务每三分钟执行一次。实例:)

[root@xuexi ~]# cat file_md5.sh 创建文件对比的信息库

find /var/html/bbs/ -type f|xargs md5sum >/oldboy/md5sum.db

find /var/html/bbs/ -type f >/oldboy/a.log

[root@xuexi ~]# cat web6.sh

#!/bin/bash

n=$(cat /oldboy/a.log|wc -l)(源目录文件的行数)

while true

do

Md5=$(md5sum -c /oldboy/md5sum.db 2>>/dev/null|grep -i fail|wc -l)(md5对比错误的行数)

find /var/html/bbs/ -type f >/oldboy/new-a.log(随时查看源文件的行数)

log=/oldboy/check.log

if [ $Md5 -ne 0 ] || [ $(cat /oldboy/new-a.log|wc -l) -ne $n ]

then

echo "$(md5sum -c /oldboy/md5sum.db 2>>/dev/null|grep -i fail)" >$log

diff /oldboy/a.log /oldboy/new-a.log >>$log

mail -s "file is cuangai $(date)" 1570267901@qq.com

fi

sleep 3

done

shell脚本小结:

1) 重视书写习惯,开发规范和开发制度,尽量减少脚本调试的难度,提升开发效率。

2) 基本语法要熟悉,才能利用好调试。

3) 思路要清晰,复杂的脚本要简单化分段实现。

Shell脚本调试技巧:

1.使用dos2unix命令处理来自windows下开发的脚本。

第一步.没有安装先安装yum install -y dos2unix

第二步[root@xuexi ~]# cat -v mysql1.sh检测

第三步:[root@xuexi ~]# dos2unix mysql1.sh 用dos2unix命令格式化

dos2unix: converting file mysql1.sh to UNIX format ...

2 使用echo 命令调试

使用bash命令参数调试:

-n:不会执行改脚本,进查询脚本语法是否有问题,并给出错v误提示。

-v: 在执行脚本时,先将脚本的内容输出到屏幕上然后执行脚本,如果有错误,也会给出提示。

-x : 将执行的脚本内容及输出显示到屏幕上,这个是调试很有用的参数

4.set脚本调试工具:

使用bash -x 会把整个脚本执行一遍并检测一般,set可以分段检测,只检测你想检测的那一段。

#!/bin/bash

set -x

for n in {1..9}

do

for m in {1..9}

do

if [ $m -le $n ]

then

echo -ne "${m}x${n}=$(( $m * $n ))\t"

fi

set +x

[root@xuexi ~]# sh koujue.sh

for n in '{1..9}'

for m in '{1..9}'

'[' 1 -le 1 ']'

echo -ne '1x1=1\t'

1x1=1 + set +x

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值