1.shell 概念:
是操作系统内核与用户交互的接口。
2.每类操作系统都会有相应的shell ,不论windows,linux ,还是unix 。
1)windows家族系列:
windows shell: 如windows 的dos 系统(使用dos 命令可以编写批处理)。
2)linux 家族系列:
linux shell : Linux默认的shell为Bourne Again shell ,简称bash 。
REDHAT ENTERPRISE 5/6/7
20REDHAT CENOS 社区版5/6/7
Fedora
SUSE 9/10/11
3)unix家族系列Unix 默认使用的shell,根据操作系统的不同而不同,其中:
FreeBSD缺省的是C shell
HP-UX缺省的是POSIX shell
IBM AIX缺省的是Korn Shell
HP UNIX
FREE BSD
IBM AIX
1.创建以.sh为扩展名的文件
创建方法: 用vi编辑器创建。如:
vi hello.sh
2.编辑脚本文件
编辑脚本文件需要注意的内容:
1)第一行以“#!” 开头,声明所使用的shell的全路径。
2)脚本中适量增加注释内容。
注释的语法以“# ” 开头,”#”之后的内容不被执行。如:
#!/bin/bash
echo "hello,world!" # 打印输出hello,world
3.增加脚本文件执行权限
脚本的执行,需要一定的权限,特别是对于不同的用户所有者。
我们通常这么执行一个脚本:
1)chmod +x 脚本名字。 # 所有用户均对该脚本有执行权限。
2)chmod 755 脚本名字。 # 用户所有者对该脚本具有完全的权限,其他 人对该脚本拥有执行权限。
4.运行脚本文件
运行脚本的方法:
1)进入脚本文件目录执行:
cd /home/liutaostdio/script
2)./脚本名 来运行,如:
[liutaostdio@WLJY01 myscript]$ ./hello.sh
hello,world!
3)以/bin/sh 脚本名来运行,如:
[liutaostdio@WLJY01 myscript]$ /bin/sh hello.sh
hello,world!
1.变量的定义
1)shell 中的变量名可以由字母、数字、下划线组成,但数字不能作为变量名的第一个字符;
2)通过赋值符等号”=” 来定义一个变量的值。
如:
myname='galley' # 字符串类型,不解析任何字符。
courses="abcdedf" #双引号内部会解析$和反斜杠特殊字符。
sum=100;price=1.2544
now_date=`date` # 反引号执行系统命令
shell 的变量类型只有字符串类型,所以当你不用引号引起来的时候,要保证变量的值不包含特殊的符号,如空格符、美元符、&符。
mystr='123 5'
2.变量的引用
1)变量的引用,使用美元符号$ 加变量名,来引用一个变量的值。
如:
#定义变量
programe_name="httpd"
#引用变量
echo $programe_name
echo ${programe_name}
2)变量名外面的花括号是可选的,加花括号是为了帮助解释器识别变量的边界,比如下面这种情况:
#/bin/sh
for skill in php java linux db2
do
echo "I am good at ${skill}Script" # 帮助shell解释器识别边界
done
3.变量值的特殊符号引用
1)关于单引号和双引号以及反引号的引用方法演示:
[root@localhost sh]# testvar=100
# 单引号的引用
[root@localhost sh]# echo 'The testvalue is $testvar'
The testvalue is $testvar
# 双引号的引用
[root@localhost sh]# echo "The testvalue is $testvar"
The testvalue is 100
# 反引号的引用
[liutaostdio@WLJY01 ~]$ now_date=`date`
[liutaostdio@WLJY01 ~]$ echo $now_date
Sat Jul 18 23:58:59 CST 2015
1.环境变量
1)环境变量的定义:
环境变量一般是指在操作系统中用来指定操作系统运行环境的一些参数,如PATH、PWD、USER、当前使用的SHELL名称等。
2)常见的环境变量
PATH:系统路径;
HOME:当前用户家目录;
HISTSIZE:保存历史命令记录的条数;
LOGNAME:当前用户登录名;
HOSTNAME:主机名称,若应用程序要用到主机名的话,一般是从这个环境变量中的取得的;
SHELL:当前用户用的是哪种shell;
LANG/LANGUGE:和语言相关的环境变量,使用多种语言的用户可以修改此环境变量;
MAIL:当前用户的邮件存放目录。
3)查看环境变量
env:显示所有环境变量。
echo $PATH : 显示某一个环境变量的值
2.局部变量
1)局部变量量包括:
在Shell脚本中由用户自定义的变量;
Shell脚本中定义的变量作用域是从被定义的地方开始,到shell结束为止,起作用域为本脚本,离开本脚本,变量无效。
2)动手操作:
编写一个脚本,定义一个变量并输出其结果;
退出脚本再输出这个变量看有没有结果。
在用户登陆的shell中定义的变量,重新登陆后该变量消失。
3)动手操作:
登录到shell中,给一个变量赋值,显示该变量的结果;
退出当前shell ,重新登录,再输出这个变量,看到无结果。
3.预定义变量
预定义变量和环境变量相类似,也是在Shell一开始时就定义了的变量。
所不同的是,用户只能根据Shell的定义来使用这些变量,而不能重定义它。
所有预定义变量都是由$符和另一个符号组成的,常用的Shell预定义变量有:
$# 位置参数的数量。(/bin/sh test.sh 1 3 5)
$* 所有位置参数的内容
$? 命令执行后返回的状态。 # 0表示成功,非0表示失败
$$ 当前进程的进程号
$! 后台运行的最后一个进程号。# 很少用,了解即可
$0 当前执行的进程名
如:
[liu@WLJY01 myscript]$ cat predefine_var.sh
#!/bin/sh
echo "这个程序的名字:$0";
echo "参数的数量:$#"
echo "所有的参数:$*"
echo "当前进程号:$$"
echo "命令执行的返回状态:$?"
echo "后台运行的最后一个进程号:$!"
[liu@WLJY01 myscript]$ sh predefine_var.sh 1 2 3 4
输出结果:
这个程序的名字:predefine_var.sh
参数的数量:4
所有的参数:1 2 3 4
当前进程号:10171
命令执行的返回状态:0
后台运行的最后一个进程号。
echo 命令发送数据到标准的输出设备,数据采用的是字符串的方式,echo 命令可以输出一个变量。
[liu@WLJY01 ~]$ myprograme="myprograme is : mysql monitor script"
[liu@WLJY01 ~]$ echo $myprograme
myprograme is : mysql monitor script
1) -e:识别输出内容里的转义序列
[liu@WLJY01 myscript]$ echo -e "hello\tworld"
hello world
2) -n:忽略结尾的换行
[liu@WLJY01 myscript]$ echo -e -n "hello\tworld"
hello world[liu@WLJY01 myscript]$
和echo 的功能类似,printf 也可以输出变量,printf 还可以按照格式输出变量。
需要注意的是:
1)printf的默认输出没有换行,换行需要自己加“\n”
[liu@WLJY01 myscript]$ mystr="hello,world"
[liu@WLJY01 myscript]$ printf $mystr
hello,world[liu@WLJY01 myscript]$
换行输出:
[liu@WLJY01 myscript]$ mystr="hello,world"
[liu@WLJY01 myscript]$ printf "%s\n" $mystr
hello,world
2)printf支持格式化输出
[liu@WLJY01 myscript]$ cat test_printf.sh
#!/bin/sh
name=zhangsan
age=43
address="beijing"
# %s代表字符串,%d代表十进制整数
printf "name:%s,age:%d,address:%s\n" $name $age $address
#输出结果
[liu@WLJY01 myscript]$ sh test_printf.sh
name:zhangsan,age:43,address:beijing
read 命令读取标准输入设备的下一行,标准输入中的新一行到换行符前的所有字符会被读取,并赋值给对应的变量。
可以结合echo 一起实现读取并输出的功能。
脚本内容:
#!/bin/sh
# 接受输入并输出IP地址
echo "please input your ipaddress"
read ipaddr
echo "my ip address is $ipaddr"
#运行结果
[liustdio@WLJY01 myscript]$ sh read-echo.sh
please input your ipaddress
192.168.1.1
my ip address is 192.168.1.1
“<<” 可以被认为是一种重定向符,重定向脚本文件中的一行作为到一个命令的输入。操作符<< 被放在输入重定向的命令之后,紧跟在<< 的各行作为命令的输入,输入的结尾通过文件结束符(ctrl+D)表示,也可以自己定义定界符,定界符后的单词作为输入各行结束的定界符。
注意结束时的定界符一定要顶格写。
例1:用“<<” 符作为每行的命令输入来操作数据库。
[liu@WLJY01 myscript]$ cat operate_mysqldb.sh
#!/bin/sh
# 演练用"<<" 按行输入来操作数据库
/usr/local/mysql5.6.17/bin/mysql <#自定义定界符!
status
select count(*) from test.student
! #顶格,说明输入结束
例2:自动连接ftp服务器来下载数据。
#!/bin/sh
# 演练用"<<" 按行输入来上传下载文件
ftpserver=192.168.1.100
rq=`date + %Y%m%d`
cd /home/liu/mydocs
ftp -i -n <$ftpserver
user oracle post
cd ems
bin
get $rq.dat
bye
!
1.let 命令让BASH shell 执行算数值的操作,使用let,可以比较两个值或执行加减乘除等这样的算数操作,这种操作经常用于shell 程序中的控制流程结构或执行需要的运算,注意let命令只能执行整数的相关运算,运算结果也只能保存整数。
2.使用方法如下:
let 变量名 = 变量1 运算符 变量2
3.常见的算数操作分类:
1)加法: +
2)减法: -
3)乘法: *
4)除法: /
5)取余数: %
6)注意,和c语言类似,let i=$i+1 也可以写成let i++ ,从而简化书写。
let 命令使用方法举例
1.执行常见的算数运算操作:
[liu@WLJY01 myscript]$ cat operate_let.sh
#!/bin/sh
# let 执行算数操作经常使用的方法演练
i=10
j=20
k=3
# 执行算数运算
let res1=$i+$j+$k
let res2=$j-$i-$k
let res3=$i*$j*$k
let res4=$i*$j/$k
# 输出运算结果
echo "i+j+k=$res1"
echo "j-i-k=$res2"
echo "i*j*k=$res3"
echo "i*j/k=$res4" # 注意观察此处的结果,结果为66.66666,但let只能保留整数结果66,将小数部分截取。
2.let 方法来控制流程结构:
[liu@WLJY01 myscript]$ cat operate_let2.sh
#!/bin/sh
# 使用let方法来控制流程结构
i=1
n=3
while [ 1 ]
do
if [ $i -le $n ]
then
echo "echo $i"
else
break
fi
let i=$i+1 # 用let进行+1操作,此处也可以写成let i++
done
1.expr命令介绍
expr在linux中是一个功能非常强大的命令,和let功能类似,它做算数运算时,只能进行整数类型的运算,不能保存小数结果,除了进行算数运算,expr还可以进行字符串的操作,因此,expr功能非常强大。
2.expr 使用方法如下:
expr expression1 操作符 expression2
*操作符前必须加’\’用于转义,
并且操作符和两个expression之间必须有空格(这一点与let不同)。
expr 不适合于小数的运算。
[liu@WLJY01 myscript]$ expr 1 + 1
2
[liu@WLJY01 myscript]$ expr 1.1 + 1
expr: non-numeric argument
3.常见的算数操作分类:
1)加法: +
2)减法: -
3)乘法: * (注意,expr 进行乘法运算时,* 要进行转义写成*,避免与字符串操作的*冲突)
4)除法: /
5)取余数: %
4.expr 命令使用方法举例:
1)执行常见的算数运算操作:expr 作为外部命令要用反引号引起来
#!/bin/sh
# expr 执行算数操作经常使用的方法演练
i=10
j=20
k=3
# 执行算数运算
echo "i:$i;j:$j;k:$k"
res1=`expr $i + $j + $k` # expr 作为外部命令要用反引号引起来。
res2=`expr $j - $i - $k`
res3=`expr $i \* $j \* $k`
res4=`expr $i \* $j / $k`
# 输出运算结果
echo "i+j+k=$res1"
echo "j-i-k=$res2"
echo "i*j*k=$res3"
echo "i*j/k=$res4" # 注意观察此处的结果,结果为66.66666,但expr只能保留整数结果,将小数部
2)expr方法来控制流程结构:
[liu@WLJY01 myscript]$ cat operate_expr2.sh
#!/bin/sh
# 使用expr方法来控制流程结构
i=1
n=5
# 用expr 来控制输出,连续输出 i 变量的值。
while [ 1 ]
do
if [ $i -le $n ]
then
echo " $i"
else
break
fi
i=`expr $i + 1` #注意此处的写法,与let 不同。
done
1.bc命令介绍
let和expr不能处理浮点运算,并且缺乏特定的一些重要的精确操作,但是bc可以进行浮点运算,是一个多功能的灵活的工具,提供精确的复杂计算功能,它是linux 一个重要的工具,bc经常使用在管道里。
2.bc使用方法如下:
variable=`echo "OPTIONS; OPERATIONS" | bc`
其中scale 作为bc一个最重要的选项,用来指定输出小数的位数。例如:
$ n=`echo "scale=3; 13 / 2" | bc`
$ echo $n
$ 6.500
常用的浮点运算操作演练
[liu@WLJY01 myscript]$ cat operate_bc.sh
#!/bin/sh
# expr 执行算数操作经常使用的方法演练
# bc 执行浮点运算方法演练
i=10
j=20
k=3
# 执行算数运算
echo "i:$i;j:$j;k:$k"
res1=`expr $i + $j + $k`
res2=`expr $j - $i - $k`
res3=`expr $i \* $j \* $k`
res4=`expr $i \* $j / $k`
# 执行浮点运算
res5=`echo "scale=5;$i*$j/$k"|bc` # 注意此处乘法不需要用转义
# 输出运算结果
echo "i+j+k=$res1"
echo "j-i-k=$res2"
echo "i*j*k=$res3"
echo "expr: i*j/k=$res4"
echo "bc:i*j/k=$res5"
1.expr命令字符串的操作
shell中字符串操作也是常见的运算之一,expr除了进行算数运算之外,还可以进行字符串相关的运算,以下简单介绍使用expr进行的常用字符串操作。
输出字符串的长度。
[liu@WLJY01 ~]$ str1="abcde12345"
[liu@WLJY01 ~]$ echo ${#str1}
10
[liu@WLJY01 ~]$ expr length $str1
10
2.取子串的操作
expr substr $string $position $length #注意位置编号从1开始
echo ${string:$pos:$length} # 注意位置编号从0开始
[liutaostdio@WLJY01 ~]$ string="abcde1234567890"
[liutaostdio@WLJY01 ~]$ expr substr $string 1 3
abc
[liutaostdio@WLJY01 ~]$ echo ${string:0:3}
abc
3.字符传连接的操作
expr 命令没有字符串连接的参数,但字符串连接操作也是非常常见的。
[liu@WLJY01 ~]$ str1=abc
[liu@WLJY01 ~]$ str2=123
[liu@WLJY01 ~]$ str3="${str1},$str2" # 这个地方,可以定义字符串连接的分割符
[liu@WLJY01 ~]$ echo $str3
4.字符串替换的操作
expr 命令没有字符串替换的操作,但字符串替换操作也是非常常见的。
[liutaostdio@WLJY01 ~]$ string="you and you and zhangsan"
[liutaostdio@WLJY01 ~]$ echo ${string/you/YOU} # 只替换一次
YOU and you and zhangsan
[liutaostdio@WLJY01 ~]$ echo ${string//you/YOU} # 全部替换
YOU and YOU and zhangsan
1.test整数比较的方法
说明 | 命令 |
---|---|
大于 | -gt |
小于 | -lt |
大于等于 | -ge |
小于等于 | -le |
等于 | -eq |
不等于 | -ne |
2.test 整数比较方法演练
[liu@WLJY01 myscript]$ cat test_int.sh
#!/bin/sh
#test 整数比较方法熟练演练
a=100
b=200
c=100
d=300
# 输出a,b,c,d的值
echo -e "a:$a\t b:$b \t c:$c \t d:$d"
# 大于比较
test $b -gt $a
if [ $? -eq 0 ]
then
echo "b>a"
else
echo "b
fi
# 大于等于比较
test $b -ge $a
if [ $? -eq 0 ]
then
echo "b>=a"
else
echo "b
fi
# 等于比较
test $c -eq 100
if [ $? -eq 0 ]
then
echo "c==100"
else
echo "c!=100"
fi
#不等于比较
test $d -ne 400
if [ $? -eq 0 ]
then
echo "d!=400"
else
echo "d=400"
fi
1.字符串比较的方法:
说明 | 命令 |
---|---|
测试空字符串 | -z |
测试字符串的长度为非零 | -n |
等于某一个字符串 | = |
不等于某一个字符串 | != |
2.test 字符串比较方法演练
[liu@WLJY01 myscript]$ cat test_string.sh
#!/bin/sh
#test 字符串比较方法熟练演练
str1="abc"
str2='abc'
str3="123"
str4=""
# 输出字符串的值
echo -e "str1:${str1}\t str2:${str2} \t str3:${str3} \t str4:${str4}"
# 长度是否为0
test -n $str1 # 长度不为0,则程序执行返回值为0
if [ $? -eq 0 ]
then
echo "the length of str1 is not zero"
else
echo "the length of str1 is zero"
fi
# 字符串是否为空
test -z $str4 # 字符串长度为0,则程序返回0
if [ $? -eq 0 ]
then
echo "the length of str4 is zero"
else
echo "the length of str4 is not zero"
fi
# 字符串等于比较
test $str1 = $str2 # 字符串相等,则程序返回值为0
if [ $? -eq 0 ]
then
echo "str1 == str2"
else
echo "str1 != str2"
fi
#字符串不等于比较
test $str1 != $str3 # 字符串不相等,则程序返回值为0
if [ $? -eq 0 ]
then
echo "str1 != str3"
else
echo "str1 ==str3"
fi
1.test逻辑比较的方法
1) 逻辑与 -a
2) 逻辑或 -o
3) 逻辑非 !
2.test逻辑比较方法演练:
回忆:
1)pwd [选项]
查看”当前工作目录“的完整路径,一般情况下不带任何参数
2)$0
Shell本身的文件名
3)$1~$n
添加到Shell的各参数值。$1是第1参数、$2是第2参数…
4)$?
最后运行的命令的结束代码(返回值)
[liutaostdio@WLJY01 myscript]$ cat test_logic.sh
#!/bin/sh
#test 逻辑比较方法熟练演练
basepath=$(pwd)
filename=$0
echo "$basepath目录下的$filename 与或非运算演练..."
# 与运算
test $# -eq 1 -a $1 -eq 100 #输入的参数个数为1且第一个参数为100
if [ $? -eq 0 ]
then
echo "参数个数为1且参数值为100"
else
echo "不满足与运算的输入要求.."
fi
# 或运算
test $# -ge 1 -o $1 -eq 100 # 输入参数的个数为1或第一个参数为100
if [ $? -eq 0 ]
then
echo "参数个数大于等于1,或第一个参数为100"
else
echo "不满足或运算的输入要求"
fi
运算结果演示:
[liu@WLJY01 myscript]$ sh test_logic.sh 200 200
/home/liu/myscript目录下的test_logic.sh 与或非运算演练...
不满足与运算的输入要求..
参数个数大于等于1,或第一个参数为100
1.test文件比较的方法
说明 | 命令 |
---|---|
文件存在并且是一个常规文件 | -f |
文件不为空 | -s |
文件可读 | -r |
文件可写(修改) | -w |
文件可运行 | -x |
文件是一个目录名 | -d |
文件是一个符号链接 | -h |
文件名引用一个字符设备 | -c |
文件名引用一个块文件 | -b |
2.文件类型讲解
常规文件:
-rw-rw-r– 166 Jul 19 00:34 Here.sh
目录文件:
drwxrwxr-x. 4096 Jul 26 11:36 201507
字符设备或块设备文件:
crw–w—-. 1 10 May 24 17:30 /dev/tty10
块设备文件:
brw-rw—-. 1 May 24 17:30 /dev/sda1
套接口文件:
srwxrwxrwx. 0 May 24 17:31 /data/mysql5.6.17/mysql.sock
符号链接文件:
lrwxrwxrwx. 8 Jul 26 11:53 ttt.sh -> test1.sh
3.test文件比较方法演练
[liutaostdio@WLJY01 myscript]$ cat test_file.sh
#!/bin/sh
#test 文件比较方法熟练演练
basepath=$(pwd)
filename=$0
filename2="./nonexist.txt"
dir_name="./201507"
echo "$basepath目录下的$filename 文件比较方法演练..."
#文件存在且为常规文件与运算
test -f $filename
if [ $? -eq 0 ]
then
echo "$filename 存在且为常规文件.."
else
echo "$filename 不存在或不为常规文件.."
fi
test -f $filename2
if [ $? -eq 0 ]
then
echo "$filename2 存在且为常规文件.."
else
echo "$filename2 不存在或不为常规文件.."
fi
test -d $dir_name
if [ $? -eq 0 ]
then
echo "$dir_name is a directory... "
else
echo "$dir_name is not a directory.."
fi
test -r $filename
if [ $? -eq 0 ]
then
echo "$filename is readable .."
else
echo "$filename is not readable .."
fi
test -w $filename
if [ $? -eq 0 ]
then
echo "$filename is writeable..."
else
echo "$filename is not writeable .."
fi
test -x $filename
if [ $? -eq 0 ]
then
echo "$filename is excuteable..."
else
echo "$filename is not excuteable .."
fi
运算结果演示:
[liu@WLJY01 myscript]$ /bin/sh test_file.sh
/home/liu/myscript目录下的test_file.sh 文件比较方法演练...
test_file.sh 存在且为常规文件..
./nonexist.txt 不存在或不为常规文件..
./201507 is a directory...
test_file.sh is readable ..
test_file.sh is not writeable ..
test_file.sh is excuteable...