领导安排要做一个数据库的自动备份计划。闲来没事先学习一下linux的shell,后期再结合rman备份脚本来给领导一个交代。
shell的语法如下:
#!/bin/sh --shell开始
#this is my first shell --#表示该shell的注释 也可写在代码中间
echo "Please enter your name:" --命令和控制结构
read NAME
echo "$NAME need help!!"
这样就写好了一个简单的shell脚本了。
执行脚本的方法: ./shellname or sh shellname
其中:
sh -x shellName --执行该脚本显示所有变量的值
sh -n shellName --不执行脚本只检查语法,返回所有的语法错误
注意:在执行前应检查该脚本的执行权限。
下面介绍下 shell的变量:
shell的变量(2种):
1:临时变量:在shell程序内部定义的变量,范围为定义它的程序。其他程序不可见。包括两种内型
用户自定义变量:如:上面脚本中 NAME
位置变量:
2:永久变量:系统的环境变量。不会随shell结束而消失。如:$HOME,$JAVA_HOME,$PATH ...
变量赋值:
定义是赋值: NUM=100
将一个命令的执行结果赋值:TIME=`date`
将一个变量赋值给另一个变量: VAR1=VAR2
将字符串的值赋值个变量:NAME="jack" or NAME='jack'
单引号 和 双引号的区别:
在使用双引号时如果变量值里有另一个变量b,b会显示它的值:
-bash-3.2# echo $TIME
2012-08-09
-bash-3.2# TEST="jack and time $TIME"
-bash-3.2# echo $TEST
jack and time 2012-08-09
单引号则不会。
对变量进行操作的命令:
在终端可使用echo查看变量值: echo $TIME
set 可查看系统中所有已经定义的变量
unset varName 删除变量
shell解释执行用户命令式。将命令行的第一个部分作为命令名,其他部分作为参数;
位置变量:出现在命令行上的位置确定的参数称为 位置参数。如:
ls -l file1 fiel2 file3 ..file9
$0 这个命令本身,包括参数: ls -l
$1 file1
$2 file2 以此类推,最大到 9个参数。
特殊变量:
$* 这个shell程序的所有参数
$# 这个shell程序的参数个数
$$ 这个shell程序的PID
$! 执行上一个后台命令的PID
$? 执行上一个命令的返回值 0表示上个命令执行成功 非0表示不成功
例子:
special_var.sh:
#!/bin/sh
#this is a example for special_var
echo '$* is--' $*
echo '$# is--' $#
echo '$$ is--' $$
echo '$! is--' $!
echo '$? is--' $?
echo '$0 is--' $0
echo '$1 is--' $1
输出结果为:
-bash-3.2# ./special_var.sh file1 file2 file3
$* is-- file1 file2 file3
$# is-- 3
$$ is-- 4096
$! is--
$? is-- 0
$0 is-- ./special_var.sh
$1 is-- file1
变量相关的就这么多了 下面来看看shell常用命令:
read varName --在执行shell时,交互式的读取数据并赋值给varName
expr --对整数型变量进行算术运算 + - \* (乘法) /(除法)
test 测试条件 --测试变量是否相等,是否为空,文件类型...
范围: 整数 字符串 文件
常见字符串测试:
-z string 字符串string 为空串(长度为0)时返回真
-n string 字符串string 为非空串时返回真
str1 = str2 字符串str1 和字符串str2 相等时返回真
str1 == str2 同 =
str1 != str2 字符串str1 和字符串str2 不相等时返回真
str1 < str2 按字典顺序排序,字符串str1 在字符串str2 之前
str1 > str2 按字典顺序排序,字符串str1 在字符串str2 之后
常见整数测试:
int1 -eq int2 如果int1 等于int2,则返回真
int1 -ne int2 如果int1 不等于int2,则返回真
int1 -lt int2 如果int1 小于int2,则返回真
int1 -le int2 如果int1 小于等于int2,则返回真
int1 -gt int2 如果int1 大于int2,则返回真
int1 -ge int2 如果int1 大于等于int2,则返回真
文件测试:
-b filename 当filename 存在并且是块文件时返回真(返回0)
-c filename 当filename 存在并且是字符文件时返回真
-d pathname 当pathname 存在并且是一个目录时返回真
-e pathname 当由pathname 指定的文件或目录存在时返回真
-f filename 当filename 存在并且是正规文件时返回真
-g pathname 当由pathname 指定的文件或目录存在并且设置了SGID 位时返回真
-h filename 当filename 存在并且是符号链接文件时返回真 (或 -L filename)
-k pathname 当由pathname 指定的文件或目录存在并且设置了"粘滞"位时返回真
-p filename 当filename 存在并且是命名管道时返回真
-r pathname 当由pathname 指定的文件或目录存在并且可读时返回真
-s filename 当filename 存在并且文件大小大于0 时返回真
-S filename 当filename 存在并且是socket 时返回真
-t fd 当fd 是与终端设备相关联的文件描述符时返回真
-u pathname 当由pathname 指定的文件或目录存在并且设置了SUID 位时返回真
-w pathname 当由pathname 指定的文件或目录存在并且可写时返回真
-x pathname 当由pathname 指定的文件或目录存在并且可执行时返回真
-O pathname 当由pathname 存在并且被当前进程的有效用户id 的用户拥有时返回真(字母O 大写)
-G pathname 当由pathname 存在并且属于当前进程的有效用户id 的用户的用户组时返回真
file1 -nt file2 file1 比file2 新时返回真
file1 -ot file2 file1 比file2 旧时返回真
f1 -ef f2 files f1 and f2 are hard links to the same file
逻辑测试
-a 逻辑与,操作符两边均为真,结果为真,否则为假。
-o 逻辑或,操作符两边一边为真,结果为真,否则为假。
! 逻辑否,条件为假,结果为真。
awk --用于指定数据的分割符。默认为 空格
awk --用于指定数据的分割符。默认为 空格
-bash-3.2# grep ^root /etc/passwd
root:x:0:0:root:/root:/bin/bash
-bash-3.2# awk -F: '$3==0 {print $1}' /etc/passwd --不是转义符,是单引号。$3和$1是awk命令自己定义的变量和位置变量无关
root
在来看看shell的控制结构:
if 语句
#!/bin/sh
#this is example for if..else
scores=40;
if [ $scores -gt 90 ]; then
echo "very good!";
elif [ $scores -gt 80 ]; then
echo "good!";
elif [ $scores -gt 60 ]; then
echo "pass!";
else
echo "no pass!";
fi;
the result is "no pass!"
shell命令,可以按照分号分割,也可以按照换行符分割。如果想一行写入多个命令,可以通过“';”分割。
其中的 [[ 和 [ (或者test)是有区别的
如:
[chengmo@centos5 ~]$ a=5;if [[ a -gt 4 ]] ;then echo 'ok';fi;
ok
exit --退出程序执行。0为正常退出:exit 0,非0为非正常退出;
for … in 语句
for 变量 in 空格隔开的字符串如: a b c
do
命令语句
done
说明:seq字符串 只要用空格字符分割,每次for…in 读取时候,就会按顺序将读到值,给前面的变量。
$(seq 10) 产生 1 2 3 。。。。10空格分隔字符串。
例如:
#!/bin/sh
#this is example for for1
for i in $(seq 10); do
echo $i;
done;
for((赋值;条件;运算语句))
for((赋值;条件;运算语句))
do
命令
done;
例子:
#!/bin/sh
#this is example for for2
for((i=1;i<=10;i++));do
echo $i;
done;
while语句结构
while 条件语句
do
命令
done;
例子:
#!/bin/sh
i=10;
while [ $i -gt 5 ];do
echo $i;
((i--));
done;
实例2:(循环读取文件内容:)
#!/bin/sh
while read line;do
echo $line;
done < /etc/hosts;
until 循环:
until 条件
do
action
done
意思是:直到满足条件,就退出。否则执行action.
例子:
#!/bin/sh
a=10;
until [[ $a -lt 0 ]];do
echo $a;
((a—));
done;
select循环:
select 变量 in 关键字
do
命令
done
例子
#!/bin/sh
#this is example for select
echo "what is you select"
select VAR1 in "a" "b" "c"
do
break --跳出整个循环
done
echo "you selected $VAR1 !"
case ... esac语句:
case 变量 in
字符串1) 命令列表1
;;
。。。
字符串2) 命令列表2
;;
esac
例子:
#!/bin/sh
#this is example for case
echo "***********"
echo "Please select your operation"
echo "press c to copy"
echo "press d to delete"
echo "************"
read op
case $op in
c)
echo "your selected is copy!"
;;
d)
echo "your selected is delete!"
;;
*) --其他选项用*
echo "incalide selection!!"
esac
一般情况select和case是一起使用的:例如:
#!/bin/sh
select ch in "begin" "end" "exit"
do
case $ch in
"begin")
echo "start something"
;;
"end")
echo "stop something"
;;
"exit")
echo "exit"
break;
;;
*)
echo "Ignorant"
;;
esac
done;
可以参考系统自带shell 如:/etc/rc.d/init.d/httpd
为了shell有良好的可读性 可用 函数
格式:
函数名(){
命令序列
}
调用函数是不带();如:函数名 参数1 参数2...
函数里不能有局部变量 只能是全局变量(在shell程序里的变量)
要让普通用户执行权限:
sh shellName
1:对脚本有r权限
2:对脚本的所在目录有rx权限
./ 脚本
1:对脚本有rx权限
2:对脚本所在目录有rx权限