分类:
2010-05-09 22:53:30
<1>shell简介
命令替换
myfile的内容
parm
findfile
#ls `cat myfile` -al
shell脚本基本元素
a.#!/bin/sh
b.#注释
c.变量 #用来存储信息
d.流程控制结构
管道| #一个命令输出作为后一个命令的输入
重定向<>#与管道相关,可以改变程序运行的输入来源和输出地点
sort
特殊字符
双引号:用来使shell无法认出空格、制表符和其它特殊字符
单引号:用来使shell无法认出所有特殊字符
反引号:用来替换命令
反斜杠:用来使shell无认出其后的特殊字符
分 号:允许在一行放多个命令
& :命令后台执行
括 号:创建成组的命令
大括号:创建命令块
竖 杠:管道
<>& :表示重定向
*?{}! :表示模式匹配
$ :变量名的开头
# :注释
空格 :当做空白
换行符:当做空白
制表符:当做空白
<2>shell变量和运算符
2.1.1本地变量
用户现在shell生命期的脚本中使用
veriable-name=value
set显示本地所有的变量
readonly variable-name
例:#LOCALTEST="test"
#echo ${LOCALTEST}
test
#readonly LOCALTEST
#LOCALTEST="test4"
bash:LOCALTEST:readonly variable
#readonly
declare -r LOCALTEST="test"
declare -ir UID="0"
2.1.2环境变量
环境变量用于所有用户的进程(通常称子进程)。
登录进程称父进程。shell执行的用户进程均称为子进程
环境变量可用于所有子进程,这包括编辑器、脚本和应用。
$HOME/.bash_profile(/etc/profile)
export来设置
env来查看
2.1.3变量替换
用变量的值替换它的名字
echo
在变量名前加$,使用echo命令可以显示单个变量取值
例:#testvar-"this is a test"
#echo ${testvar}
this is a test
变量替换(续)
${variable name} 显示实际值到variable name
${variable name:+value} 如果设置了variable name,显示值value,否则为空
${variable name:?value} 如果未设置variable name,显示自定义错误value
${variable name:-value} 如果未设置variable name,显示其值value
${variable name:=value} 如果未设置variable name,设置其值value,并显示
2.1.4变量清除
unset variable #readonly例外
2.1.5位置变量
位置变量表示$0,$1……$9
$0脚本名字
2.1.6标准shell变量
bash默认建立了一些标准环境变量,可在/etc/profile中定义
如:EXINIT
HOME
MAIL
MAILCHECK
MAILPATH
PATH #程序路径
PS1 #提示符
PS2 #一行运行多个命令时用
SHELL
TERMINFO
TERM
TZ #时区
PWD
LFS
LOGNAME
2.1.7特殊变量
$# 传递的到脚本的参数个数
$* 以一个单字符串显示所有向脚本传递的参数,不同于位置变量,此选项可超过9个
$$ 脚本运行的当前进程ID号
$! 后台运行的最后一个进程的进程ID号
$@ 与$#相同,但是使用时加引号,并在引号中返回每个参数
$- 显示shell使用的当前选项,与set命令功能相同
$? 显示最后命令的退出状态。0表示没有错误,其他任何值表示有错误
2.1.8影响变量的命令
declare
- 设置或显示变量
- -f 只显示函数名
- -r 创建只读变量(declare和typeset)
- -x 创建转出变量
- -i 创建整数变量
- 使用+替代-,可以颠倒选项的含义,-r例外
export
- 用于创建传给子shell的变量
- -- 表明选项结束,所有后续参数都是实参
- -f 表明在“名-值”对中的名字是函数名
- -n 把全局变量转换成局部变量,换句话说,命令的变量不再传给shell
- -p 显示全局变量列表
readonly
- 显示或设置只读变量
- -- 表明选项结束
- -f 创建只读变量
set
- 设置或重设各种shell
shift [n]
- 用于移动位置变量,调整位置变量,使$3的值赋于$2,$2的值赋于$1
typeset
- 用于显示或设置变量
- 是declare的同义词
unset
- 用于取消变量的定义
- -- 表明选项结束
- -f 删除只读变量,但不能取消从shell环境中删除指定的变量和函数。如PPID,PS1,等
2.2引号
2.2.1引用的必要性
变量和替换操作,在脚本中执行变量替换时最容易犯的错误就是引用错误
2.2.2双引号
可以引用除字符$、`、\外的任意字符或字符串
2.2.3单引号
让shell忽略任何引用值
2.2.4反引号
用于设置系统命令的输出到变量。shell将反引号中的内容作为一个系统命令,并执行其内容
2.2.5反斜杠
屏蔽字符特殊含义
2.3运算符
运算符是对计算机发出的指令
运算对象
- 数字、字符
- 变量
- 表达式 #运算符和运算对象的组合体
2.3.1运算符的类型
按位运算符 ~,<<,>>,&,|,^
~op1 反运算符,把op1中所有的二进制为1变为0,0变为1
op1<
op1>>op2 右移运算符,把op1中的二进制位向右移动op2位,忽略最右边移的各位,最左
端的各位补上0值,每做一次按位左移就有实现op1除以2
op1&op2 比较运算符,op1和op2对应位,对于每个二进制位来说,如果二者该位都是1,
则结果位1;否则,结果位为0
op1^op2 异或运算符,比较op1和op2对应位,对于每个二进制位来说,如果二者该位互补,
则结果位1;否则,结果位为0
op1|op2 或运算符,比较op1和op2对应位,对于每个二进制位来说,如果二者该位有一个
是1或都是1,则结果位1;否则,结果位为0
$[] 表示形式告诉shell对方括号中的表达式求值。
如#!/bin/bash
#$[]表示形式举例
echo $[3+9]
逻辑运算符
&& 与运算符
|| 或运算符
>,==,<,!= 大于,等于,小于,不等于运算符
赋值运算符
=,+=,-=,*=,/=,%=,&=,^=,|=,<<=,>>=
let $count=$count+$change
let $count+=$change
2.3.2表达式替换
$[]和$(()) 还是$[]吧,$[]可以接受不同基数的数字,如[bash#n]n表示基数2到36的任何基数
2.3.3运算的优先级 13最高
13 -,+ 正,负
12 |,~ 逻辑非,按位取反
11 *,/,% 乘,除,取模
10 +,- 加,减
9 <<,>> 按位左移,按位右移
8 <=,>=,<,> 小于等于,大于等于,小于,大于
7 ==,|= 等于,不等于
6 & 按位或
5 ^ 按位异或
4 | 按位或
3 && 逻辑与
2 | 按位或
1 =,+=,-=,*=,/=,%=,&=,^=,|=,<<=,>>= 赋值、运算且赋值
<3>shell输入与输出
3.1.1 echo #显示文本行或变量,或者把字符串输入到文件
echo [option] string
-e 解析转义字符
-n 回车不换行
转义符(\c,\f,\t,\n)
3.2.1 read #可以从键盘或文件的某一行文本中读入信息,并将其赋值给一个变量
read varible1 varible2 #如果只指定了一个变量,那read将会把所有的输入赋于该变量,直到遇到
第一个文件结束符或回车;如果给出了多个变量,它们按顺序分别被赋
于不同的变量。shell将用空格作为变量之间的分隔符
例:#!/bin/bash
#readname
echo -n "first name:"
read firstname
echo -n "last name:"
read lastname subname
echo -e "your first name is :${firstname}\n"
echo -e "your last name is :${lastname}\n"
echo -e "your subname is :${subname}\n"
3.3.1 cat #显示文件内容、创建文件,还可用它来显示控制字符
-v 显示控制字符
3.4.2 管道举例
df -k |awk '{print $1}' |grep -v "filesystem" #查看空间,查找第一列,过滤“Filesystem”
3.5.1 tee #把输出的一个副本输送到标准输出,另一个副本拷贝到相应的文件中,常用于管道之后
-a 将输入附加在文件的后头
3.5.2 tee举例
df -k |awk '{print $1}' |grep -v "filesystem" |tee partation.txt
3.6.1 标准输入、输出和错误
在shell中执行命令时,每个进程都和三个打开的文件相联系,并使用文件描述符来引用这些文件。
由于文件描述符难记,shell同时也给出了相应的文件名
文件 文件描述符
输入文件-标准输入 0(缺省是键盘,也可以是文件或其它命令的输出)
输出文件-标准输出 1(缺省是屏幕,也可以是文件)
错误输出文件-标准错误 2(缺省是屏幕,也可以是文件)
系统中实际上有12个文件描述符,可以任意使用文件描述符3-9
3.7.1 文件重定向
command > filename 把标准输出重定向到一个新文件中
command >> filename 把标准输出重定向到一个文件中(追加)
command 1 > filename 把标准输出重定向到一个文件中
command > filename 2>&1 把标准输出和标准错误一起重定向到一个文件中
command 2 > filename 把标准错误重定向到一个新文件中
command 2 >> filename 把标准错误重定向到一个新文件中(追加)
command >> filename 2>&1 把标准输出和标准错误重定向到一个新文件中(追加)
command < filename >filename2 command命令以filename作为标准输入,以filename2作为标准输出
command < filename command命令以filename作为标准输入
command << delimiter 从标准输入中读取,直到遇到delimiter分界符
command < &m 把文件描述符m作为标准输入
command > &m 把标准输出重定向到文件描述符m中
command < &- 关闭标准输入
3.7.2 重定向举例:
#cat >>eof.txt<
>he he
>bye
>EOF
#########################
grep "opoent" missiles 2>/dev/null
3.8.1 结合使用标准输出和标准错误
#cat acc_new acc_old.txt>acc.out 2>acc.err
合并使用标准输出和标准错误
切记shell是从左至右分析相应的命令
#grep "standard" standard.txt>grep.out 2>&1
3.9.1 exec #用于替代当前shell:并没启动子shell,使用这一命令时任何现有互不环境都将被清除,
并重新启动一个shell
exec command #command通常是个shell脚本,只有对文件描述符进行操作时,不会覆盖当前shell
3.10.1 文件描述符,exec与文件描述符结合
3-9文件描述符
例:#!/bin/bash
#file_desc
exec 3<&0 0
read line2
exec 0<&3
echo $line1
echo $line2
<4>控制流结构
4.1.1 流控制是
4.1.2 if语句
语句格式:
if 条件1 #如果条件1为真
then #那么
命令1 #执行命令1
elif 条件2 #如果条件1不成立
then #那么
命令2 #执行命令2
else #如果条件1,2均不成立
命令3 #那么执行命令3
fi #完成
#########################if语句必须以单词fi终止
if条件
then命令
fi
########################
例:
#!/bin/bash
#ifelif
echo -n "Enter your name:"
read NAME
if [ -z$NAME] || [ "$NAME" = "" ]
then
echo "You did not enter a name"
elif [ "$NAME" = "root" ];
then
echo "Hello root!"
elif [ "$NAME" = "john" ];
then
echo "Hello john!"
else
echo "You are not root or john,but hi $NAME"
fi
############################
4.2.1 case语句
####################
case 值 in
模式1)
命令1
;;
模式2)
命令2
;;
esac
####################
例:
#!/bin/bash
#case select
echo -n "Enter a number from 1 to 3:"
read $ANS in
1)
echo "You select 1"
;;
2)
echo "You select 2"
;;
3)
echo "You select 3"
;;
y|Y)
echo "You select $ANS"
*)
echo "`basename $0`: This is not between 1 and 3" >&2
exit;
;;
esac
#############################################
4.3.1 for 循环
#############################################
for 变量名 in 列表
do
命令1
命令2
done
#############################################
4.4.1 until循环
#############################################
until 条件
do
命令1
命令2
done
注:条件可为任意测试条件,测试发生在循环末尾,因此循环到少执行一次
#############################################
#!/bin/sh
#until_mon
#监控分区
Part="~/"
#得到磁盘使用的百分比
LOOK_OUT=`df |grep $Part|awk '{print $5}'|sed 's/%//g'`
echo $LOOK_OUT
until [ "$LOOK_OUT" -gt "10" ]
do
echo "Filesystem ~/ is used 30%"
LOOK_OUT=`df |grep $Part|awk '{print $5}'|sed 's/%//g'`
sleep 5
done
################################################
4.5.1 while 循环
################################################
while 命令
do
命令1
命令2
……
done
注:在while和do之间虽然通常只使用一个命令,但可以放几个命令,命令通常用作测试条件。
################################################
#!/bin/bash
#whileread
echo "按住
while echo -n "您的尊姓大名?";read NAME
do
echo "没听过……${NAME}"
done
#############################################
4.6.1 break和continue控制
break [n]
退出循环
如果是在一个嵌入循环里,可以指定n来跳出的循环个数。
continue
跳过循环步
注:continue命令类似于break命令,只有一点重要差别,它不会跳出循环,只是跳过这个循环步。
#############################################
#!/bin/bash
#breakout
while :
do
echo -n "Enter any number [1……5] : "
read ANS
case $ANS in
1|2|3|4|5)
echo "You enter a number between 1 and 5."
break
;;
*)
echo "Wrong number,SB.Try again?(y/n):"
read IS_TRY
case $IS_TRY in
y|yes|Y|yes|YES)
continue
;;
*)
break
;;
esac
esac
done
#############################################
<5> 文本过滤
5.1 正则表达式
元字符用于匹配字符串
[] 只匹配[]内的内容,可以是一个单字符,也可是字符序列,可以用-表示范围,
如[1-3]=[123],[A-Za-z0-9]
. 只匹配任意单字符
pattern\{n\} 只用来匹配前面pattern出现次数,n为次数
pattern\{n,\} 只用来匹配前面pattern出现次数,次数最少为n
pattern\{n,m\} 只用来匹配前面pattern出现次数,次数为n与m之间
",',||,^,*,+ 特殊字符
#############################################
例:
IP ((25[0-5])|(2[0-4]\d)|(1\d\d)|([1-9]\d)|\d)(\.((25[0-5])|(2[0-4]\d)|(1\d\d)|([1-9]\d)|\d)){3}
域名 [a-zA-Z0-9][-a-zA-Z0-9]{0,62}(\.[a-zA-Z0-9][-a-zA-Z0-9]{0,62})+\.?
5.12 find 命令举例(续)
xargs在使用find命令的-exec选项处理匹配到的文件时, find命令将所有匹配到的文件一起传递
给exec执行。但有些系统对能够传递给exec的命令长度有限制,这样在find命令运行几分
钟之后,就会出现溢出错误。错误信息通常是“参数列太长”或“参数列溢出”。这就是xargs
命令的用处所在,特别是与find命令一起使用。
find命令把匹配到的文件传递给xargs命令,而xargs命令每次只获取一部分文件而不是全
部,不像-exec选项那样。这样它可以先处理最先获取的一部分文件,然后是下一批,并
如此继续下去。
在有些系统中,使用-exec选项会为处理每一个匹配到的文件而发起一个相应的进程,并
非将匹配到的文件全部作为参数一次执行;这样在有些情况下就会出现进程过多,系统
性能下降的问题,因而效率不高;
而使用xargs命令则只有一个进程。另外,在使用xargs命令时,究竟是一次获取所有的
参数,还是分批取得参数,以及每一次获取参数的数目都会根据该命令的选项及系统内
核中相应的可调参数来确定。
例:
find . -type f -print | xargs file
find . -perm -7 -print | xargs chmod o-w
5.13 grep命令类名
[[:upper:]] [A-Z]
[[:alnum:]] [0-9a-zA-Z]
[[:lower:]] [a-z]
[[:space:]] 空格或tab
[[:digit:]] [0-9]
[[:alpha:]] [a-zA-Z]
5.14 awk介绍(续)
awk脚本由各种操作和模式组成
模式和动作
模式部分决定动作语句何时触发及触发事件(BEGIN,END)
动作对数据进行处理,放在大括号{}内指明(print)
分割符、域和记录
awk执行时,其浏览域标记为$!-$n。这种方法称为域标识。$0为所有域。
注意执行时不要混淆符号$和shell提示符$,它们是不同的。
5.16 合并与分割
uniq 从一个文本文件中去除或禁止重复行
<6> shell函数
6.1 函数定义
shell允许将一组命令集或语句形成一个可用块,这些块称为函数
#############################################
定义函数的格式
############
函数名 ()
{
命令1
…
}
############
function 函数名 ()
{
…
}
#############################################
#!/bin/bash
#hellofun
function hello () //GNU bash, version 3.2.39,加了function反而不行
{
echo "Hello,today is `date`"
return 0
}
hello
#############################################
6.2 参数传递
向函数传递参数就像在脚本中使用位置变数$1,$2…$9
#############################################
#!/bin/bash
#hellofun
function hello () //GNU bash, version 3.2.39,加了function反而不行
{
echo "Hello,$1 ,today is `date`"
return 0
}
hello SB
#############################################
6.3 函数文件
#############################################
#!/bin/bash
#func
#Source function
. hellofun.sh //引用函数一定要点空格
hello
#############################################
6.4 检查载入函数和删除函数
察看载入函数 set
删除函数 unset
6.6 函数返回状态值
#############################################
#!/bin/bash
#func
#Source function
. hellofun.sh //引用函数一定要点空格
hello
echo $?
#############################################
<7> 脚本参数传递
7.1 shift
7.2 getopts
##########################
##########高级Shell编程#######
##########################
<1>深入讨论
1.1 深入讨论awk
条件操作符
~ 匹配正则
!~ 不匹配正则
#############################################
#!/bin/bash
#awkif
echo "210-219网段的访问量是:`awk '{if ($1~/^21[0-9]/) print $()}' |wc -l`"
#############################################
awk内置变量
ARGC 命令行参数个数
ARGV 命令行参数排列
ENVIRON 支持队列中系统环境变量的使用
FILENAME awk浏览的文件名
FNR 浏览文件的记录数
FS 设置输入域分隔符,等价于命令行-F选项
NF 浏览记录的域个数
NR 已读的记录数
OFS 输出域分隔符
ORS 输出记录分隔符
RS 控制记录分隔符
awk字符串函数
gsub(r,s) 在整个$0中用s替代r
gsub(r,s,t) 在整个t中用s替代r
index(s,t) 返回s中字符串t的第一个字符
length(s) 返回s长度
match(s,r) 测试s是否包含匹配r的字符串
split(s,a,fs) 在fs上将s分成序列a
spring(fmt,exp) 返回经fmt格式化后的exp
sub(r,s) 用$0中最左边最长的子字符串代替s
substr(s,p) 返回字符串s中从p开始的后缀部分
substr(s,p,n) 返回字符串s中从p开始长度为n的后缀部分
awk转义字符
\b 退格键
\t tab键
\f 走纸换页
\ddd 八进制值
\n 新行
\c 任意其他特殊字符,例如\\为反斜线符号
\r 回车键
printf修饰符
%c ASCII字符
%d 整数
%f 浮点数,例如(123.44)
%e 浮点数,科学记数法
%f 新行
%g awk决定使用哪种浮点数转换e或f
%o 八进制数
%s 字符串
%x 十六进制数
#############################################
#!/bin/bash
#This is show a menu
loopvar=2
#############
# main menu #
#############
main_menu()
{
echo
echo
dis_mainmenu="CREATE MINISITE IN CHENG.COM"
curdate=`date "+%Y-%m-%d %T"`
cat <
====================================
$dis_mainmenu
====================================
** 1)ADD MINISITE ACCOUNT
** 2)ADD DOMAIN IN CHENG.COM
** 3)ADD DATABASE IN MYSQL
** 4)ADD VIRTUAL HOST IN APACHE
** 5)BACKUP MINISITE
** 6)DELETE MINISITE
** 7)EXIT
====================================
mayday
}
while [ $loopvar -gt 0 ]
do
main_menu
echo -n " Please choose [1-7]:"
read main_choice
case $main_choice in
7)
exit
;;
*)
clear
continue
;;
esac
done
#############################################
<2> shell工具
2.1 日志文件
#############################################
#!/bin/bash
#datelog.sh
#当前的日期
current_date=`date "+%Y%m%d"`
#今天的日志文件名
todaylog="testlog/${current_date}.log"
#如果日志目录不存在,创建一个
if [ ! -d testlog ]
then
mkdir testlog
fi
#如果日志文件不存在,创建一个
if [ ! -f $todaylog ]
then
touch $todaylog
fi
#输出日志到日志文件
log_time_format=`date "+%Y-%m-%d %T"`
echo "${log_time_format} 命令开始" >>$todaylog
#
# command blocks
sleep 4
#
#输出日志到日志文件
log_time_format=`date "+%Y-%m-%d %T"`
echo "${log_time_format} 命令结束" >>$todaylog
#############################################
2.2 信号
kill -l 列出所有信号
0退出shell信号,通常是CTRL-D
1挂起父进程被杀死
2来自键盘的中断信号,通常是CTRL-C
3从键盘退出
9无条件终止
11段(内存)冲突
15软件终止(缺省杀进程)
kill发送信号给进程
2.3 trap捕捉信号
信号可以被应用程序或脚本捕获,并依据该信号(1.2.3.15)采取相应的行动。
一些信号不能被捕获。如果一个命令收到信号9,就无法再捕捉其他信号。
捕捉到一个信号后,可以
1)不行动,由系统处理
2)忽略
3)采取相应的行动
2.4 eval
eval命令将会首先扫描命令行进行所有的置换,然后再执行该命令。该命令适用
于那些一次扫描无法实现其功能的变量。
MYFILE="cat myfile"; `eval $MYFILE`
2.5 logger
logger命令向/var/log/message文件发送消息
格式一般为logger -p -i message
-p 为优先级,这也是缺省值
-i 在每个消息中记录发送消息的进程号
<3> 运行级别脚本介绍
3.1 运行级别
目录/etc/rcn.d
当前级别runlevel
运行级别目录文件格式SXXscript,KXXscript
3.2 启动应用程序
启动脚本分析(start|stop|restart)
/etc/init.d/下有很多脚本
<4> 几个脚本例子
#############################################
#!/bin/bash
#kill_process.sh
#只需要将firefox改为相应的进程即可
current_PID=$$
ps aux|grep "firefox"|grep -v "grep"|awk '{print $2}'>/tmp/${current_PID}.txt
for pid in `cat /tmp/${current_PID}.txt`
do
{
echo "Kill -9 $pid"
}
done
rm -f /tmp/${current_PID}.txt