Linux——shell编程基础笔记

1.变量的赋值方式

先写变量名,紧接着是“=”,最后是值,中见无空格。变量不区分变量类型,如需要指定变量类型可以使用declare显示定义变量类型。变量可分为环境变量和普通(局部)变量。shell的环境变量用来确定登陆的用户名、命令路径、终端类型、登录目录。永久保存环境变量,可以在用户家目录下的.bash_profile或.bashrc(非用户登录,如ssh)或/ect/profile中定义。

2.有3个命令可以显示环境变量的值

set、env、declare。set输出所有变量,env只显示全局变量,declare所有变量函数和已经导出的变量。set -o 显示bash shell的所有配置。

3.设置环境变量有3种方法

export a=value
a=value;export a
declare -x a=value

4.环境变量永久生效的位置

用户环境变量,/home/家目录/.bashrc(bash_profile);全局环境变量,/etc/profile(bashrc),/etc/profile.d/。

5.设置登录提示的的两种方式

修改/etc/motd
在/etc/profile.d/下增加echo脚本

6.普通变量定义三种写法

1.a=‘vaule’;2.a=value;3.a=“value”

7.输出变量

a 表 示 输 出 变 量 , 也 可 以 用 {a} 表示输出变量,也可以用 aa。
"双引号符号变量值连续输出字符,输出变量名的值;'单引号变量值原样输出。

[root@master ~]# a=12
[root@master ~]# echo '$a'
$a
[root@master ~]# echo "$a"
12
[root@master ~]# echo '${a}'
${a}
[root@master ~]# echo "${a}"
12

8.执行变量内容

a=$(ls)等价于a=ls

[root@master ~]#cmd=`ls`;echo $cmd
[root@master ~]#cmd=$(ls);echo $cmd
[root@master ~]#cmd=$(data+%F);echo $cmd
[root@master ~]#echo $(data+%F).tar.gz
[root@master ~]#tar zcf etc_$(date+%F).tar.gz /etc/

.关于date和’’、""、’’

[root@master ~]#echo "today is date"
[root@master ~]#today is date
[root@master ~]# echo 'today is date' 
[root@master ~]#today is date
[root@master ~]#echo "today is `date`"
[root@master ~]#today is Tue May 29 20:09:51 PDT 2018
       
[root@master ~]#OLDBAY=testchars
[root@master ~]#echo $OLDBOY
[root@master ~]#testchars
[root@master ~]#echo "$OLDBOY"
[root@master ~]#testchars
[root@master ~]#echo  '$OLDBOY'
[root@master ~]#$OLDBOY
[root@master ~]#cat grep.log
testchars
oldboy
[root@master ~]#grep "$OLDBOY" grep.log
[root@master ~]#testchars
[root@master ~]#grep  $OLDBOY grep.log
[root@master ~]#testchars
[root@master ~]#grep '$OLDBOY' grep.log

9.grep awk和sed与’(单引号)、"(双引号)、·(执行符号)、$

a=value或者a="value"或者a=‘value’**
grep

[root@master ~]a="value"
[root@master ~]#cat  >>  value<<  EOF
[root@master ~]#> value
[root@master ~]#> EOF
[root@master ~]#grep $a log
[root@master ~]#value
[root@master ~]#grep '$a' log
[root@master ~]#grep "$a" log
[root@master ~]#value
[root@master ~]#grep $a log  
[root@master ~]#value
[root@master ~]#grep `$a` log
[root@master ~]#syntax error

awk

[root@master ~]a="value"
[root@master ~]#awk 'BEGIN {printf "$a"}'
[root@master ~]#$a
[root@master ~]#awk 'BEGIN {printf '$a'}'
[root@master ~]#awk 'BEGIN {printf $a}'  
[root@master ~]#awk 'BEGIN {printf `$a`}'
[root@master ~]#syntax error
[root@master ~]# a=`pwd`
[root@master ~]#awk 'BEGIN {printf "$a"}'
[root@master ~]#$a
[root@master ~]#awk 'BEGIN {printf '$a'}'
[root@master ~]#syntax error
[root@master ~]#awk 'BEGIN {printf $a}'  
[root@master ~]#awk 'BEGIN {printf `$a`}'
[root@master ~]#syntax error

为了避免以上情况用echo给awk输出

[root@master ~]#a='value'
[root@master ~]#echo $a | awk '{printf $0}'
[root@master ~]#value
[root@master ~]#echo "$a" | awk '{printf $0}'
[root@master ~]#value
[root@master ~]#echo '$a' | awk '{printf $0}'   
[root@master ~]#$a
[root@master ~]#a=`pwd`
[root@master ~]#echo $a | awk '{printf $0}'
[root@master ~]#/root
[root@master ~]#echo "$a" | awk '{printf $0}'
[root@master ~]#/root
[root@master ~]#echo '$a' | awk '{printf $0}'
[root@master ~]#$a

10.特殊变量

$0:脚本执行名称及路径
$n:参数值
$#:参数个数
$@$*不加""获取传递的所有参数
$@""获取所有参数视为不同的字符串,返回数组,$*""获取所有参数视为一个字符串。
[root@master ~]# echo {1..12}
1 2 3 4 5 6 7 8 9 10 11 12
[root@master ~]# echo ${1..12}
-bash: ${1..12}: bad substitution
[root@master ~]# echo \${1..12}
$1 $2 $3 $4 $5 $6 $7 $8 $9 $10 $11 $12
[root@master ~]# echo $11 $12 $13
1 2 3

11.更改语言为中文

查看当前系统语言环境:

[root@master ~]# echo $LANG
en_US.UTF-8

查看安了哪些中文语言包

[root@master ~]# locale -a |grep "zh_CN"
zh_CN
zh_CN.gb18030
zh_CN.gb2312
zh_CN.gbk
zh_CN.utf8

没有输出,说明没有安装,输入下面的命令安装

[root@master ~]# yum groupinstall "fonts" -y
[root@master ~]# locale -a |grep "zh_CN"
zh_CN
zh_CN.gb18030
zh_CN.gb2312
zh_CN.gbk
zh_CN.utf8

说明系统已安装中文语言包,无需再安装。重要提示,如果按照下面的步骤你的系统仍然无法使用中文,那么请一个一个尝试上面的编码方式。比如把LANG="zh_CN.GBK"修改为LANG=“zh_CN.UTF-8”。
设置中文,建议做备份,

[root@master ~]# vim /etc/locale.conf
LANG="en_US.UTF-8"

将下面的代码复制到配置/etc/locale.conf文件中
LANG=“zh_CN.GBK”
LANGUAGE=“zh_CN.GB18030:zh_CN.GB2312:zh_CN”
SUPPORTED=“zh_CN.UTF-8:zh_CN:zh:en_US.UTF-8:en_US:en”
SYSFONT=“lat0-sun16”
使立即生效

 [root@master ~]source /etc/locale.conf

打开环境变量配置文件

 [root@master ~]vim /etc/profile
 export LANG=zh_CN.GBK

使立即生效

[root@master ~]source /etc/profile

11.read命令

 [root@master ~]# help read
 read [-rs] [-a ARRAY] [-d delim] [-n nchars] [-N nchars] [-p prompt] [-t timeout] [var_name1 var_name2 ...]

read命令用于从标准输入中读取输入单行,并将读取的单行根据IFS变量分裂成多个字段,并将分割后的字段分别赋值给指定的变量列表var_name。第一个字段分配给第一个变量var_name1,第二个字段分配给第二个变量var_name2,依次到结束。如果指定的变量名少于字段数量,则多出的字段数量也同样分配给最后一个var_name,如果指定的变量命令多于字段数量,则多出的变量赋值为空。
如果没有指定任何var_name,则分割后的所有字段都存储在特定变量REPLY中。
选项说明:
-a:将分裂后的字段依次存储到指定的数组中,存储的起始位置从数组的index=0开始。
-d:指定读取行的结束符号。默认结束符号为换行符。
-n:限制读取N个字符就自动结束读取,如果没有读满N个字符就按下回车或遇到换行符,则也会结束读取。
-N:严格要求读满N个字符才自动结束读取,即使中途按下了回车或遇到了换行符也不结束。其中换行符或回车算一个字符。
-p:给出提示符。默认不支持"\n"换行,要换行需要特殊处理,见下文示例。例如,"-p 请输入密码:"
-r:禁止反斜线的转义功能。这意味着""会变成文本的一部分。
-s:静默模式。输入的内容不会回显在屏幕上。
-t:给出超时时间,在达到超时时间时,read退出并返回错误。也就是说不会读取任何内容,即使已经输入了一部分。
示例1
将读取的内容分配给数组变量,从索引号0开始分配。

[root@xuexi ~]# read -a array_test
what is you name?    
[root@xuexi ~]# echo ${array_test[@]}
what is you name?
[root@xuexi ~]# echo ${array_test[0]}
what

示例2
指定读取行的结束符号,而不再使用换行符。

[root@xuexi ~]# read -d '/'
what is you name \//       # 输入完尾部的"/",自动结束read

由于没有指定var_name,所以通过$REPLY变量查看read读取的行。

[root@xuexi ~]# echo $REPLY
what is you name /

示例3
限制输入字符。输入了5个字符后就结束。

[root@xuexi tmp]# read -n 5
12345
[root@xuexi tmp]# echo $REPLY   # 输入12345共5个字符
12345

如果输入的字符数小于5,按下回车会立即结束读取。

[root@xuexi ~]# read -n 5
123
[root@xuexi ~]# echo $REPLY
123

如果使用的是"-N 5"而不是"-n 5",则严格限制读满5个字符才结束读取。

[root@xuexi ~]# read -N 5
123\n4
[root@xuexi ~]# read -N 5
123          # 3后的回车(换行)算是一个字符
4

示例4
使用-p选项给出输入提示。

[root@xuexi ~]# read -p "pls enter you name: "
pls enter you name: Junmajinlong
[root@xuexi ~]# echo $REPLY
Junmajinlong

“-p"选项默认不带换行功能,且也不支持”\n"换行。但通过$'string’的方式特殊处理,就可以实现换行的功能。

[root@node2 ~]# read -p $'Enter your name: \n'
Enter your name: 
JunMaJinLong

示例5
禁止反斜线转义功能。

[root@xuexi ~]# read -r
what is you name \?
[root@xuexi ~]# echo $REPLY
what is you name \?

示例6
不回显输入的字符。比如输入密码的时候,不回显输入密码。

[root@xuexi ~]# read -s -p "please enter your password: "
please enter your password:
[root@xuexi ~]# echo $REPLY
123456

示例7
将读取的行分割后赋值给变量。

[root@xuexi ~]# read var1 var2 var3
abc def    galsl djks
[root@xuexi ~]# echo $var1:::$var2:::$var3
abc:::def:::galsl djks

示例8
给出输入时间限制。没完成的输入将被丢弃,所以变量将赋值为空(如果在执行read前,变量已被赋值,则此变量在read超时后将被覆盖为空)。

[root@xuexi ~]# var=5
[root@xuexi ~]# read -t 3 var
1
[root@xuexi ~]# echo $var

12.echo

参数
-n 不要在最后自动换行
-e 若字符串中出现以下字符,则特别加以处理,而不会将它当成一般文字输出。
\a 发出警告声;
\b 删除前一个字符;
\c 最后不加上换行符号;
\f 换行但光标仍旧停留在原来的位置;
\n 换行且光标移至行首;
\r 光标移至行首,但不换行;
\t 插入tab;
\v 与\f相同;
\ 插入\字符;
\nnn 插入nnn(八进制)所代表的ASCII字符;
–help 显示帮助
–version 显示版本信息

[root@localhost test]# echo "Hello World"
Hello World
[root@localhost test]# echo Hello World
Hello World
[root@localhost test]# echo 'Hello World'
Hello World

上述三种方法看起来相似,但是各有一些特殊的用途和副作用。

[root@localhost test]# echo "Hello World!"
-bash: !": event not found

报错了,感叹号在双引号中竟然报错了,说明在双引号中不能使用叹号,只能在单引号或者不使用引号的情况下使用感叹号,如果需要在双引号中使用,则需要对感叹号转义。

[root@localhost test]# echo 'Hello World!'
Hello World!
[root@localhost test]# echo Hello World!
Hello World!

注意:Linux很多符号都是转义的,尽量不要使用双引号
打印彩色输出
示例1

[root@master ~]# echo -e "\033[30m 黑色字 \033[0m"
[root@master ~]# echo -e "\033[31m 红色字 \033[0m"
[root@master ~]# echo -e "\033[32m 绿色字 \033[0m"
[root@master ~]# echo -e "\033[33m 黄色字 \033[0m"
[root@master ~]# echo -e "\033[34m 蓝色字 \033[0m"
[root@master ~]# echo -e "\033[35m 紫色字 \033[0m"
[root@master ~]# echo -e "\033[36m 天蓝字 \033[0m"
[root@master ~]# echo -e "\033[37m 白色字 \033[0m"
 

[root@master ~]# echo -e "\033[40;37m 黑底白字 \033[0m"
[root@master ~]# echo -e "\033[41;37m 红底白字 \033[0m"
[root@master ~]# echo -e "\033[42;37m 绿底白字 \033[0m"
[root@master ~]# echo -e "\033[43;37m 黄底白字 \033[0m"
[root@master ~]# echo -e "\033[44;37m 蓝底白字 \033[0m"
[root@master ~]# echo -e "\033[45;37m 紫底白字 \033[0m"
[root@master ~]# echo -e "\033[46;37m 天蓝底白字 \033[0m"
[root@master ~]# echo -e "\033[47;30m 白底黑字 \033[0m"

控制选项说明 :

\33[0m 关闭所有属性
\33[1m 设置高亮度
\33[4m 下划线
\33[5m 闪烁
\33[7m 反显
\33[8m 消隐
\33[30m – \33[37m 设置前景色
\33[40m – \33[47m 设置背景色
\33[nA 光标上移n行
\33[nB 光标下移n行
\33[nC 光标右移n行
\33[nD 光标左移n行
\33[y;xH设置光标位置
\33[2J 清屏
\33[K 清除从光标到行尾的内容
\33[s 保存光标位置
\33[u 恢复光标位置
\33[?25l 隐藏光标
\33[?25h 显示光标

背景颜色映射表

代码 颜色值
0 重置
40 黑色
41 红色
42 绿色
43 黄色
44 蓝色
45 洋红
46 青色
47 白色

字体颜色映射表

代码 颜色值
0 重置
30 黑色
31 红色
32 绿色
33 黄色
34 蓝色
35 洋红
36 青色
37 白色

13.case分支语句

取得的值将检测匹配的每一个模式。一旦模式匹配,则执行完匹配模式相应命令后不再继续其他模式。如果无一匹配模式,使用星号 * 捕获该值,再执行后面的命令。

#!/bin/bash
echo 'Input a number:'
read Num
case $Num in
    1)  echo 'You select 1'
    ;;
    2)  echo 'You select 2'
    ;;
    3)  echo 'You select 3'
    ;;
    4|5)  echo 'You select 4 or 5'
    ;;
    *)  echo 'default'
    ;;
esac
#!/bin/bash
option=$1
case ${option} in
   -f) echo "param is -f"
      ;;
   -d) echo "param is -d"
      ;;
   *) 
      echo "$0:usage: [-f ] | [ -d ]"
      exit 1  #退出码
      ;;
esac 

13.for循环语句

一般格式

for 变量 in 列表
do
    command1
    command2
    ...
    commandN
done

列表是一组值(数字、字符串等)组成的序列,每个值通过空格分隔。每循环一次,就将列表中的下一个值赋给变量。​ in 列表是可选的,如果不用它,for 循环使用命令行的位置参数。

[root@master ~]# vim test.sh
#!/bin/bash
for var in 1 2 3 4 5
do
    echo "The value is: $var"
done
[root@master ~]# bash test.sh
The value is: 1
The value is: 2
The value is: 3
The value is: 4
The value is: 5
[root@master ~]# vim test.sh
#!/bin/bash
for str in 'This is a string'
do    
    echo $str
done
[root@master ~]# bash test.sh
This is a string

显示主目录下以 .bash 开头的文件

[root@master ~]# vim test.sh
#!/bin/bash
for FILE in $HOME/.bash*
do   
    echo $FILE
done
[root@master ~]# bash test.sh
/home/where/.bash_history
/home/where/.bash_logout
/home/where/.bashrc 

14.while循环语句

​ while循环用于不断执行一系列命令,也用于从输入文件中读取数据;命令通常为测试条件。其格式为:

while expression
do
   ...
done
[root@master ~]# vim test.sh
#!/bin/bash
COUNT=0
while [ $COUNT -lt 5 ]
do
    COUNT=$(($COUNT + 1))
    echo $COUNT
done
[root@master ~]# bash test.sh
1
2
3
4
5

while循环可用于读取键盘信息,输入信息被设置为变量FILM,按结束循环。

[root@master ~]# vim test.sh
#!/bin/bash
echo -n 'input film: '
while read FILM
do
    echo "great film the $FILM"
done
[root@master ~]# bash test.sh
input film:gongfu
great film gongfu

15.shell函数

函数可以让我们将一个复杂功能划分成若干模块,让程序结构更加清晰,代码重复利用率更高。像其他编程语言一样,Shell 也支持函数。Shell 函数必须先定义后使用。

[root@master ~]# help function
function: function name { COMMANDS ; } or name () { COMMANDS ; }
    Define shell function.
    
    Create a shell function named NAME.  When invoked as a simple command,
    NAME runs COMMANDs in the calling shell's context.  When NAME is invoked,
    the arguments are passed to the function as $1...$n, and the function's
    name is in $FUNCNAME.
    
    Exit Status:
    Returns success unless NAME is readonly.
function_name () {
    [commands]
    ...
    [ return value ]
}

可以在函数名前加上关键字 function:

function function_name () {
    [commands]
    ...
    [ return value ]
}

函数返回值,可以显式增加return语句;如果不加,会将最后一条命令运行结果作为返回值。
Shell 函数返回值只能是整数,一般用来表示函数执行成功与否,0表示成功,其他值表示失败。如果 return 其他数据,比如一个字符串,往往会得到错误提示:“numeric argument required”。
​ 如果一定要让函数返回字符串,那么可以先定义一个变量,用来接收函数的计算结果,脚本在需要的时候访问这个变量来获得函数返回值。

[root@master ~]# vim test.sh 
#!/bin/bash
myfunc () {
   echo "hello world"
}
myfunc
[root@master ~]# bash test.sh  
hello world 

调用函数只需要给出函数名,不需要加括号。
函数返回值

[root@master ~]# vim test.sh 
#!/bin/bash
myfunc(){
   echo "hello world"
   return 5
}
myfunc
echo "myfunc return $?"
[root@master ~]# bash test.sh
hello world
myfunc return 5

函数返回值在调用该函数后通过 $? 来获得。
函数嵌套调用

[root@master ~]#  ./test.sh 
myfunc1
myfunc2

函数参数传递

[root@master ~]# vim test.sh 
#!/bin/bash
myfunc () {
   echo "myfunc $1 $2 $@"
}
myfunc
[root@master ~]#  ./test.sh 
myfunc 1 2 1 2 3

函数取消
像删除变量一样,删除函数也可以使用 unset 命令。
unset function_name
函数中定义变量
​在函数中定义的变量在整个shell脚本中都能使用。

[root@master ~]# vim test.sh 
#!/bin/bash
myfunc () {
   echo "myfunc"
   var=888
}
myfunc
echo $var
[root@master ~]#  ./test.sh 
where@ubuntu:~$ ./test.sh 
myfunc
888 

16.dir dirname basename

[root@master ~]# dir /server/sh.sh
[root@master ~]# /server
[root@master ~]# basename /server/sh.sh
[root@master ~]# sh.sh

[root@master ~]# cat n.sh
dirname $0
basename $0

17.if的两种表达方式

 [ $# -ne 2 ] && { echo ""; exit 1; }
 if [ $# -ne 2] 
 then 
	echo;
	exit 1;
 fi
[root@resource yum]# if [ $# -ne 2 ];then echo "s";   fi;
s

18.传参的方式

生成脚本
[root@master ~]# echo ${1…12} >> a.sh
[root@master ~]# vim a.sh
$1 $2 $3 $4 $5 $6 $7 $8 $9 $10 $11 $12

19.set – $@ ∗ " * " "@" "$*"区别

[root@master ~]# set  --  "I am" handsome boy
[root@master ~]# echo $# $1 $2 $3
3 I am handsome boy
[root@master ~]# echo $*
I am handsome boy
[root@master ~]# echo $@
I am handsome boy
[root@master ~]# for i in $*;do echo $i;done;
I
am
handsome
boy
[root@master ~]# for i in $@;do echo $i;done;
I
am
handsome
boy
[root@master ~]# echo "$*"
I am handsome boy
[root@master ~]# echo "$@"
I am handsome boy
[root@master ~]# for i in "$*";do echo $i;done;
I am handsome boy
[root@master ~]# for i in "$@";do echo $i;done;
I am
handsome
boy

20.shift n

[root@master ~]# set -- "i am" handsome boy
[root@master ~]# shift
[root@master ~]#  echo $1
handsome
[root@master ~]#  echo $#
2
echo $1 $2
if [ $# -eq 2 ]; then
       shift;
       echo $1
fi

21.eval

当shell执行到eval时,会将eval后的参数组合成一个新的命令执行。

[root@master ~]# set 11 22 33 44
#输出最后一个参数值 
#得到结果为44
[root@master ~]# eval echo "\$$#"

22.零星知识

#判断语句

[root@master ~]# cat a.sh
[ $#  -ne 2 ] &&
{
      echo "must have two args"
      exit 119
}

#输出不换行

[root@master ~]#echo -n oldboy;echo oldboy;
oldboyoldboy

#行输入
while read line
do
echo $line;
done;

23.exec

在不创建新子进程的情况下执行后面的语句,执行完毕后,进程退出,包括在终端下,执行完毕,终端退出登录。

[root@master temp]# vim a.sh
exec date
       while read line
              do
              echo $line;
              done;

24. $? $$ $! $_

$$获取当前执行的进程号; $! 获取上一次执行的进程号 ;
$_获取上一次执行的最后一个参数 ;
$? 获取返回值0 1 。

25.变量子串

a = {a}= a=a
${#a}:获取a的长度
${a:offset}:获取offset后的子串
${a:offset:length}:获取offset后length的子串
${a:#subword}:从开头删除subword最短匹配子串
${a:##subword}:从开头删除subword最长匹配子串
${a:%subword}:从结尾删除subword最短匹配子串
${a:%%subword}:从结尾删除subword最长匹配子串
${a:/pattern/string}:用string替换第一个pattern匹配的字串
${a://pattern/string}:用string替换所有pattern匹配的字串

26.获取长度

[root@master ~]#  expr length $a
[root@master ~]#  echo $a | wc -L
[root@master ~]#  echo $a | awk '{printf length($0)}'
[root@master ~]#  echo ${#a}
[root@master ~]#  echo ${a#} //输出a的值,#忽略
[root@master ~]# a='abc$$$$$abc'
#abc不加''
[root@master ~]#  echo ${a##abc} 
#abc不加''
[root@master ~]#  $$$$$abc
#全部删除
[root@master ~]#  echo ${a##a*c} //abc不加''
[root@master ~]# f=str_finish.jpg
[root@master ~]# echo ${f//_finish/}
[root@master ~]# str.jpg

27.time

计算程序执行时间

[root@master ~]# time for i in seq 12 ;do sleep 1 ; done;
       real    0m2.008s
       user    0m0.005s
       sys     0m0.000s
[root@master ~]# time for n in {1...1000}; do char=`seq -s "oldboy" 100`; echo ${char}/expr length $char/${char}|wc -L|awk '{print length($0)}';done 
[root@master ~]# for f in `ls *fin*.jpg`;do mv $f `echo ${f//_finshd}`

28.变量子串扩展

${a:-word}:若a未赋值或为空,则用word替换a输出
${a:=word}:若a未赋值或为空,则用word赋值a输出a
${a:?word}:若a未赋值或为空,则用word作为报错信息输出
${a:+word}:若a未赋值或为空,什么都不做,若a赋值,用word代替a的值

[root@master ~]# find ${path:-/tmp} -name "*.tar.gz" -type f -mtime +9|xargs rm -f

29.运算符

$((a+b)) == $[a+b] 数字运算符

[root@master ~]# a=1
[root@master ~]# b=2
[root@master ~]# echo ((a+b))
-bash: syntax error near unexpected token `('
[root@master ~]# echo $((a+b))
3
[root@master ~]# echo $[a+b]
3
[root@master ~]# a=12;b=13
[root@master ~]#  i=a+b
[root@master ~]# echo $i
a+b
[root@master ~]# a+b
-bash: a+b: command not found
[root@master ~]# ((i=a+b))
[root@master ~]# echo $i
25

#以上不能是浮点数,只能是整数
#在((和[内的变量可以去掉$

[root@master ~]# ((a=12*44)
>  ^C
[root@master ~]# echo $((a=12*44))
528
[root@master ~]# ((i=12))
[root@master ~]# ((i=i*4))
[root@master ~]#  echo $i
48
[root@master ~]# echo $((12<11))
0
[root@master ~]# a=1
[root@master ~]# echo $((a++))
1
[root@master ~]# echo $(($a++))
-bash: 2++: syntax error: operand expected (error token is "+")
[root@master ~]# vim caculate.sh
#!/bin/bash 
a=$1;
b=$2;
echo "a+b=$((a+b))"
[root@master ~]# bash  caculate.sh 11 22
a+b=33

30.判断整数

[ -n “echo $num | sed 's/[0-9]//g'”]
[ $? -eq 0 ] && echo int || echo chars

31. if &&

if […] && [ ]…
[ $? -eq 0 ] && echo int || echo chars

32 .计算结果

[root@master ~]#  vim a.sh
 echo $(($1))
[root@master ~]#  ./a.sh 12+1
[root@master ~]#  let a="+"
-bash: let: a=+: syntax error: operand expected (error token is "+")

函数调用不得加()

#!/bin/bash
num1=0
num2=0
let operator=1
function print_usage()
{
        printf "please input an integer!"
        exit 1
}
function unempty()
{
       if [ -n "`echo ${num1} | sed 's/[0-9]//g'`"] && [ -n "`echo ${num2} |sed 's/[0-9]//g'`"]
       then 
         print_usage;
       fi  
       exit 0
}
     

function input1()
{ 
        read -p "please input first number(input q quit):" num1 
} 
function input2()
{ 
        read -p "please input second number(input q quit):" num2 
}
function inputoperator()
{
       read -p "please input operator(+-*/)" operator
       while true
       do
        if [ "${operator}" = "+" ] ||  [ "${operator}" = "-" ] ||  [ "${operator}" = "*" ] ||  [ "${operator}" = "/" ]
        then
          break
        fi
       done
}

while true
do
       input1
       if [ "${num1}" = "q" ] || [ "${num2}" = "q" ];then
         break
       fi
       input2
       if [ "${num1}" = "q" ] || [ "${num2}" = "q" ];then
         echo $num1
         break
       fi
       inputoperator
       echo $(($num1$operator$num2)) 
done

33.let

[root@master ~]# let a=a++

34.计算表达式三种方法

[root@master ~]# c=$((a+b))
[root@master ~]# c=$[a+b]
[root@master ~]# let c=a+b

35.expr

[root@master ~]# expr 2 + 2
[root@master ~]# expr 2 /* 2
[root@master ~]# unset i
[root@master ~]# i=expr 2 * 2
[root@master ~]# echo i 1. 可 以 计 算 整 数 也 可 以 计 算 浮 点 数 2. 数 字 和 运 算 符 之 间 必 须 有 空 格 , 否 则 原 样 输 出 3. 参 加 运 算 的 字 符 串 必 须 是 整 数 , 如 果 不 是 i 1.可以计算整数也可以计算浮点数 2.数字和运算符之间必须有空格,否则原样输出 3.参加运算的字符串必须是整数,如果不是 i1.2.3.?为0
[root@master ~]# i=5
[root@master ~]# expr $i+6 &>/dev/null
[root@master ~]# echo $?
[root@master ~]# 0

36.expr 函数

STRING : REGEXP
anchored pattern match of REGEXP in STRING
match STRING REGEXP
same as STRING : REGEXP
substr STRING POS LENGTH
substring of STRING, POS counted from 1
index STRING CHARS
index in STRING where any CHARS is found, or 0
length STRING
length of STRING

if expr “$1” : “.*.pub” & >/dev/null then … //判断扩展名
for i in i am boy ; do [ expr length $i -le 2 ] && echo … || echo … ;done;

输入的参数和默认的参数要通过一个变量赋值,否则就容易出现条件判断错误。

#!/bin/bash
argnum=$#
arg1=$1
function checkInteger(){
#[ "$#" -eq  "0" ] && echo  "please input interger"
#[ $# -eq  1 ] && echo  "please input interger"
if  [[ $argnum == 0 ]]   then  
     echo "please input args"
fi
}

function main()
{
    checkInteger
}

main

37. bc

[root@master ~]# echo 'scale=3;4+12' | bc

38. 生成连续字符串

[root@master ~]# seq -s "+" 1 12
1+2+3+4+5+6+7+8+9+10+11+12
[root@master ~]# echo {1..12} | tr ' ' '+'
1+2+3+4+5+6+7+8+9+10+11+12
[root@master ~]# echo `seq -s '+' 10` = `seq -s "+" 10 | bc` 
1+2+3+4+5+6+7+8+9+10 = 55
[root@master ~]# echo `seq -s "+" 10` = `seq -s " + " 10 | xargs expr`
1+2+3+4+5+6+7+8+9+10 = 55
[root@master ~]# echo `seq -s "+" 10` = $((`seq -s "+" 10`))
1+2+3+4+5+6+7+8+9+10 = 55
[root@master ~]# echo `seq -s "+" 10` =  $[ `seq -s '+' 10`]
1+2+3+4+5+6+7+8+9+10 = 55

39.使用awk运算

[root@master ~]# echo  "44 33" | awk '{ printf $1-$2}'
11

40.declare

[root@master ~]# declare -i a=12 b=13
[root@master ~]# c=a+b
[root@master ~]# echo $c
a+b

41.read

[root@master ~]# read -p 'please input numer' -t 5 a b //a b不带$
please input numer-bash: read: `//a': not a valid identifier

42.条件测试方法(不加if)

test express
[ express ] express 两边有空格,不能用&& == >,只能用-a -o -gt -lt -eq
[[ express ]] express 两边有空格,是对[]的扩展,可以用 && == >
((express)) express 两边无空格

43. 测试操作符

( EXPRESSION )
EXPRESSION is true
! EXPRESSION
EXPRESSION is false
EXPRESSION1 -a EXPRESSION2
both EXPRESSION1 and EXPRESSION2 are true
EXPRESSION1 -o EXPRESSION2
-n STRING
the length of STRING is nonzero
STRING equivalent to -n STRING
-z STRING
the length of STRING is zero
STRING1 = STRING2
the strings are equal
STRING1 != STRING2
the strings are not equal
INTEGER1 -eq INTEGER2
INTEGER1 is equal to INTEGER2
INTEGER1 -ge INTEGER2
INTEGER1 is greater than or equal to INTEGER2
INTEGER1 -gt INTEGER2
INTEGER1 is greater than INTEGER2
INTEGER1 -le INTEGER2
INTEGER1 is less than or equal to INTEGER2
INTEGER1 -lt INTEGER2
INTEGER1 is less than INTEGER2
INTEGER1 -ne INTEGER2
INTEGER1 is not equal to INTEGER2
FILE1 -ef FILE2
FILE1 and FILE2 have the same device and inode numbers
FILE1 -nt FILE2
FILE1 is newer (modification date) than FILE2
FILE1 -ot FILE2
FILE1 is older than FILE2
-b FILE
FILE exists and is block special
-c FILE
FILE exists and is character special
-d FILE
FILE exists and is a directory
-e FILE
FILE exists
-f FILE
FILE exists and is a regular file
-g FILE
FILE exists and is set-group-ID
-G FILE
FILE exists and is owned by the effective group ID
-h FILE
FILE exists and is a symbolic link (same as -L)
-k FILE
FILE exists and has its sticky bit set
-L FILE
FILE exists and is a symbolic link (same as -h)
-O FILE
FILE exists and is owned by the effective user ID
-p FILE
FILE exists and is a named pipe
-r FILE
FILE exists and read permission is granted
-s FILE
FILE exists and has a size greater than zero
-S FILE
FILE exists and is a socket
-t FD file descriptor FD is opened on a terminal
-u FILE
FILE exists and its set-user-ID bit is set
-w FILE
FILE exists and write permission is granted
-x FILE
FILE exists and execute (or search) permission is granted

44.测试变量需要加引号

file1=/etc/services;file2=/set/rc.local
[ -f "$file1" ] && echo 1 || echo 0
[ -e /etc ] && echo 1
[ "${NETWORKING}" == "no" ] && exit 6;

二者都一样

[ -f  "/etc/services" ] && echo 1 || echo 0
[ -f  /etc/services ] && echo 1 || echo 0

在[]使用-eq -ne -gt -ge -lt -le 来比较数字大小,在[[]]和(())中使用== = >= >等和-eq -ne -gt -ge -lt -le来比较。

45.条测试表达式种类

[ contion ] && { .... }
[[ contion ]] && { .... }
test contion && { .... }
if [ contion ] ; then  ....  fi

46.abc两端要有空格

[ "abc" == "abc"]
过滤出含有-eq的行
grep -w  "\-eq"  /etc/init.d/fns       

47.比较操作符

[ 2 \<1 ] && echo 1
[[ 5< 6 ]] && echo 1
[[ 5 -gt 6 ]] && echo 1
((3<2)) && echo 1

(())不能使用-eq等写法,[[]]既可以使用-eq等写法,也可以使用<等写法,[]也可以使用<等写法,推荐使用-eq。
变量算术比较不用使用"":

[ $a > $b ] && echo 1
[[ $a > $b ]] && echo 1
(($a > $b]))&& echo 1

48. 逻辑操作符号

在[]和test中使用-a -o !
在[[]]和(())中使用&& !||

[ 5 -eq 6 -o 5 -gt 3 ] && echo 1
((5==6 || 5>3)) && echo 1
[ -z "$a" -o "$a" != "$b" ] && echo 1

49. 通配符

通配符只适用于[[]]

if [[ "$source"=*" via "* ]]; then... fi
if [[ $sports" =~_r?ntedev ]]; then... fi

50. 脚本传参

#!/bin/bash
var = $1
[ "$var" == "1" ] && {
       echo 1 
       exit 0
}
[ "$var" == "2" ] && {
       echo 2
       exit 0
}
[ "$var" != "2" -a "$var" != "1" ] &&
       echo error
       exit 0
}
if [ "$var != "2" -a "$var" != "1"]
then
{
       echo error
       exit 0
}
fi

51. read读入参数

#!/bin/bash
echo -n "please input char"  //-n不换行
read var
var = $1
[ "$var" == "1" ] && {
       echo 1 
       exit 0
}
[ "$var" == "2" ] && {
       echo 2
       exit 0
}
[ "$var" != "2" -a "$var" != "1" ] &&
       echo error
       exit 0
}

(1)read -t 5 -p “please input two number:” a1 a2
(2)[[]]可以带模式匹配
(3)&&||两端可以有空格也可以没有空格
(4)test -z filename && echo true || echo false 判断文件是否为空
[ -f filename ] && echo exist || echo not exist判断文件是否存在
(5)f1 -ot f2 f1 older f2
f1 -nt f2 f1 newer f2

52. 带目录的判断,可以将cat放在menu函数内

cat <<END 
1.......
2.........
3.........
END
read -p "which do you like?" a
[ "$a" == "1" ] && { echo ... ; exit 0 ;}
[ "$a" == "2" ] && { ..... }
[ "$a" == "3" ] && { ..... }
[[ "$a" =~ [ 1-4  ] ]] && { ..... } 不等于1-4

53. 完整的判断输入参数

path=/server/script
[ ! -d "$path" ] && mkdir &path -p
#menu
cat <<END
1.install lamp
2.install lnmp
3.exit
END
read num 
expr &num+1 &>/dev/null
[ $? -ne 0 ] && {
       echo "the num you input must be{1|2|3}"
       exit 1
}
[ $num -eq 1] && {
       echo "start installing lamp"
       sleep 2;
       [ -x "$paht/lamp.sh" ] || {
              echo "$path/llamp.sh not exist or can not exec."
              exit 1;
       }
       $path/lamp.sh
       exit $?
}
[ $num -eq 2] && {
       echo "start installing lnmp"
       sleep 2;
       [ -x "$paht/lnmp.sh" ] || {
              echo "$path/llnmp.sh not exist or can not exec."
              exit 1;
}
       $path/lnmp.sh
       exit $?
}
[ $num -eq 3] && {
       echo "bye"
       exit 3
}
[[ $num = ~[1-3] ]] && {
       echo "input eror"
       exit 4
}

54. if elif

if conition
then

elif conition
then

else
fi

55. if 条件表达式

if test 表达式
       then
       ....
fi
if  [ 字符串和算术表达式 ]
       then
       ....
fi
if  [[ 字符串表达式 ]]
       then
       ....
fi
if  ((算术表达式))
       then
       ....
fi
if  命令
       then
       ....
fi
#!/bin/bash
if `ls`
       then
       echo "fail"
fi
command not found

56. 发送邮件

echo -e " set from [email protected] smtp=smtp.163.com set smtp-auth-user=oldboy smtp-auth-psassword=… smtp-auth=login >> /etc/mail.rc
echo “oldboy” | mail -s “title” [email protected]
mail -s “title” [email protected] < /tmp/test.txt

57. 监控内存

FreeMem=free -m | awk 'NR==3 {print $NF}'
Chars=“current memory is $FreeMem”
if [ $FreeMe -lt 100 ] then
echo $Chars | tee /temp/message.txt
mail -s "date +F -%T $Chars" [email protected] < /temp/message.txt
fi

58. 监控服务运行状态一

1.采用监控端口的方式,监控本地服务运行状态
# netstat -nlt
Active Internet connections (only servers)
Proto Recv-Q Send-Q Local Address           Foreign Address         State      
tcp        0      0 0.0.0.0:111             0.0.0.0:*               LISTEN     
tcp        0      0 0.0.0.0:80              0.0.0.0:*               LISTEN     
tcp        0      0 0.0.0.0:22              0.0.0.0:*               LISTEN     
tcp        0      0 0.0.0.0:3306            0.0.0.0:*               LISTEN     
tcp6       0      0 :::111                  :::*                    LISTEN     
# netstat -nlt | grep 3306 | awk -F "[ : ]+" '{print $5}'	
Address
111
80
22
3306
*
# netstat -lnutp | grep 3306 | wc -l
1
# netstat -lnutp | grep mysql| wc -l
1
# ss -lnutp | grep 3306 | wc -l
1
# ss -lnutp | grep mysql| wc -l
1
# lsof -i  tcp:3306 | wc -l
# lsof -i:3306 | wc -l
2.采用远端监控服务器端口的方式,监控本地服务运行状态
# nmap 211.159.169.159 3306 | grep mysql | wc -l
1
# echo -e "\n" | telnet 211.159.169.159 3306 2>/dev/null | grep Connected | wc -l
1
# nc -w 2 211.159.169.159 3306 &>/dev/null
# echo $?
0
# ps -ef | grep mysql |grep -v grep | wc -l //服务器运行
3
              
# curl -s -o /dev/null 211.159.169.159 &>/dev/null
# echo $?
0 
wget -T 10 -q --spider 211.159.169.159/index.html &>/dev/null
# echo $?
0  
wget --timeout  10 --tries=2 --spider 211.159.169.159/index.html &>/dev/null
# echo $?
0

58. 脚本监控服务运行状态二

if [ `netstat -tnlp |grep 3306 | awk -F:[  : ] '{print $5}'` -eq 3306 ];
if [ "`netstat -tnlp |grep 3306 | awk -F:[  : ] '{print $5}'`" == "3306" ];
if [ `netstat -ltunlp | grep mysql | wc -l ` -gt 0 ];
if [ `lsof -i tcp:3306 | wc -l ` -gt 0 ];
then 
	echo "Mysqld is runing"
else 
	echo "Mysqld is stoped"
fi

if [ `rpm -qa nmap | wc -l` -lt 1 ] && yum install nmap -y &>/dev/null
if[ `nmap 211.159.169.159 -p 3306 2>/dev/null | grep open | wc -l ` -gt 0 ]
then 
	echo "Mysqld is runing"
else 
	echo "Mysqld is stoped"
fi

if [ `rpm -qa nmap | wc -l` -lt 1 ] && yum install nmap -y &>/dev/null
if[ `nc -w 2 211.159.169.159  3306  &>/dev/null  && echo ok | grep ok  | wc -l ` -gt 0 ]
then 
	echo "Mysqld is runing"
else 
	echo "Mysqld is stoped"
fi
 
if[ `ps -ef | grep -v grep | grep mysql | wc -l ` -gt 0 ]
then 
	echo "Mysqld is runing"
else 
	echo "Mysqld is stoped"
fi

60. 监控网页头信息

# curl -I -s -w "%{http_code}\n"  -o /dev/null 211.159.169.159
# `curl -I -s -w "%{http_code}\n"  -o /dev/null 211.159.169.159 ` =~ [23[0[012]
if [ `curl -I 211.159.169.159 2>/dev/null | head -1 | egrep "200|302|301" | wc -l`  -eq 1]
then echo "Nginx is running"
else echo "Nginx stoped"
fi        
content_type   The Content-Type of the requested document, if there was any.
filename_effective     The ultimate filename that curl writes out to. This is only meaningful if curl is told to write to  a  file  with  the  --remote-name  or     --output option. It's most useful in ombination with the --remote-header-name option. (Added in 7.25.1)
ftp_entry_path The initial path curl ended up in when logging on to the remote FTP server. (Added in 7.15.4)
time_namelookup
http_code      The  numerical response code that was found in the last retrieved HTTP(S) or FTP(s) transfer. In 7.18.2 the alias response_code was added    to show the same info.
http_connect   The numerical code that was found in the last response (from a proxy) to a curl CONNECT request. (Added in 7.12.4)
local_ip       The IP address of the local end of the most recently done connection - can be either IPv4 or IPv6 (Added in 7.29.0)
local_port     The local port number of the most recently done connection (Added in 7.29.0)
num_connects   Number of new connects made in the recent transfer. (Added in 7.12.3)
num_redirects  Number of redirects that were followed in the request. (Added in 7.12.3)
redirect_url   When an HTTP request was made without -L to follow redirects, this variable will show the actual URL a redirect would take you to. (Added in 7.18.2)
remote_ip      The remote IP address of the most recently done connection - can be either IPv4 or IPv6 (Added in 7.29.0)
remote_port    The remote port number of the most recently done connection (Added in 7.29.0)
size_download  The total amount of bytes that were downloaded.
size_header    The total amount of bytes of the downloaded headers.
size_request   The total amount of bytes that were sent in the HTTP request.
size_upload    The total amount of bytes that were uploaded.
speed_download The average download speed that curl measured for the complete download. Bytes per second.
speed_upload   The average upload speed that curl measured for the complete upload. Bytes per second.
ssl_verify_result    The result of the SSL peer certificate verification that was requested. 0 means the verification was successful. (Added in 7.19.0)
time_appconnect   The time, in seconds, it took from the start until the SSL/SSH/etc connect/handshake to the remote host was completed. (Added in 7.19.0)
time_connect   The time, in seconds, it took from the start until the TCP connect to the remote host (or proxy) was completed.  The time, in seconds, it took from the start until the name resolving was completed.
time_pretransfer     The time, in seconds, it took from the start until the file transfer was just about to begin. This includes all pre-transfer commands and    negotiations that are specific to the particular protocol(s) involved.
time_redirect  The time, in seconds, it took for all redirection steps include name lookup, connect, pretransfer and transfer before the final  transaction was started. time_redirect shows the complete execution time for multiple redirections. (Added in 7.12.3)
time_starttransfer     The  time,  in  seconds, it took from the start until the first byte was just about to be transferred. This includes time_pretransfer and    also the time the server needed to calculate the result.
time_total     The total time, in seconds, that the full operation lasted. The time will be displayed with millisecond resolution.
url_effective  The URL that was fetched last. This is most meaningful if you've told curl to follow location: headers.

60. 监控nginx服务异常

wget -O /etc/yum.repos.,d/epel.repo  http://mirrors.aliyun.com/repo/epel1-6.repo
yum install nginx -y
/etc/init.d/nginx start
curl http://127.0.0.1
通过命令检测nginx服务是否运行正常
netstat  -lnt|grep -w 80 | awk -F "[  :]"+" '{print $5}'
netstat  -lntip | grep -w 80 | wc -l
netstat -lntup | grep mysql | wc -l
ss -lntup | grep -w 80 | wc -l
ss -lntup | grep -w 80 | wc -l
lsof -i tcp:80 | wc -l
在远端监控服务器本地端口
namp 127.0.0.1 -p 80 | grep open | wc -l
echo -e "\n"|telnet 127.0.0.1 80 2>/dev/null |grep Connected | wc -l
nc-w 2 127.0.0.1 80 &>/dev/null  && echo $?
对服务进程监控
ps -ef | grep nginx | grep -v | wc -l
ps -C nginx --no-header | wc -l
测试网站
wget --spider --timeour=10 --tries-2 http://127.0.0.1 &>/dev/null
echo &?
wget -T 10 -q --spider http://127.0.0.1  &>/dev/null
echo &?
curl -s -o /dev/null http://127.0.0.1
echo &? 
curl -I -s -w "%{http_code}\n" -o /dev/null http://127.0.0.1

if [ `netstat -lnt | grep 80 |awk -F "[ :]+" '{print $5}'` -eq 80]
if [ "`netstat -lnt | grep 80 |awk -F "[ :]+" '{print $5}'`" ="80" ]
if [ `netstat  -lntup | grep ngonx | wc -l` -gt 0]
if [ `lsof -i tcp:80 | wc -l ` -gt 0 ]

[ rpm -qa nmap | wc -l  -lt 1 ] && yum install nmap -y &>/dev/null
if [ `nmap 127.0.0.1 -p 80 2 >/dev/null | grep open | wc -l ` -gt 0 ]
...................p141
[ `rpm -qa nc |wc -l` -lt 1 ] yum install nc -y &> /dev/null
if [ `nc -w 2 127.0.0.1 80 &>/dev/null && echo ok | grep ok | wc -l ` -gt 0 ]

if [ `ps -ef | grep -v grep | grep nginx | wc -l` -ge 1 ]

if [[ `curl -I -s -o /dev/null -w "%{http_code}\n" http://127.0.0.1` =~[23]0[012]  ]]

if [ `curl -I http://127.0.0.1 2 >/dev/null/head -1 | egrep "200|302|301" | wc -l ` -eq 1 ]

if [ "`curl -s http://127.0.0.1` " = "oo" ]

61. 判断是否为数字

exper $a+1 $>/dev/null
RETVAL=$?
if [[ $RETVAL = 0 ]] 
判断数字是否为空
if [ -z $a ]

-n 判断变量长度不为0
-z 判断变量长度为0

62. 判断字符串为纯数字字符串

[ -n "`echo 123 | sed 's/[0-9]//g'`" ] && echo char || echo int ]
[ -z "`echo 123 | sed 's/[0-9]//g'`" ] && echo int || echo char ]
[ -z "`echo "${num//[0-9]/}"`" ] && echo int || echo char
[[ -n $num && "$num“ = "${num//[^0-9]/}" ] && echo "it is num"
[[ $num =~ ^[0-9]+$ ]] && echo int || echo char

63.判断字符串长度是否为0

[ -z "dddd" ] && echo 1 || echo 0
[ -n "dddd" ] && echo 1 || echo 0
[ ${#num} != 0] && echo 1 || echo 0
[ `expr length $num ` -eq 0 ] && echo 1 || echo 0
[ `echo $num | wc -L ` -eq 0] && echo 1 || echo 0
[ 'echo $num | awk '{print lenght}' ` -eq 0 ]  && echo 1 || echo 0

64.PHP连接数据库测试(和shell木有关系)

vim test.php
<?php
$link_id = mysql_connect("hostname","user","password");
if($link_id)
{
  echo "mysql successful"
}
else
{
 echo mysql_error();
}
?>

65. 比较数字大小

65.1 第一种写法
#!/bin/bash 
a=$1
b=$2
if [ $# -eq 2 ]
	echo "$0 arg1 arg2"
	exit 2
fi
expr $a+1 &>/dev/null
RETVAL1=$?
expr $b+1 &>/dev/null
RETVAL2=$?
if [ RETVAL1 -ne 0 -a RETVAL2 -ne 0 ]; then
	echo "please input two int number"
	exit 3
fi
if [ $a -lt $b ] ; then
	echo "$a<$b"
elif [ $a -eq $b ] ; then
	echo "$a=$b"
else 
	echo "$a>$b"
fi
65.2 第二种写法
#!/bin/bash 
read -p "pls input two number" a b
expr $a+1 &>/dev/null
RETVAL1=$?
expr $b+1 &>/dev/null
RETVAL2=$?
if [ -z $a ] || [ -z $b ]
then 
	echo "please input two number again"
	exit 1
fi
if [ RETVAL1 -ne 0 -a RETVAL2 -ne 0 ]; then
	echo "please input two int number"
	exit 3
fi
if [ $a -lt $b ] ; then
	echo "$a<$b"
elif [ $a -eq $b ] ; then
	echo "$a=$b"
else 
	echo "$a>$b"
fi

66. 判定字符串为数子

 [ -n "`echo variable | sed 's/[0-9]//g`" ] && echo char || echo int
 [ -z "`echo variable | sed 's/[0-9]//g`" ] && echo int  || echo char
 [ -n "`echo 123 | sed 's/[0-9]//g`" ] && echo char || echo int        
 [ -z "`echo 123 | sed 's/[0-9]//g`" ] && echo int  || echo char
 num=oldboy123
 [ -z "`echo "${num//[0-9]/}"`" ]  && echo int  || echo char //不完善,如果num未定义
 [ -n $num -a  -z "`echo "${num//[0-9]/}"`" ] && echo int  || echo char 

 expr $num+1 &/dev/num
 echo $?

 [[ 123=~^[0-9]+$ ]] echo int || echo char

# echo oldboy | bc
0
# echo 23 | bc
23

67. 判断字符串长度为0

# [ -z "old" ] && echo 1 || echo 0
# [ -n "old" } && echo 1 || echo 0
# [ ${#str} -eq 0 ] && echo 1 || echo 0
# [ `expr length $str` -eq 0 ] && echo 1 || echo 0
# [ `echo $str | wc -L ` -eq 0 ] && echo 1 || echo 0
# [ `echo $str  | awk '{print length}' ` -eq 0 ] && echo 1 || echo 0

如果将函数放在独立的文件中,被脚本加载使用,要使用source或"."
在函数内部使用local定义局部变量,变量离开函数后消失
在函数执行的时候,函数名后面不要跟括号

cat  >>/etc/functions << - EOF  #EOF可以使用Tab而不用顶格
oldboy()
{

}
EOF

67.echo改变颜色

echo -e “\E[1;31m \E[4m blueicex \E[0m”
echo -e “\033[1;31m \033[4m blueicex \033[0m”
0关闭所有属性
[1加粗m
1高亮m
4下划线m
5闪烁m
7反显m
8消隐m
30-37前景色m
40-47背景色m

#!/bin/bash
RED="\E[1;31m"
CREEN="\E[1;32m"
YELLOW="\E[1;33m"
BLUE="\E[1;34m"
REST="\E[0m"
read -p "pls select a number 1,2,3,4" num
case "$num" in 
	1)
		echo  -e "${RED}RED${REST}"
		;;    
	2)
		echo  -e  "${YELLOW}YELLOW${REST}"
		;;    
	3)
		echo   -e "${BLUE}BLUE${REST}"
		;;    
	4)
		echo   -e "${CREEN}RED${CREEN}"
		;;   
	*)
		echo "must be 1,2,3,4"
		esac

优化版

#!/bin/bash
RED="\E[1;31m"
CREEN="\E[1;32m"
YELLOW="\E[1;33m"
BLUE="\E[1;34m"
REST="\E[0m"
function usage(){
	echo "$0 :{1|2|3|4}"
	exit 1
}
function menu(){
	cat <<END
	1.......
	2......
	3......
	4......
	END
}
function chose()
{
	read -p "pls select a number 1,2,3,4" num
	case "$num" in 
		1)
			echo   -e "${RED}RED${REST}
			;;    
		2)
			echo   -e "${YELLOW}YELLOW${REST}
			;;    
		3)
			echo   -e "${BLUE}BLUE${REST}
			;;    
		4)
			echo   -e "${CREEN}RED${CREEN}
			;;   
		*)
			usage;
	esac
}
function main()
{
	menu;
	chose;
}
main;
#!/bin/bash
RED="\E[1;31m"
CREEN="\E[1;32m"
YELLOW="\E[1;33m"
BLUE="\E[1;34m"
PINK="\E[1;35m"
REST="\E[0m"
if [ $# -ne 2] then
	echo "$0 args is two:content color{red|yellow|green|blue|pink}"
	exit 1
fi
case "$2" in 
	red|RED)
		echo   -e ${RED}$1${REST}
		;;
	blue|BLUE)
		echo   -e ${BLUE}$1${REST}
		;;      
	green|GEEN)
		echo   -e ${GREEN}$1${REST}
		;;
	yellow|YELLOW)
		echo   -e ${YELLOW}$1${REST}
		;;
	pink|PINK)
		echo  -e ${PINK}$1${REST}
		;;
esac
#!/bin/bash
RED="\E[1;31m"
CREEN="\E[1;32m"
YELLOW="\E[1;33m"
BLUE="\E[1;34m"
PINK="\E[1;35m"
REST="\E[0m"
function pushcolor()
{         
	if [ $# -ne 2 ] then
		echo "$0 args is two:content color{red|yellow|green|blue|pink}"
		exit 1
	fi
	case "$2" in 
		red|RED)
			echo -e ${RED}$1${REST}
			;;
		blue|BLUE)
			echo  -e ${BLUE}$1${REST}
			;;      
		green|GEEN)
			echo  -e ${GREEN}$1${REST}
			;;
		yellow|YELLOW)
			echo  -e ${YELLOW}$1${REST}
			;;
		pink|PINK)
			echo  -e ${PINK}$1${REST}
			;;
		esac
}
pushcolor "blueicex" red
#!/bin/bash
RED="\E[1;31m"
CREEN="\E[1;32m"
YELLOW="\E[1;33m"
BLUE="\E[1;34m"
PINK="\E[1;35m"
REST="\E[0m"
function pushcolor()
{         
	if [ $# -ne 2 ] then
		echo "$0 args is two:content color{red|yellow|green|blue|pink}"
		exit 1
	fi
	case "$2" in 
		red|RED)
			echo -e ${RED}$1${REST}
			;;
		blue|BLUE)
			echo  -e ${BLUE}$1${REST}
			;;      
		green|GEEN)
			echo  -e ${GREEN}$1${REST}
			;;
		yellow|YELLOW)
			echo  -e ${YELLOW}$1${REST}
			;;
		pink|PINK)
			echo  -e ${PINK}$1${REST}
			;;
	esac
}
function main()
{
		pushcolor $1 $2              pushcolor $*
}
main $*

68. echo加背景色

echo -e "\E[40;37m value \E0m" 
\E可以用\33代替
65.rsync
# rsync --daemon 
# netstat -tnulp | grep 873
# pkill rsync

69.rsync脚本

#!/bin/bash
. /etc/init.d/functions
REVALUE=0
killproc=0
startproc=0
if [ $# -ne 1 ] ; then
	echo "$0:{start:stop:restart}";
fi
case "$1" in
	"start"|"START")
		if [ `netstat -tnulp|grep 8730|wc -l` -ge 1 ] ;then
			action "$0 already started" /bin/false
			exit 0
		fi
		/usr/local/rsync/bin/rsync --daemon
		sleep 2
		$REVALUE = $?
		if  [ $REVALUE -eq 0 ] ; then
			action "rsycn is started" /bin/true
			exit 1
		fi
		if  [ $REVALUE -nq 0 ] ; then
			action "rsycn start faile" /bin/false
			exit 0
		fi
	;;
	"stop"|"STOP")
		if [ `netstat -tnulp|grep 8730|wc -l` -ge 1 ] ;then
			killall rsync
			sleep 2
			action "$0 already stoped" /bin/true
			exit 1
		fi
		action "rysnc is started" /bin/true
		exit 1
		;;
	"restart"|"RESTART")
		if [ `netstat -tnulp|grep 8730|wc -l` -ge 1 ] ;then
		killall rsync
		sleep 2
		killproc=`netstat -tnulp|grep 8730|wc -l`
		fi
		/usr/local/rsync/bin/rsync --daemon
		sleep 2
		startproc=`netstat -tnulp|grep 8730|wc -l`
		if [ $killproc -eq 0 -a $startproc -ge 1 ] ; then
			action "rsycn is already restart" /bin/true
			exit 1
		fi
		exit 0
		;;
		*)
			echo "$0:{start:stop:restart}"
			exit 0
			;;
		esac

70. 将rsycnd脚本加入开机自启动

需要将rsycnd脚本放在/etc/init.d/下,否则无效
chkconfig --list rsycnd
chkconfig --add rsycnd

71. 函数语法

function name(){}
function name{}
name(){}

72. return和exit的区别

72.1.return是退出函数,exit是退出脚本
72.2.如果函数放在脚本文件里,要使用source和.
72.3.使用local定义局部变量
72.4. 函数实例

#!/bin/bash
function usage()
{
	echo $"usage:$0 url";
	exit 1;
}

function check_url()
{
	wget --spider -q -o /dev/null --tries=1 -T 5 $1
	if [ $? -eq 0 ]
	then 
		echo "$1 is yes"
	else
		echo "$1 is no"
	fi
}
                
function main()
{
	if [ $# -ne 1 ]
	then
		usage
	fi
	check_url $1
}
main $* 


#!/bin/bash
. /etc/init.d/functions
function usage()
{
	echo $"usage:$0 url";
	exit 1;
}

function check_url()
{
	wget --spider -q -o /dev/null --tries=1 -T 5 $1
	if [ $? -eq 0 ]
	then 
		action "$1 is yes" /bin/true
	else
		action "$1 is no" /bin/false
	fi
}
                
function main()
{
	if [ $# -ne 1 ]
	then
		usage
	fi
		check_url $1
}
main $* 

73. 优化系统配置

`awk '{print  "wget https://github.com/blueicex/blueice1980/tree/master/yumsource/"$1}' yumfiles  `
:nohl
 #!/bin/bash
function mod_yum()
{ 
	echo "mod_yum"
	if [[ -d /etc/yum.repos.d ]] 
	then 
		mkdir /etc/yum.repos.d &>/dev/null
	fi
`awk '{print  "wget https://github.com/blueicex/blueice1980/tree/master/yumsource/"$1}' yumfiles` 
}
function close_selinux()
{ 
	echo "close_selinux"
	sed -i 's/SELINUX=enforcing/SELINUX=disabled/g' -n /etc/selinux/config 
	grep 'SELINUX=disabled' /etc/selinux/config
	setenforce 0 &>/dev/null
	getenforce 
}
function close_firewalld()
{
	echo "close_firewalld"
	iptables -F 
	systemctl stop firewalld
}
function lestest_service()
{
	echo "least_service"   
}
function adduser()
{
	echo "adduser"
	if [ `grep -w "blueicex" /etc/passwd|wc -l` -lt 1 ]
	then
		useradd blueicex 
		echo blueicex|passwd --stdin blueicex
		\cp /etc/sudoers /etc/sudoers.bak
		echo "blueicex ALL=(ALL) NOPASSWD:ALL " >> /etc/sudoers
		tail -l /etc/sudoers
	visudo -c 
	fi
}
function charset()
{
	echo "charset"
	echo 'LANG="zh_CN.UTF-8"' > /etc/sysconfig/i18n
	source /etc/sysconfig/i18n
}

function time_sync()
{
	echo "timesysnc"
	cron=/var/spool/cron/root
if [[ `grep -w "ntpdate" $cron|wc -l` -lt 1 ]]
then
	echo "*/5 * * * * /usr/sbin/ntpdate time.nist.gov >/dev/null" >> $cron
	crontab -l
fi
}
function com_line_set()
{
	echo "com_line_set"
}
function open_file_set()
{
	echo "open_file_set"
	if [[ `grep 65535 /etc/security/limits.conf|wc -l` -lt 1 ]]
	then
		echo '*  -  nofile 65535 ' >>/etc/security/limits.conf
		tail -l /etc/security/limits.conf
	fi 
}
function set_kernel()
{
	echo "set_kernel"
	if [[ `grep kenel_flag /etc/sysctl.conf|wc -l` -lt 1 ]]
	then
		cat >>/etc/sysctl.conf <<  EOF
		net.ipv4.tcp_fin_timeout = 2
		net.ipv4.tcp_tw_reuse = 1
		net.ipv4.tcp_tw_recycle = 1
		net.ipv4.tcp_syncookies = 1
		net.ipv4.tcp_keepalive_time = 1
		net.ipv4.ip_local_port_range = 4000  65000
		net.ipv4.tcp_max_syn_backlog = 16384
		net.ipv4.tcp_max_tw_buckets = 36000
		net.ipv4.route.gc_timeout = 100
		net.ipv4.tcp_syn_retries = 1
		net.ipv4.tcp_synack_retries = 1
		net.core.somaxconn = 16384
		net.core.netdev_max_backlog = 16384
		net.ipv4.tcp_max_orphans = 16384
		net.nf_conntrack_max = 25000000
		net.netfilter.nf_conntrack_tcp_timeout_established = 180
		net.netfilter.nf_conntrack_tcp_timeout_time_wait = 120
		net.netfilter.nf_conntrack_tcp_timeout_close_wait = 60
		net.netfilter.nf_conntrack_tcp_timeout_fin_wait =120
		EOF
	fi
}
function init_ssh()
{
	echo "init_ssh"
	\cp /etc/ssh/sshd_config /etc/ssh/sshd_config.`date +"%Y-%m-%d_%H-%M-%S"`
	sed -i -e 's%#Port 22%Port 51111%' -e 's%#PermitRootLogin yes%PermitRootLogin no%' -e 					's%#PermitEmptyPasswords no%PermitEmptyPasswords no%' /etc/ssh/sshd_config
	sed -i -e 's%#UseDNS yes%UseDNS no%'  /etc/ssh/sshd_config
	systemctl restart sshd
}
function update_linux()
{
	echo "update_linux"
	yum update -y
	yum install nmap tree dos2unix nc -y 
}
main()
{
	#mod_yum 
	close_selinux
	close_firewalld
	adduser
	charset
	time_sync
	com_line_set
	set_kernel
	init_ssh
	update_linux
}
main

74.

[ -f /etc/init.d/functions ] && ./etc/init.d/functions  || exit 1

75.

-eq 是关系运算符号,不能用于比较字符相等

76.

\换行操作符

77. case

read -p "...." ans
case "$ans" in
	1)  //字符串比较不加""
	;;
	7|9)
	;;
	[3-6])
	;;
	*)
	;;
esac

78 . 在一个文件里添加搜索删除用户

#!/bin/bash
FILEPATH=/blueicex/users
. /etc/init.d/functions
[ ! -f $FILEPATH ] && touch $FILEPATH
function usage()
{
	echo `basename $0` add del search
}

if [ $UID -ne 0 ] 
then
{ 
	echo "Operation must supper user!"
	exit 1
}
fi
if [ $# -ne 2 ]
then 
{
	usage
	exit 1
}
fi

case "$1" in 
	-a|add)
		shift
		if grep "^$1$" $FILEPATH >/dev/null 2>&1
		then
			action "$1 is alreay exist" /bin/false
			exit 1
		else
			chattr -i $FILEPATH 
			cp $FILEPATH $FILEPATH.`date +%F%T`
			echo "$1" >> $FILEPATH
			[ $? -eq 0 ] && action "Add $1 succees" /bin/true
			chattr +i $FILEPATH
			exit 0
		fi
		;;
-d|del|delete)
		shift
		if [ `grep "^$1$" $FILEPATH | wc -l` -lt 1 ]
		then
			action "$1 user not exist" /bin/false
			exit 1
		else
			echo $1
			chattr -i $FILEPATH
			cp $FILEPATH $FILEPATH.`date +%F%T`
			sed -i '/^${1}$/d' $FILEPATH
			[ $? -eq 0 ] && action "delete user success" /bin/true
			chattr +i $FILEPATH
			exit 0
			fi
		;;
-s|search)
	shift
	if [ `grep -w "$1" $FILEPATH | wc -l` -lt 1 ]
	then
		action "$1 is not exist " /bin/false
	else
		action "$1 is exist " /bin/true
	fi
	;;
*)
	usage
	exit 0
	;;
esac

79. grep 精确过滤有三种

grep -w 'blueicex' /etc/passwd
grep '^blueicex$' /etc/passwd
grep '/blueicex/b' /etc/passwd

80. while和until

while <condition>
do
	command
done
until <condition>
do
	command
done
while true/[ 1 ]
do
	usleep 20000 //微秒
	uptime            //Tell how long the system has been running
done 
> sh /.../.sh&            //后台运行命令 nohup/.../.sh &      //nohup - run a
> command immune to hangups, with output to a non-tty

81. screen

#新建一个叫yourname的session
screen -S yourname
#列出当前所有的session
screen -ls
screen -r yourname -> 回到yourname这个session
screen -d yourname -> 远程detach某个session
screen -d -r yourname -> 结束当前session并回到yourname这个session
screen -wipe命令清除该会话

82. 暂停停止脚本运行

暂停脚本运行
ctrl+z
关闭执行的脚本
kill %n

83.while

i=12
while ((i>0))
do
	echo "$i"
	((i--))
done
i=12
while [[   $i>0 ]]
do
	echo "$i"
	((i--))
done
i=12
while [  $i -gt 0  ]
do
	echo "$i"
	((i--))
done
i=12
utile [  $i -gt 0  ]
do
	echo "$i"
	((i--))
done

84. 猜数字

#!/bin/bash
total=0
export LANG="zh_CN.UTF-8"
NUM=$((RANDOM%6))
readnum()
{
	 read -p "please input number" number
	exper $number +1 &> /dev/null
	if[ $? -ne 0 ]
	then
		echo "please input number"
		readnum
	if
}
guess()
{
	((total++))
	if[ $number -eq $NUM ]
	then
	if[ $total -le 3 ]
	 then
	fi
 }

main()
{
	readnum;
	while true
	do
		gusee
	done
 } 
main

85. 手机充值10元,每次短信花费0.15元,当余额低于0.15元时,提示余额不足。

85.1

sum=100
i=0.15
while((sum>=i))     //不加¥
do
	((sum=sum-i))
	[ $sum -lt $i ] && break;
	echo "send message left $sum"
done
echo "money is not enough:$sum"

85.2

sum=100
i=0.15
while ((sum>=i))
do
((sum=sum-i))
[ $sum -lt $i ] && {
echo "send message left $sum,money is not enough"
break;
}
done

85.3

sum=15
msg_count=0
msg_fee=1.5
menu()
{
	cat <<END
	1.recharge 
	2.sendmessage
	3.quit
	END
recharge()
{
	read -p "please input charge number" number
	expr $number+1 &>/dev/null
	[ $? -ne 0 ] && echo "input charge number must is int" || { ((sum=sum+number)) echo  "current sum is $sum"}
} 
sendmessage()
{
	if [ $sum -lt $msg_fee ]
	then
	printf "remainder fee is not enough $sum\n"
	else
		while true
		do
			read -p "please input message content" messag
			((sum=sum-msg_fee))
			printf "send message success\n"
			if [ $sum -lt msg_fee ]
			then
				printf " remainder fee is not enought $sum\n"
				return 1
			fi                                             
		done
	fi
}
main(){
while [[ 1 ]]
do
	menu
	read -p "please input num select:" select
	case "$select" in
		1)
		recharge()
		;;
		2)
		sendmessage()
		;;
		3)
		exit 1
		;;
		*)
		printf "select is wrong. must is {1|2|3}\n"
		;;
		esac
done
}
main

86. 使用while监控网站,每隔10秒确定一次网站是否正常

#!/bin/bash
.  /etc/init.d/functions
if [ $# -ne 1] then
	action $"useage $0 need url" /bin/false
	exit
fi
while true
do
	if [ `curl -o /dev/null --connect-time 5 -s -w "%{http_code}" $1 | egrep -w "200|300|" | wc -l ` -ne 1 ]
	then
		action  "$1 is error"   /bin/false
		mail -s  "$1 is error" [email protected]
	else
		action  "$1 is ok "  /bin/true
	fi
	sleep 5
done

87. 同时检测多个网址工作状态

#!/bin/bash
. /etc/init.d/functions
check_cout=0
//数组定义方式
url_list=(
        http://192.168.3.62
        http://45.40.199.217
        http://www.baidu.com
)
function wait(){
echo "3 second late check begin"
for ((i=0;i<3;i++))
do
	echo -n ".";sleep 1;
done
echo
}

function check_url()
{
	wait
	for ((i=0; i<`echo ${#url_list[*]}`; i++)) //数组访问方式和取得数组大小,${url_list[*]}取得数组所有元素
	do 
		wget -o /dev/null --tries=1 -T 3 --spider ${url_list[$i]} >/dev/null 2>&1
		if [ $? -eq 0 ]
		then
			action "${url_list[$i]}" /bin/true
		else
			action "${url_list[$i]}" /bin/false
		fi
	done
	((check_cout++))
}
main(){
while true
do 
	check_url
	echo "------check count: ${check_count}----------"
	sleep 10
done
}
main

88. 分析apache日志,计算访问资源的大小

88.1

#!/bin/bash
. /etc/init.d/functions
sum=0
exec < $1
while read line
do
	size=`echo $line | awk '{print $10}'`
	expr $size+1
	if [ $? -ne 0 ]
	then
		continue
	fi
	((sum=$sum+$size))
done
echo "${1} :total:${sum}bytes=`echo $((sum/1024))`KB"

88.2

awk '{print $10}' access_log-2018608 | grep -v "-" | awk '{sum+=$1} END {print sum"KB"}'

89. 循环读取文件的方式

89.1

exec<file
sum=0
while read line
do
	cmd
done

89.2

cat FILE_PATH | while read line 
do
	cmd
done

89.3

while read line
do
	cmd
done<file

90. 开发类似cat的脚本

while read line
do
	echo $line
done<$1

91. for的表达形式

91.1

for i in valuse 
do
	command     
done

in valuse可以省略,相当于in $@
91.2

for in in values
do
	if [ condition1 ] && [ condition2 } && [ condition 3]
		command
	else
		command
	fi
done

91.3

for((begin;condition;end|))
do
	command
done

91.4

for num in 1 2 4  5 6
do
	echo $num
done

91.5

function main()
{
	for arg in $@
	do
		echo $arg
	done
}

91.6

#echo {3..1}
#4 3 2 1
echo [1-4]
[1-4]
#echo -e [1-4]
[1-4]

91.7

for in `seq 1 5 `/`ls`
do
	command
done

92. 批量更改文件名

92.1

#!/bin/bash
cd /test
for  filename in `ls | grep 'txt$'	`
do
	mv $filename   `echo $flilename | cut  -d "." -f1`.gif
done

92.2

rename "gif" "txt"  *.gif
rename "_finish" ""  *.jpg //去除文件名中共同的部分

92.3

#!/bin/bash
for file in `ls *.jpg`
do
	mv $file `echo $file | sed 's/_finish//g'`
done

92.4

ls |  awk  -F  '.'  ' { if($2=="txt")  {print "mv " $0 " "$1"blueicex.gif"} } ' | bash

93. 查看启动级别的进程

chkconfig --list | grep 3:on

94. 批量开启指定的服务

94.1

LANG=en
for closeprocess in 'chkconfig --list | grep 3:on | awk '{print $1}''
do
	chkconfig --level 3 $closeprocess off
done
for startprocess in sshd crond network 
do
	chkconfig --level 3 $startprocess on
done
chkconfig --list | grep 3:on

94.2

LANG=en
for process in `chkconfig --list | grep 3:on | awk ' { print $1 } ' | grep -vE 'sshd|httpd|crond' 
do
	chkconfig $process off
done

94.3

chkconfig --list | grep 3:on |grep -vE 'sshd|httpd|crond' | awk ' { print "chkconfig " $1 " off"} ' | bash  =========chkconfig --list | egrep -v 'sshd|httpd|crond' | awk ' { print "chkconfig " $1 " off"} ' | bash

95. 备份压缩数据库

#!/bin/bash
PATH="/usr/bin/":$PATH
DBBKPATH=/blueicex/dbback
DBUSER=root  #未加""
DBPASSWD=blueicex
SOCKET=/var/lib/mysql/mysql.sock
LOGINCMD="mysql -u$DBUSER -p$DBPASSWD -S $SOCKET"
DUMPCMD="mysqldump -u$DBUSER -p$DBPASSWD -S $SOCKET"

[ ! -d "$DBBKPATH" ] && mkdir $DBBKPATH
for dbname in `$LOGINCMD -e "show databases;" | sed "1,2d" | egrep -v "mysql|schema"`
do
	$DUMPCMD $dbname | gzip >$DBBKPATH/${dbname}_$(date +%F).sql.gz  
done

96. 创建多个数据库

#!/bin/bash
DBUSER=root
DBPASSWD=blueicex
SOCKET="/var/lib/mysql/mysql.sock"
LOGINCMD="mysql -u$DBUSER -p$DBPASSWD -S $SOCKET"
for dbname in "gege" "liuzexuan"
do
	$LOGINCMD -e "create database if not exists $dbname;"
done
$LOGINCMD -e "show databases;"

97. 创建测试数据库表

# cat dbtxt
blueicex male 38 basketball
gege female 34 eatmeat
liuzexuan female 7 watchTV

#!/bin/bash
DBUSER=root
DBPASSWD=blueicex
SOCKET="/var/lib/mysql/mysql.sock"
LOGINCMD="mysql -u$DBUSER -p$DBPASSWD -S $SOCKET"
awk ‘BEGIN{name='';age='';sex='';favor=''; 

————Blueicex 2020/2/5 9:50 [email protected]

你可能感兴趣的:(Shell)