分类:
2012-12-18 11:42:12
原文地址:shell脚本FAQ与常用数据库服务器监控脚本 作者:kennychang05
[Q]学会使用简单的sed命令?
sed命令可以对行进行打印,删除,替换操作
格式:
sed ‘command’ filename
平时我们用的最多的是打印命令:
sed –n ‘/pattern/p’ datafile
该命令的意思是只打印匹配pattern的行,参数-n必须要指定,否则会把datafile文件中的信息全部打印出来。/p是指打印的意思.
也可以明确的指定打印哪几行,可以通过下面的命令:
sed –n ‘1,3p’ datafile
打印第一行和第三行
另外一种形式,指定行的范围
sed –n ‘/pattern1/,/pattern2/p’ datafile
打印在模式pattern1,pattern2之间的所有行,包括匹配pattern1,pattern2的行
删除命令:
sed ‘3d’ datafile
删除datafile文件的第三行,其余的行都被打印出来
sed ‘3,$d’ datafile
删除第三行到最后一行的内容,即只打印datafile文件的第一行,第二行。d代表删除的意思,美元符代表文件的最后一行,逗号称为范围操作符。
sed ‘/pattern/d’ datafile
所有包含模式pattern的行都被删除;其余的行都被打印。
替换命令:
sed ‘s/pattern1/pattern2/g’ datafile
s命令用于替换。命令的末端的标志g表示在行内进行全局替换;也就是说,如果某一行里出现了多个pattern1,所有的pattern1都会被替换成pattern2.如果没有g命令,则只将每一行的第一个pattern1替换成pattern2
[Q]学会使用简单的awk命令?
格式:
awk ‘pattern’ filename
awk ‘{action}’ filename
awk ‘pattern{action}’ filename
示例:
awk ‘pattern’ filename
该命令把文件中匹配pattern的所有行都打印出来,相当于sed –n ‘/pattern/p’ filename
awk ‘{action}’ filename
对于action,我们通常用的是print命令
awk ‘{print $1}’ filename
打印文件的第一列,此命令与sed命令相结合,就可以打印某行某列的内容。也可以由awk下面的命令示例独立完成。
awk ‘pattern{action}’ filename
如:awk ‘/pattern/{print $1,$2}’ filename
当文件filename中某一行中含有模式pattern时,awk打印该行的头两个字段。记住,字段的分隔符是空白符。
[Q]如何用awk命令分割字符串?
[oracle@test oracle]$ echo "aaa,bbb,ccc"|awk -F ',' '{print $1,$2,$3}'
aaa bbb ccc
awk -F ',' 这里的意思是以 ,为分隔符,如果不指定-F '分隔符',默认情况下是以空格为分隔符
[Q]如何判断文件是否存在?
Bourrn shell与korn shell脚本是有差异的
#!/bin/sh #Bourrn shell script #danchen for test v_file=/tmp/abc.shx if [ ! -f $v_file ] then echo "$v_file is not exist" fi |
#!/bin/ksh #korn shell script #danchen for test v_file=/tmp/abc.shx if [ ! -a $v_file ] then echo "$v_file is not exist" fi |
[Q]如何比较文件内容是否发生了变化?
$CP /tmp/link_danger.log /tmp/link_danger.log.new v_mc=`diff /tmp/link_danger.log.new /tmp/link_danger.log.old|grep "<"|wc -l` $CP /tmp/link_danger.log.new /tmp/link_danger.log.old |
[Q]如何写for循环语句?
格式:
for variable in word_list do commands done |
示例:
for pal in tom eygle piner biti do echo "hi $pal" done |
注:词表后面必须紧跟关键字do.如果把do和列表放在同一行,就必须用分号结束词表
我们可以先从一个文件读出内容,然后再循环,这也是比较常用的用法,这样做的好处是把列表与脚本分开,便于日常维护
w_list=`cat /tmp/test.txt` for pal in $w_list do echo "hi $pal" done |
注:文中采用的是左单引号
[Q] 如何写while循环语句?
格式:
while command do command(s) done |
简单示例:
read answer while [ $answer != "abc" ] do echo "your input is error" read answer done
echo "you got it abc" |
[Q]break命令
内置命令break用于强行退出循环,但不退出程序(要退出程序,用exit命令)。执行break命令后,控制从关键字done的下一行开始。因此,如果有嵌套循环,可以给break命令一个数字作为参数,这样就能指定跳到哪个外层循环外面。如果你嵌套了3层循环,最外层循环就是第3层循环,中间那层是第2层循环,最里面那层就是第1层循环。
格式:
break [n]
[Q]continue命令
内置命令continue在某个条件为真时,把控制转回循环的顶部。continue下面所有的命令都被忽略。如果给它一个参数,continue就能将控制转到任一层循环的起点。
格式:
continue [n]
[Q]shell中的函数
shell中的函数其实就是给某一条或某一组命令取的名字。函数用来实现模块化的程序,并且使程序更有效率。函数在当前的shell的环境中执行,也就是说,函数执行时并不派生一个子进程。
函数使用的一些重要原则:
格式:
function function_name() { commands;commands }
注:
关键字function后紧跟函数名dir(有时函数名后跟有圆括号,但不是必须的).花括号两侧的空格是必须的。
函数的参数与返回值
由于函数是在当前shell中执行的,所以变量对函数和shell都是可见的。你在函数中对环境所做的任何改动也会改变shell的环境。
参数 你可以使用位置参量向函数传递参数。位置参量是函数私有的,也就是说,函数对参数的操作不会影响在函数外使用的任何位置参量。
内置功能local 函数私有的局部变量,在函数退出后随之消失,可以使用内置的local功能创建局部变量。
内置功能return return命令可用来退出函数并将控制转回程序调用函数的位置。
示例如下:
function abc { echo "**********************" echo "i am zhaolin" return } abc --调用函数
|
[Q]case命令
case命令是一个多路分支命令,可用来代替if/else命令。
格式:
case variable in value1) commands ;; value2) commands ;; *) commands ;; esac
|
--计算归档空间使用的百分比,已去掉百分号 v_arc_p=`df -h|grep archive|awk '{print $5}'|sed 's/%//g'` if [ $v_arc_p –gt 90 ] then --报警 else --正常 fi |
[Q]如何分析警报日志是否有新的错误信息?
#alert.log if [ -f $BDUMP/alert_${ORACLE_SID}.log.old ] then $CP 警报日志 警报日志.new v_alert=`diff警报日志.new 警报日志.old |grep "<"|grep "ORA-"` n_alert=`diff警报日志.new 警报日志.old |grep "<"|grep "ORA-"|wc -l` $CP警报日志.new 警报日志.old if [ $n_alert -gt 0 ] then echo "$v_alert" > /tmp/alert_danger.log 发送警告邮件 fi else $CP警报日志 警报日志.old fi |
[Q]如何监控机器的连接是否超过限制?
首先spool出当前的机器连接文件 spool /tmp/link_danger.log select machine,count(*) from v\$session group by machine having count(*)>15; spool off ----------------------------------------------------------------------------------------------- 对文件进行分析 if [ -f /tmp/link_danger.log.old ] then $CP /tmp/link_danger.log /tmp/link_danger.log.new v_mc=`diff /tmp/link_danger.log.new /tmp/link_danger.log.old|grep "<"|wc -l` $CP /tmp/link_danger.log.new /tmp/link_danger.log.old if [ $v_mc -gt 0 ] then v_m_c=`cat /tmp/link_danger.log.new|grep "MACHINE"|wc -l` if [ $v_m_c -gt 0 ] then --发送警告邮件 fi fi else echo " " > /tmp/link_danger.log.old fi |
[Q]如何监控锁阻塞?
--首先登陆数据库查询当前的锁阻塞信息,并spool出文件 $ORACLE_HOME/bin/sqlplus -S "taobao/taobao@dev-dbc" < set serveroutput on size 20000; set linesize 2000 spool /tmp/lock_danger.log declare sql1 varchar2(2000); sql2 varchar2(2000); machine1 varchar2(50); machine2 varchar2(50); isblock number; seq number; begin for i in(select sid,id1,id2 from v\$lock where type='TX' and lmode=6) loop isblock := 0; select serial#,machine into seq,machine1 from v\$session where sid=i.sid;
for j in(select sid,id1,id2 from v\$lock where type='TX' and request=6) loop if i.id1=j.id1 and i.id2=j.id2 then isblock := 1; select machine into machine2 from v\$session where sid=j.sid; dbms_output.put_line('machine '||machine1||' is blocking machine '||machine2); end if; end loop; if isblock=1 then dbms_output.put_line('alter system kill session '''||i.sid||','||seq||''';'); dbms_output.put_line(chr(10)); end if; end loop; end; / spool off exit; EOF
-------------------------------------------------------------------------------------------------------- 分析文件 #analyze v_kill=`cat /tmp/lock_danger.log|grep "alter system kill session"|wc -l` if [ $v_kill -gt 0 ] then --发送警告邮件 fi |
[Q]如何监控是否有会话长时间不提交sql语句?
Spool /tmp/uncom_session.log Select ‘warnig’,sid,ctime from v$lock where type=’TX’ and lmode=6 and ctime > 阀值; Spool off ------------------------------------------------------------------------------- --分析 v_session=`cat /tmp/uncom_session.log|grep “warning”|wc –l` if [ v_session –gt 0 ] then 发送邮件 fi |
[Q]如何监控数据库的负载是否正常?
echo "load" echo "************************" v_ld=`w|grep load|grep -v "grep load"|sed 's/,//g'|awk '{print $10}'` vv_ld=`printf "%2.0f" $v_ld` f_ld=3 --阀值 if [ $vv_ld -gt $f_ld ] then mailmsg="${dbname}'s load is larger than $f_ld,now is $v_ld" echo "$mailmsg" > /tmp/load_$HOSTNAME.log --发送警告邮件 else echo "${dbname}'s load is normal,now is $v_ld" fi 注:shell脚本不能比较小数,所以在此例中做了一点特殊的处理 |
[Q]如何监控交换分区的使用量?
Linux
echo "swap" echo "************************" v_swap=`free|sed -n 4p|awk '{print $3}'` f_swap=200000 --阀值 if [ $v_swap -gt $f_swap ] then mailmsg="${dbname}'s swap is larger than $f_swap,now is $v_swap" echo "$mailmsg" > /tmp/swap_$HOSTNAME.log --发送邮件 else echo "the swap is normal,now is ${v_swap}k" fi |
Unix
echo “swap” echo “*************************” 在Unix上查看交换分区使用量的命令为: lsps -s Total Paging Space Percent Used 8192MB 10% 因此通过命令分析出这个百分比,即可进行比较 v_swap=`lsps –s|grep %|awk ‘{print $2}’|sed ‘s/%//g’` if [ v_swap –gt 30 ] then --发送警告邮件 fi |
[Q]如何监控数据库的连接数是否在数据库的参数processes范围之内?
v_pga=`ps –ef|grep LOCAL|wc –l`
假如定义的processes为2000个,那么v_pga应该小于1900,如果开始超过这个值,就应该增大processes参数的值,或者改小客户端应用服务器的连接数
[Q]如何判断所有的文件系统的空间使用率是否在一个正常的水平?
linux
#filesystem used persent echo "" echo "filesystem space check" echo "************************" f_used=95 v_used=`df -h|sed -n '2,$p'|awk '{print $5}'|sed 's/%//g'` for space in $v_used do if [ $space -gt $f_used ]; then echo "${HOSTNAME}'s filesystem space is more than $f_used%,now is $space%" > /tmp/filesystem.log df -h|grep $space >> /tmp/filesystem.log 发送邮件 fi done |
[Q]如何判断表空间使用率是否超过阀值?
f_used=95 v_used_list=`cat /tmp/freespace.log|grep -v TEMP|sed -n '4,$p'|awk '{print $5}'` for v_used in $v_used_list do if [ `echo "$v_used >= $f_used" | bc` -eq 1 ]; then cat /tmp/freespace.log|grep $v_used > /tmp/freespace_danger.log 发送警告邮件 fi done |