1,shell变量可分为两类:局部变量和环境变量,局部变量只在创建它们的shell中可用。而环境变量则可以在创建它们的shell及其派生出来的任意子进程中使用。
局部变量:
1)${var}返回变量的值,案例:name="tom" 则${name}就会获取变量name的值(tom)
2) ${#var}返回变量字符串的长度,案例:name="tom" ${#name}返回3
3)${var:start_index}返回从start_index开始一直到字符串末尾,start_index=0-x,从倒数第x开始一直到字符串末尾。
案例:name="helloworld";${name:0}; 返回:helloworld ${name:0-3}; 返回:rld
4)${var:start_index:length}返回从start_index开始的length个字符, 案例:${name:0:5}返回:hello
5)${var#string}返回从左边删除string后的字符串,尽量短的去匹配,案例:path="http://127.0.0.1/index.jsp"; 则${path#*/}返回/127.0.0.1/index.jsp
6)${var##string}返回从左边删除string后的字符串,尽量长的去匹配,案例:path="http://127.0.0.1/index.jsp"; 则${path##*/}返回/index.jsp
7)${var%string}返回从右边删除string后的字符串,尽量短的去匹配,案例:path="http://127.0.0.1/index.jsp"; 则${path%/*}返回http://127.0.0.1
8)${var%%string}返回从右边删除string后的字符串,尽量长的去匹配,案例:path="http://127.0.0.1/index.jsp"; 则${path%%/*}返回http:
9)${var:-newstr}如果var为空或者未定义,则返回newstr,如果var不为空,返回原值。案例:address=""; ${address:-new address};
10)${var:=newstr}如果var为空或者未定义,则返回newstr,并把newstr赋值给var,如果var不为空,返回原值。
案例 address=""; echo ${address:=newaddress}; echo ${address} 输出结果:都是newaddress
11)${var:?newstr}如果var为空或者未定义,将newstr写入标准错误流,本语句失败,如果var不为空,返回原值。
案例:address=""; ${address:?new address}; echo ${address}
12)${var:+newstr}如果var不为空,返回newstr,如果var为空,返回空值。案例:address=""; ${address:+new address}; echo ${address}
13) ${var/substring/newstring}返回var中第一个substring被替换成newstring后的字符串,str3="088880"; ${str3/0/hello}; 输出:hello88880
14) ${var//substring/newstring}返回var中所有的substring被替换成newstring后的字符串,str3="088880"; ${str3//0/hello}; 输出:hello8888hello
15)$(command)返回command命令执行后返回的结果,相当于`command`,案例:$(rm b)
16,$((算术表达式)) 返回括号内算术运算的结果,案例:$((20+5*2)) 返回30
案例:
i#!bin/bash
#define param
name="helloworld";
#get param value
echo ${name};
#get param length
echo ${#name};
#get index from 0 to length param
echo ${name:0};
#get index from -3 to length param
echo ${name:0-3};
#get index from 0 length:5 param
echo ${name:0:5};
paths="http://127.0.0.1:8080/index.jsp";
echo ${paths#*/};
echo ${paths##*/};
echo ${paths%/*};
echo ${paths%%/*};
address="";
echo ${address:-newaddress};
add="myaddress1";
echo ${add:-newmyaddress1};
str1="";
echo ${str1:+newmyaddress1};
str2="";
echo ${str2:=newstr2};
echo ${str2};
str3="088880";
echo ${str3/0/hello};
echo ${str3//0/hello};
17,日期类型:
#!/bin/bash
Date=`date +%Y%m%d%H%M%S`; 等价于Date=$(date +%Y%m%d%H%M%S);
echo $Date;
输出结果:20180103212426
Date1=`date '+%Y-%m-%d %H:%M:%S'`;
echo $Date1;
输出结果:2018-01-03 21:24:26
Date2=`date +%Y-%m-%d`
输出结果:2018-01-03
2,shell特殊变量:
shell特殊变量:Shell $0, $#, $*, $@, $?, $$和命令行参数
$$ 表示当前Shell进程的ID,即pid
$0表示当前脚本的文件名
案例:#!/bin/bash
echo shell process pid: $$;
echo shell filename: $0;
$n表示传递给脚本或函数的参数。n 是一个数字,表示第几个参数。例如,第一个参数是$1,第二个参数是$2
案例:#!/bin/bash
(( count = $# ))
(( a = 1 ))
while (( a<= count )); do
echo $1;
echo $2;
(( a++ ))
done
案例:test.sh 1.txt 2.txt 3.txt则 $1表示1.txt $2表示2.txt $3表示3.txt
$#表示传递给脚本或函数的参数个数。
案例:#!/bin/bash
(( count = $# ))
(( a = 1 ))
while (( a <= count )); do
echo $1;
shift; #shift命令的作用是:每次将参数的位置向前移动一位
(( a = a + 1 ))
done
案例:test.sh 1.txt 2.txt 3.txt则 $#为3
$*传递给脚本或函数的所有参数。
案例:#!/bin/bash
for a in $* ;do echo $a; done
执行:sh ./test.sh 1.txt 2.txt 输出结果:1.txt 2.txt
$@表示传递给脚本或函数的所有参数。被双引号" "包含时,与 $* 稍有不同,下面将会讲到。
案例: for a in $@ ; do echo $a; done # $@可以不加引号
$?表示上个命令的退出状态,或函数的返回值。
#!/bin/bash
ls -al;
echo command1 status: $?; // command1 status:0 命令执行成功,返回$? 为:0
rm b;
echo command2 status: $?; // command1 status:1 命令执行失败,返回$? 为:1
$!:后台运行的最后一个进程的pid
$-:显示shell使用的当前选项
$_:之前命令的最后一个参数
3,环境变量
环境变量的定义方法如下:
var=value
export var
shell在初始化的时候会在执行profile等初始化脚本,脚本中定义了一些环境变量,这些变量会在创建子进程时传递给子进程。
用env命令可以查看当前的环境变量。常用的系统环境变量如下:
_(下划线) 上一条命令的最后一个参数
BASH 展开为调用bash实例时使用的全路径名
CDPATH cd命令的搜索路径。它是以冒号分隔的目录列表,shell通过它来搜索cd命令指定的目标目录。例如.:~:/usr
EDITOR 内置编辑器emacs、gmacs或vi的路径名
ENV 每一个新的bash shell(包括脚本)启动时执行的环境文件。通常赋予这个变量的文件名是.bashrc。
EUID 展开为在shell启动时被初始化的当前用户的有效ID
GROUPS 当前用户所属的组
HISTFILE 指定保存命令行历史的文件。默认值是~/.bash_history。如果被复位,交互式shell退出时将不保存命令行历史
HISTSIZE 记录在命令行历史文件中的命令数。默认是500
HOME 主目录。未指定目录时,cd命令将转向该目录
IFS 内部字段分隔符,一般是空格符、制表符和换行符,用于由命令替换,循环结构中的表和读取的输入产生的词的字段划分
LANG 用来为没有以LC_开头的变量明确选取的种类确定locale类
OLDPWD 前一个工作目录
PATH 命令搜索路径。一个由冒号分隔的目录列表,shell用它来搜索命令,一个普通值为 /usr/gnu/bin:/usr/local/bin:/usr/ucb:/usr/bin
PPID 父进程的进程ID
PS1 主提示符串,默认值是$
PS2 次提示符串,默认值是>
PS3 与select命令一起使用的选择提示符串,默认值是#?
PS4 当开启追踪时使用的调试提示符串,默认值是+。追踪可以用set –x开启
PWD 当前工作目录。由cd设置
RANDOM 每次引用该变量,就产生一个随机整数。随机数序列可以通过给RANDOM赋值来初始化。如果RANDOM被复位,即使随后再设置,它 也将失去特定的属性
REPLY 当没有给read提供参数时设置
SHELL 当调用shell时,它扫描环境变量以寻找该名字。shell给PATH、PS1、PS2、MAILCHECK和IFS设置默认值。HOME和MAIL由login(1)设置
SHELLOPTS 包含一列开启的shell选项,比如braceexpand、hashall、monitor等
UID 展开为当前用户的用户ID,在shell启动时初始化
4 数值变量
shell中默认把变量值当作字符串,例如:
age=22
age=${age}+1
echo ${age}
输出结果为22+1,而不是23,因为shell将其解释为字符串,而不是数学运算。
可以用let命令使其进行数学运算,例如:
age=22
let age=${age}+1
echo ${age}
也可以用declare把变量定义为整型。例如:
declare -i age=22 ; declare -l age=22
age=${age}+1;
echo ${age};
这里就用 -i 选项把age定义为整型的了。此后每次运算,都把age的右值识别为算术表达式或数字。
5数组
在shell中可以使用数组,例如:
array[0]=0
array[1]=1
array[2]=2
则array就是一个数组,也可以这样给数组初始化:
array=(0 1 2) // 元素之间以空格分隔
可以通过 ${array[$i]}来访问array中某个元素,${array[*]} 的返回值即数组的所有元素组成的串,${#array[*]} 的返回值即数组的元素个数,${array[*]:0:2} 返回第一个和第二个元素组成的串。0表示开始的位置,2表示要返回的元素个数,开始位置可以为0-2(0减去2)之类的,表示从倒数第二个元素开始。
案例:
#!/bin/bash
a=(1 2 3 4 5);
for (( i=0;i < ${#a[*]};i++ ));
do
echo ${a[$i]}
done
6,if条件语句 help if if的文档帮助命令
格式: if COMMANDS; then COMMANDS; [ elif COMMANDS; then COMMANDS; ]... [ else COMMANDS; ] fi
案例: num=2; if [[ $num -lt 3 ]]; then echo trues; fi; //if语句中[[ ]]中跟逻辑表达式
//$((算术表达式)) 返回括号内算术运算的结果
if [[ $((1+2)) -lt 5 ]]; then echo small; fi
//$(command)返回command命令执行后返回的结果
if $(rm -r b); then echo delete success; fi
if [[ 4 -lt 3 ]]; then echo small;elif [[ 3 -lt 4 ]]; then echo big; else echo queqls; fi
7,for循环语句 help for for的文档帮助命令
1)for-each:
语法: for NAME [in WORDS ... ] ; do COMMANDS; done
案例:for i in 1 2 3; do echo $i; done
for a in "$@" ; do echo $a; done
2)普通for循环:
语法: for (( exp1; exp2; exp3 )); do COMMANDS; done
案例:for (( i=1;i<=10;i++ )); do echo $i; done
8,while循环语句
语法:(( EXP1 ))
while (( EXP2 )); do
COMMANDS
(( EXP3 ))
done
案例:#while
(( i=1 ))
while(( i < 10 )); do
echo $i;
(( i=i+1 ))
done
9,shell函数
函数可以将shell脚本程序划分成一个个功能相对独立的模块,使代码的模块化更好,结构更加清晰,并可以有效的减少程序的代码量,减少重复代码的编写。在Shell 中,函数就是一组命令集或语句形成一个可用块,函数增强了shell的可编程能力
语法:
#func_name 为函数名
function func_name(){
#函数内容
}
#函数调用
func_name param
函数体中,可以通过$1,$2--$9接受函数调用中的变量
函数可以通过return返回函数执行的结果,或者echo一个字符串返回
return:主要用来返回退出状态,即$?
0 <= 返回值(整数) <= 255;
0 为无错误;非0 为有错误;
注:如果返回其他数据,可以使用echo或者全局变量
return_var=`func $var1 $var2`
===========================
函数返回一个被称为退出状态的值. 退出状态可以由return 来指定statement, 否则函数的退出状态是函数最后一个执行命令的退出状态 (0 表示成功, 非0 表示出错代码). 可以在脚本中由$? 引用
退出值为 0 表示成功
退出值非 0 表示失败
当一个命令因为严重的信号 N 退出时,bash 将使用 128+N 作为它的退出状态
案例1: #!/bin/bash
#函数的声明
function Looprint(){
count=0;
total=$1;
while (( $count <= $total )); do
echo $count;
let ++count; #let使得count进行数值+1 ,没有let,shell就看成是字符串拼接
sleep 1;
done
return 0;
}
这种方式也行:
function Looprint(){
(( count=0 ))
(( total=$1 ))
while (( count <= total )); do
echo $count;
(( count++ ))
sleep 1;
done
return 0;
}
#函数的调用
read -p "please input the num of you want:" n;
Looprint $n;
案例2:#!/bin/bash
#funtion define
function funcfactorial(){
local factorial=1;
for(( i = 1;i <= $1;i++ ));do
factorial = factorial * $(( $factorial * $i));
done
echo $1 factorial is $factorial;
}
#functon application
funcfactorial $1; #函数名 跟上参数 (注意:函数名和变量名不能重复)
总结:local一般用于局部变量声明,多在在函数内部使用。
(1)shell脚本中定义的变量是global的,其作用域从被定义的地方开始,到shell结束或被显示删除的地方为止。
(2)shell函数定义的变量默认是global的,其作用域从“函数被调用时执行变量定义的地方”开始,到shell结束或被显示删除处为止。函数定义的 变量可以被显示定义成local的,其作用域局限于函数内。但请注意,函数的参数是local的。
(3)如果同名,Shell函数定义的local变量会屏蔽脚本定义的global变量。
案例3:有返回值的函数的调用
#!/bin/bash
#函数声明
function func3(){
echo $(( $1 * $2 ));
}
# 函数调用
result=$( func3 $1 $2 ); #$() equals ``
echo the result is $result;
10,shell的内置命令
1)冒号(:)是一个空命令,偶尔用于简化条件逻辑,相当于true的一个别名。
例如 while : 相当于while true
2)续行符\[enter] 必须是行的最后一个字符 用于统一命令跨多行
3) eval命令 允许对参数进行求值
4) exec命令 将当前shell替换为一个不同的程序 exec wall “Thanks for all the fish”
5) exit n命令 使脚本程序以退出码n结束运行
6)export命令 设置或显示环境变量
7) expr命令
综合案例:
1,重启tomcat shell 脚本,直接执行 sh ./start.sh 就可以重启tomcat
#!/bin/bash
shutDownComma=/usr/tomcat/apache-tomcat-7.0.29/bin;
startComma=/usr/tomcat/apache-tomcat-7.0.29/bin;
logComma=/usr/tomcat/apache-tomcat-7.0.29/logs;
cd $shutDownComma;
echo $shutDownComma;
echo shutdown begintime: `date +'%Y-%m-%d %H:%M:%S'`;
sh ./shutdown.sh;
echo shutdown endtime: `date +'%Y-%m-%d %H:%M:%S'`;
if (( $? == 0 ));
then
cd $startComma;
echo start begintime: `date +'%Y-%m-%d %H:%M:%S'`;
sh ./startup.sh;
echo start endtime: `date +'%Y-%m-%d %H:%M:%S'`;
else echo shudown server fail; exit;
fi
if (( $? == 0 ));
then
echo server start success!
cd $logComma;
echo log print begintime: `date +'%Y-%m-%d %H:%M:%S'`;
tail -100f catalina.out;
else echo start server fail;exit;
fi
if(( $? == 0 ));
then
echo server log show success!
else echo server log show fail;exit;
fi
关闭防火墙命令: service iptables stop
同步每台主机的时间:ntpdate ntp.sjtu.edu.cn
案例2:xsync 灵活的把一个节点中文件或者是目录复制到另个一个节点中的相同位置
rsync -rvl 命令 远程节点之间进行文件或者文件夹的复制,使用scp命令也可以实现,但是scp复制符号链接时,复制过去是一个文件,而使用rsync -l就可以把符号链接复制过去
使用root用户常见xsync文件
touch xsync
给文件授予可执行权限
chmod a+x xsync
编辑脚本:
==========================编辑====================================
#!/bin/bash
#获取参数个数
pcount=$#;
if (( pcount<1 )); then
echo no args;
exit;
fi
#获取第一个参数
p1=$1;
#获取文件名称(不管是绝对路径还是相对路径)
fname=`basename $p1`;
#echo $fname;
#获取文件或者文件夹的上级目录的绝对路径
pdir=`cd -P $(dirname $p1);pwd`;
#echo $pdir;
cuser=`whoami`;
for (( hostname=101;hostname<104;hostname++ )); do
echo -------------s$hostname-------------
#将本地节点文件或文件夹复制到远程节点上相同的位置
rsync -rvl $pdir/$fname $cuser@s$hostname:$pdir;
done
案例3:xcall 当前节点指定的命令,同时也在远程节点中执行
#!/bin/bash
pcount=$#;
if (( pcount<1 )); then
echo no args;
exit;
fi
echo -------------localhost -----------------
#执行当前节点输入的命令
$@
for (( hostname=101;hostname<104;hostname++ )); do
echo -------------s$hostname-------------
# echo ssh s$hostname $@;
#在执行远程节点执行相同的命令
ssh s$hostname $@;
done
局部变量:
1)${var}返回变量的值,案例:name="tom" 则${name}就会获取变量name的值(tom)
2) ${#var}返回变量字符串的长度,案例:name="tom" ${#name}返回3
3)${var:start_index}返回从start_index开始一直到字符串末尾,start_index=0-x,从倒数第x开始一直到字符串末尾。
案例:name="helloworld";${name:0}; 返回:helloworld ${name:0-3}; 返回:rld
4)${var:start_index:length}返回从start_index开始的length个字符, 案例:${name:0:5}返回:hello
5)${var#string}返回从左边删除string后的字符串,尽量短的去匹配,案例:path="http://127.0.0.1/index.jsp"; 则${path#*/}返回/127.0.0.1/index.jsp
6)${var##string}返回从左边删除string后的字符串,尽量长的去匹配,案例:path="http://127.0.0.1/index.jsp"; 则${path##*/}返回/index.jsp
7)${var%string}返回从右边删除string后的字符串,尽量短的去匹配,案例:path="http://127.0.0.1/index.jsp"; 则${path%/*}返回http://127.0.0.1
8)${var%%string}返回从右边删除string后的字符串,尽量长的去匹配,案例:path="http://127.0.0.1/index.jsp"; 则${path%%/*}返回http:
9)${var:-newstr}如果var为空或者未定义,则返回newstr,如果var不为空,返回原值。案例:address=""; ${address:-new address};
10)${var:=newstr}如果var为空或者未定义,则返回newstr,并把newstr赋值给var,如果var不为空,返回原值。
案例 address=""; echo ${address:=newaddress}; echo ${address} 输出结果:都是newaddress
11)${var:?newstr}如果var为空或者未定义,将newstr写入标准错误流,本语句失败,如果var不为空,返回原值。
案例:address=""; ${address:?new address}; echo ${address}
12)${var:+newstr}如果var不为空,返回newstr,如果var为空,返回空值。案例:address=""; ${address:+new address}; echo ${address}
13) ${var/substring/newstring}返回var中第一个substring被替换成newstring后的字符串,str3="088880"; ${str3/0/hello}; 输出:hello88880
14) ${var//substring/newstring}返回var中所有的substring被替换成newstring后的字符串,str3="088880"; ${str3//0/hello}; 输出:hello8888hello
15)$(command)返回command命令执行后返回的结果,相当于`command`,案例:$(rm b)
16,$((算术表达式)) 返回括号内算术运算的结果,案例:$((20+5*2)) 返回30
案例:
i#!bin/bash
#define param
name="helloworld";
#get param value
echo ${name};
#get param length
echo ${#name};
#get index from 0 to length param
echo ${name:0};
#get index from -3 to length param
echo ${name:0-3};
#get index from 0 length:5 param
echo ${name:0:5};
paths="http://127.0.0.1:8080/index.jsp";
echo ${paths#*/};
echo ${paths##*/};
echo ${paths%/*};
echo ${paths%%/*};
address="";
echo ${address:-newaddress};
add="myaddress1";
echo ${add:-newmyaddress1};
str1="";
echo ${str1:+newmyaddress1};
str2="";
echo ${str2:=newstr2};
echo ${str2};
str3="088880";
echo ${str3/0/hello};
echo ${str3//0/hello};
17,日期类型:
#!/bin/bash
Date=`date +%Y%m%d%H%M%S`; 等价于Date=$(date +%Y%m%d%H%M%S);
echo $Date;
输出结果:20180103212426
Date1=`date '+%Y-%m-%d %H:%M:%S'`;
echo $Date1;
输出结果:2018-01-03 21:24:26
Date2=`date +%Y-%m-%d`
输出结果:2018-01-03
2,shell特殊变量:
shell特殊变量:Shell $0, $#, $*, $@, $?, $$和命令行参数
$$ 表示当前Shell进程的ID,即pid
$0表示当前脚本的文件名
案例:#!/bin/bash
echo shell process pid: $$;
echo shell filename: $0;
$n表示传递给脚本或函数的参数。n 是一个数字,表示第几个参数。例如,第一个参数是$1,第二个参数是$2
案例:#!/bin/bash
(( count = $# ))
(( a = 1 ))
while (( a<= count )); do
echo $1;
echo $2;
(( a++ ))
done
案例:test.sh 1.txt 2.txt 3.txt则 $1表示1.txt $2表示2.txt $3表示3.txt
$#表示传递给脚本或函数的参数个数。
案例:#!/bin/bash
(( count = $# ))
(( a = 1 ))
while (( a <= count )); do
echo $1;
shift; #shift命令的作用是:每次将参数的位置向前移动一位
(( a = a + 1 ))
done
案例:test.sh 1.txt 2.txt 3.txt则 $#为3
$*传递给脚本或函数的所有参数。
案例:#!/bin/bash
for a in $* ;do echo $a; done
执行:sh ./test.sh 1.txt 2.txt 输出结果:1.txt 2.txt
$@表示传递给脚本或函数的所有参数。被双引号" "包含时,与 $* 稍有不同,下面将会讲到。
案例: for a in $@ ; do echo $a; done # $@可以不加引号
$?表示上个命令的退出状态,或函数的返回值。
#!/bin/bash
ls -al;
echo command1 status: $?; // command1 status:0 命令执行成功,返回$? 为:0
rm b;
echo command2 status: $?; // command1 status:1 命令执行失败,返回$? 为:1
$!:后台运行的最后一个进程的pid
$-:显示shell使用的当前选项
$_:之前命令的最后一个参数
3,环境变量
环境变量的定义方法如下:
var=value
export var
shell在初始化的时候会在执行profile等初始化脚本,脚本中定义了一些环境变量,这些变量会在创建子进程时传递给子进程。
用env命令可以查看当前的环境变量。常用的系统环境变量如下:
_(下划线) 上一条命令的最后一个参数
BASH 展开为调用bash实例时使用的全路径名
CDPATH cd命令的搜索路径。它是以冒号分隔的目录列表,shell通过它来搜索cd命令指定的目标目录。例如.:~:/usr
EDITOR 内置编辑器emacs、gmacs或vi的路径名
ENV 每一个新的bash shell(包括脚本)启动时执行的环境文件。通常赋予这个变量的文件名是.bashrc。
EUID 展开为在shell启动时被初始化的当前用户的有效ID
GROUPS 当前用户所属的组
HISTFILE 指定保存命令行历史的文件。默认值是~/.bash_history。如果被复位,交互式shell退出时将不保存命令行历史
HISTSIZE 记录在命令行历史文件中的命令数。默认是500
HOME 主目录。未指定目录时,cd命令将转向该目录
IFS 内部字段分隔符,一般是空格符、制表符和换行符,用于由命令替换,循环结构中的表和读取的输入产生的词的字段划分
LANG 用来为没有以LC_开头的变量明确选取的种类确定locale类
OLDPWD 前一个工作目录
PATH 命令搜索路径。一个由冒号分隔的目录列表,shell用它来搜索命令,一个普通值为 /usr/gnu/bin:/usr/local/bin:/usr/ucb:/usr/bin
PPID 父进程的进程ID
PS1 主提示符串,默认值是$
PS2 次提示符串,默认值是>
PS3 与select命令一起使用的选择提示符串,默认值是#?
PS4 当开启追踪时使用的调试提示符串,默认值是+。追踪可以用set –x开启
PWD 当前工作目录。由cd设置
RANDOM 每次引用该变量,就产生一个随机整数。随机数序列可以通过给RANDOM赋值来初始化。如果RANDOM被复位,即使随后再设置,它 也将失去特定的属性
REPLY 当没有给read提供参数时设置
SHELL 当调用shell时,它扫描环境变量以寻找该名字。shell给PATH、PS1、PS2、MAILCHECK和IFS设置默认值。HOME和MAIL由login(1)设置
SHELLOPTS 包含一列开启的shell选项,比如braceexpand、hashall、monitor等
UID 展开为当前用户的用户ID,在shell启动时初始化
4 数值变量
shell中默认把变量值当作字符串,例如:
age=22
age=${age}+1
echo ${age}
输出结果为22+1,而不是23,因为shell将其解释为字符串,而不是数学运算。
可以用let命令使其进行数学运算,例如:
age=22
let age=${age}+1
echo ${age}
也可以用declare把变量定义为整型。例如:
declare -i age=22 ; declare -l age=22
age=${age}+1;
echo ${age};
这里就用 -i 选项把age定义为整型的了。此后每次运算,都把age的右值识别为算术表达式或数字。
5数组
在shell中可以使用数组,例如:
array[0]=0
array[1]=1
array[2]=2
则array就是一个数组,也可以这样给数组初始化:
array=(0 1 2) // 元素之间以空格分隔
可以通过 ${array[$i]}来访问array中某个元素,${array[*]} 的返回值即数组的所有元素组成的串,${#array[*]} 的返回值即数组的元素个数,${array[*]:0:2} 返回第一个和第二个元素组成的串。0表示开始的位置,2表示要返回的元素个数,开始位置可以为0-2(0减去2)之类的,表示从倒数第二个元素开始。
案例:
#!/bin/bash
a=(1 2 3 4 5);
for (( i=0;i < ${#a[*]};i++ ));
do
echo ${a[$i]}
done
6,if条件语句 help if if的文档帮助命令
格式: if COMMANDS; then COMMANDS; [ elif COMMANDS; then COMMANDS; ]... [ else COMMANDS; ] fi
案例: num=2; if [[ $num -lt 3 ]]; then echo trues; fi; //if语句中[[ ]]中跟逻辑表达式
//$((算术表达式)) 返回括号内算术运算的结果
if [[ $((1+2)) -lt 5 ]]; then echo small; fi
//$(command)返回command命令执行后返回的结果
if $(rm -r b); then echo delete success; fi
if [[ 4 -lt 3 ]]; then echo small;elif [[ 3 -lt 4 ]]; then echo big; else echo queqls; fi
7,for循环语句 help for for的文档帮助命令
1)for-each:
语法: for NAME [in WORDS ... ] ; do COMMANDS; done
案例:for i in 1 2 3; do echo $i; done
for a in "$@" ; do echo $a; done
2)普通for循环:
语法: for (( exp1; exp2; exp3 )); do COMMANDS; done
案例:for (( i=1;i<=10;i++ )); do echo $i; done
8,while循环语句
语法:(( EXP1 ))
while (( EXP2 )); do
COMMANDS
(( EXP3 ))
done
案例:#while
(( i=1 ))
while(( i < 10 )); do
echo $i;
(( i=i+1 ))
done
9,shell函数
函数可以将shell脚本程序划分成一个个功能相对独立的模块,使代码的模块化更好,结构更加清晰,并可以有效的减少程序的代码量,减少重复代码的编写。在Shell 中,函数就是一组命令集或语句形成一个可用块,函数增强了shell的可编程能力
语法:
#func_name 为函数名
function func_name(){
#函数内容
}
#函数调用
func_name param
函数体中,可以通过$1,$2--$9接受函数调用中的变量
函数可以通过return返回函数执行的结果,或者echo一个字符串返回
return:主要用来返回退出状态,即$?
0 <= 返回值(整数) <= 255;
0 为无错误;非0 为有错误;
注:如果返回其他数据,可以使用echo或者全局变量
return_var=`func $var1 $var2`
===========================
函数返回一个被称为退出状态的值. 退出状态可以由return 来指定statement, 否则函数的退出状态是函数最后一个执行命令的退出状态 (0 表示成功, 非0 表示出错代码). 可以在脚本中由$? 引用
退出值为 0 表示成功
退出值非 0 表示失败
当一个命令因为严重的信号 N 退出时,bash 将使用 128+N 作为它的退出状态
案例1: #!/bin/bash
#函数的声明
function Looprint(){
count=0;
total=$1;
while (( $count <= $total )); do
echo $count;
let ++count; #let使得count进行数值+1 ,没有let,shell就看成是字符串拼接
sleep 1;
done
return 0;
}
这种方式也行:
function Looprint(){
(( count=0 ))
(( total=$1 ))
while (( count <= total )); do
echo $count;
(( count++ ))
sleep 1;
done
return 0;
}
#函数的调用
read -p "please input the num of you want:" n;
Looprint $n;
案例2:#!/bin/bash
#funtion define
function funcfactorial(){
local factorial=1;
for(( i = 1;i <= $1;i++ ));do
factorial = factorial * $(( $factorial * $i));
done
echo $1 factorial is $factorial;
}
#functon application
funcfactorial $1; #函数名 跟上参数 (注意:函数名和变量名不能重复)
总结:local一般用于局部变量声明,多在在函数内部使用。
(1)shell脚本中定义的变量是global的,其作用域从被定义的地方开始,到shell结束或被显示删除的地方为止。
(2)shell函数定义的变量默认是global的,其作用域从“函数被调用时执行变量定义的地方”开始,到shell结束或被显示删除处为止。函数定义的 变量可以被显示定义成local的,其作用域局限于函数内。但请注意,函数的参数是local的。
(3)如果同名,Shell函数定义的local变量会屏蔽脚本定义的global变量。
案例3:有返回值的函数的调用
#!/bin/bash
#函数声明
function func3(){
echo $(( $1 * $2 ));
}
# 函数调用
result=$( func3 $1 $2 ); #$() equals ``
echo the result is $result;
10,shell的内置命令
1)冒号(:)是一个空命令,偶尔用于简化条件逻辑,相当于true的一个别名。
例如 while : 相当于while true
2)续行符\[enter] 必须是行的最后一个字符 用于统一命令跨多行
3) eval命令 允许对参数进行求值
4) exec命令 将当前shell替换为一个不同的程序 exec wall “Thanks for all the fish”
5) exit n命令 使脚本程序以退出码n结束运行
6)export命令 设置或显示环境变量
7) expr命令
综合案例:
1,重启tomcat shell 脚本,直接执行 sh ./start.sh 就可以重启tomcat
#!/bin/bash
shutDownComma=/usr/tomcat/apache-tomcat-7.0.29/bin;
startComma=/usr/tomcat/apache-tomcat-7.0.29/bin;
logComma=/usr/tomcat/apache-tomcat-7.0.29/logs;
cd $shutDownComma;
echo $shutDownComma;
echo shutdown begintime: `date +'%Y-%m-%d %H:%M:%S'`;
sh ./shutdown.sh;
echo shutdown endtime: `date +'%Y-%m-%d %H:%M:%S'`;
if (( $? == 0 ));
then
cd $startComma;
echo start begintime: `date +'%Y-%m-%d %H:%M:%S'`;
sh ./startup.sh;
echo start endtime: `date +'%Y-%m-%d %H:%M:%S'`;
else echo shudown server fail; exit;
fi
if (( $? == 0 ));
then
echo server start success!
cd $logComma;
echo log print begintime: `date +'%Y-%m-%d %H:%M:%S'`;
tail -100f catalina.out;
else echo start server fail;exit;
fi
if(( $? == 0 ));
then
echo server log show success!
else echo server log show fail;exit;
fi
关闭防火墙命令: service iptables stop
同步每台主机的时间:ntpdate ntp.sjtu.edu.cn
案例2:xsync 灵活的把一个节点中文件或者是目录复制到另个一个节点中的相同位置
rsync -rvl 命令 远程节点之间进行文件或者文件夹的复制,使用scp命令也可以实现,但是scp复制符号链接时,复制过去是一个文件,而使用rsync -l就可以把符号链接复制过去
使用root用户常见xsync文件
touch xsync
给文件授予可执行权限
chmod a+x xsync
编辑脚本:
==========================编辑====================================
#!/bin/bash
#获取参数个数
pcount=$#;
if (( pcount<1 )); then
echo no args;
exit;
fi
#获取第一个参数
p1=$1;
#获取文件名称(不管是绝对路径还是相对路径)
fname=`basename $p1`;
#echo $fname;
#获取文件或者文件夹的上级目录的绝对路径
pdir=`cd -P $(dirname $p1);pwd`;
#echo $pdir;
cuser=`whoami`;
for (( hostname=101;hostname<104;hostname++ )); do
echo -------------s$hostname-------------
#将本地节点文件或文件夹复制到远程节点上相同的位置
rsync -rvl $pdir/$fname $cuser@s$hostname:$pdir;
done
案例3:xcall 当前节点指定的命令,同时也在远程节点中执行
#!/bin/bash
pcount=$#;
if (( pcount<1 )); then
echo no args;
exit;
fi
echo -------------localhost -----------------
#执行当前节点输入的命令
$@
for (( hostname=101;hostname<104;hostname++ )); do
echo -------------s$hostname-------------
# echo ssh s$hostname $@;
#在执行远程节点执行相同的命令
ssh s$hostname $@;
done