存档

文章标签 ‘shell’

至今写的最长的Linux管道命令

2009年8月27日 Galaxy 20 条评论
ll -rt ./_log/*.o* |awk '{if($5==84){print $9}}'
 | perl -ne '/(GP.*Chr.*\.sh)/;print "$1\n";' 
 | while read a; do find . -name "$a" ;done 
 | while read ss; do qsub -l vf=280M -cwd $ss;done

……
原因嘛,有些计算节点默认的SHELL不是bash,如果没shell-bang就出错到STDOUT:

Warning: no access to tty (Bad file descriptor).
Thus no job control in this shell.

也有可能是其他原因,反正就这了……


后记,这样还是不行。也不知道计算节点的配置到底是出啥问题了。

后后记:结果嘛,# -S /bin/bash

shell版十进制转二进制脚本

2008年11月21日 Galaxy 1 条评论

http://bbs.chinaunix.net/thread-1074000-1-1.html
十进制转二进制的算法很简单
用2相除至结果为1 , 将余数和最后的1从下向上倒序写 就是结果
网上有的是各种转换的方法

#!/bin/bash
#
Usage(){
        echo "Error!!!"
        exit 1
}
num=$1
m=0
while ((m<${#num}));do
        [[ ${num:$m:1} = [0-9] ]] || Usage
        ((m++))
done
[[ $# -ne 1 || $1 == 0* ]] && Usage
bin=$(
while ((num!=0));do
        b=$((num%2))
        echo -n $b
        num=$((num/2))
done
)
echo -n $1\'s BinCode is:
n=${#bin}
while ((n>=0));do
        echo -n ${bin:$n:1}
        ((n--))
done
echo
echo Convert Finish!

echo "obase=2;10" | bc

#!/bin/sh
[ -z $1 ] && { echo "Error!!!";exit 1; }
function Usage(){
  for ((i=${#_M[@]};i>0;i--));do
     echo -n ${_M[$i]}
  done
  echo ${_M[0]}
  exit 0
}
_T=$1;_N=0
function expr2(){
  [ ${_T} -lt 2 ] && { _M[${_N}]=${_T};Usage; }
  _M[${_N}]=$((${_T}%2));((_N++))
  _T=$((${_T}/2))
  expr2 ${_T}
}
expr2 ${_T}

#/bin/bash
 
array=( 0000 0001 0010 0011
0100 0101 0110 0111
1000 1001 1010 1011
1100 1101 1110 1111)
 
function _oct2bin()
{
        echo -n ${array["0x$1"]}
}
function oct2bin()
{
        local str i len
        str=$(printf "%x" $1)
        len=${#str}
 
        for((i=0;i<len;i++))
        {
                _oct2bin ${str:$i:1}
        }
}
oct2bin $1

printf不支持二进制输出,只支持八进制和十六进制

分类: Linux 标签: ,

SED入门

2008年8月20日 Galaxy 没有评论

http://blog.chinaunix.net/u/21908/showart.php?id=1132017
磁针石
联系方式: gmail and gtalk: xurongzhong#gmail.com
参考资料
*《Automating UNIX and Linux Administration》之 “A.5 The sed Stream Editor”
*《LINUX与UNIX SHELL编程指南》第10章 “SED介绍”
*《AIX命令参考大全》sed 命令

sed 用法介绍
sed是一个非交互性文本流编辑器。它编辑文件或标准输入导出的文本拷贝。Sed可以随意编辑小或大的文件,有许多sed命令用来编辑、删除,并允许做这项工作时不在现场。sed一次性处理所有改变,因而变得很有效,对用户来讲,最重要的是节省了时间。

这里设计的主要内容有:

    • 抽取域。
      匹配正则表达式。
      比较域。
      增加、附加、替换。
      基本的sed命令和一行脚本。
  • 无论命令是什么, sed并不与初始化文件打交道,它操作的只是一个拷贝,然后所有的改动如果没有重定向到一个文件,将输出到屏幕。

    因为sed是一个非交互性编辑器,必须通过行号或正则表达式指定要改变的文本行。
    sed 命令使用两个工作空间来保留修改的行:保留选定行的模式空间和暂时存储行的保留空间。
    sed 子命令的一般格式如下:
    [address-range] function[modifiers]

    Sed的语法格式:

    sed [ -n ] Script [ File ... ]
    sed [ -n ] [ -e Script ] ... [ -f ScriptFile ] ... [ File ... ]

    1 sed怎样读取数据

    sed从文件的一个文本行或从标准输入的几种格式中读取数据,将之拷贝到一个编辑缓冲区,然后读命令行或脚本的第一条命令,并使用这些命令查找模式或定位行号编辑它。重复此过程直到命令结束。

    2 调用sed

    调用sed有三种方式:在命令行键入命令;将sed命令插入脚本文件,然后调用sed;将sed命令插入脚本文件,并使sed脚本可执行。

    使用sed命令行格式为:

    代码:

    sed [选项] sed命令输入文件。

    记住在命令行使用sed命令时,实际命令要加单引号。sed也允许加双引号。

    使用sed脚本文件,格式为:

    代码:

    sed [选项] -f sed脚本文件输入文件

    要使用第一行具有sed命令解释器的sed脚本文件,其格式为:

    代码:

    sed脚本文件[选项] 输入文件

    不管是使用shell命令行方式或脚本文件方式,如果没有指定输入文件, sed从标准输入中接受输入,一般是键盘或重定向结果。

    sed选项如下:

    n 不打印;sed不写编辑行到标准输出,缺省为打印所有行(编辑和未编辑)。p命令可以用来打印编辑行。

    c 下一命令是编辑命令。使用多项编辑时加入此选项。如果只用到一条sed命令,此选项无用,但指定它也没有关系。

    f 如果正在调用sed脚本文件,使用此选项。此选项通知sed一个脚本文件支持所有的sed命令,例如:sed -f myscript.sed input_file,这里myscript.sed即为支持sed命令的文件。

    2.1 保存sed输出

    由于不接触初始化文件,如果想要保存改动内容,简单地将所有输出重定向到一个文件即可。下面的例子重定向sed命令的所有输出至文件‘myoutfile’,当对结果很满意时使用这种方法。

    代码:

    $sed ‘some-sed-commands’ input-file > myoutfile

    2.2 使用sed在文件中查询文本的方式

    sed浏览输入文件时,缺省从第一行开始,有两种方式定位文本:

    引用:

    1) 使用行号,可以是一个简单数字,或是一个行号范围。

    2) 使用正则表达式

    下面是使用sed定位文本的一些方式。

    代码:

    x x为一行号,如1

    x,y 表示行号范围从x到y,如2,5表示从第2行到第5行

    /pattern/ 查询包含模式的行。例如/disk/或/[a-z]/

    ―――以下部分未实践

    /pattern/pattern/ 查询包含两个模式的行。例如/disk/disks/

    /pattern/,x 在给定行号上查询包含模式的行。如/disk/,3

    x,/pattern/ 通过行号和模式查询匹配行。3 . / v d u /

    x,y! 查询不包含指定行号x和y的行。1 , 2 !

    实例文档如下:

    # cat sed_case

    ssh host1 ‘command1′

    ssh host1 ‘command2′

    ssh host2 ‘command3′ ssh and ssh1 and ssh2

    *打印文件第一行,sed命令中一般都要包含p命令用来打印。

    # sed -n ’1p’ sed_case

    ssh host1 ‘command1′

    打印文件第1到3行

    # sed -n ’1,3p’ sed_case

    ssh host1 ‘command1′

    ssh host1 ‘command2′

    ssh host2 ‘command3′ ssh and ssh1 and ssh2

    查找文件中包含and的行,并打印出来。

    sed -n ‘/\ and/p’ sed_case

    ssh host2 ‘command3′ ssh and ssh1 and ssh2 ssh host1 ‘command2′

    2.3 基本sed编辑命令

    代码:

    sed编辑命令

    p 打印匹配行

    = 显示文件行号

    a \ 在定位行号后附加新文本信息

    i \ 在定位行号后插入新文本信息

    d 删除定位行

    c \ 用新文本替换定位文本

    s 使用替换模式替换相应模式

    r 从另一个文件中读文本

    w 写文本到一个文件

    q 第一个模式匹配完成后推出或立即推出

    l 显示与八进制A S C I I代码等价的控制字符

    { } 在定位行执行的命令组

    n 从另一个文件中读文本下一行,并附加在下一行

    g 将模式2粘贴到/pattern n/

    y 传送字符

    n 延续到下一输入行;允许跨行的模式匹配语句

    sed和正则表达式

    sed识别任何基本正则表达式和模式及其行匹配规则。记住规则之一是:如果要定位一特殊字符,必须使用( \)屏蔽其特殊含义

    附加文本

    格式

    [address]a\
    text\
    text\
    ……
    text

    # vi add

    #!/bin/sed -f

    /ssh2/ a\

    –add for test

    ./add sed_case

    ssh host1 ‘command1′

    ssh host1 ‘command2′

    ssh host2 ‘command3′ ssh and ssh1 and ssh2

    –add for test

    直接使用命令行: sed ‘/ssh2/a\–add for test’ sed_case可以达到类似效果。注意这里的sed没有-n参数。

    插入文本:

    插入命令类似于附加命令,只是在指定行前面插入。和附加命令一样,它也只接受一个地址。

    比如:

    # sed ‘/ssh2/i\–add for test’ sed_case

    ssh host1 ‘command1′

    ssh host1 ‘command2′

    –add for test

    ssh host2 ‘command3′ ssh and ssh1 and ssh2

    也可以指定行:

    代码:

    [sam@chenwy sam]$ cat insert.sed

    #!/bin/sed -f

    4 i\

    Utter confusion followed.

    修改文本:

    # sed ‘/ssh2/c\–add for test’ sed_case

    ssh host1 ‘command1′

    ssh host1 ‘command2′

    –add for test

    删除文本

    sed删除文本格式:

    代码:

    [address[,address]] d

    # sed ’1d’ sed_case

    ssh host1 ‘command2′

    ssh host2 ‘command3′ ssh and ssh1 and ssh2

    替换文本

    替换命令用替换模式替换指定模式,格式为:

    代码:

    [address[,address]] s/ pattern-to-find /replacement-pattern/[gpwn]

    g 缺省情况下只替换第一次出现模式,使用g选项替换全局所有出现模式。

    p 缺省sed将所有被替换行写入标准输出,加p选项将使- n选项无效。- n选项不打印输出结果。

    w 文件名使用此选项将输出定向到一个文件。

    # sed ‘s/and/and2/g’ sed_case

    ssh host1 ‘command21′

    ssh host1 ‘command22′

    ssh host2 ‘command23′ ssh and2 ssh1 and2 ssh2

    将替换结果写入一个文件用w选项

    # sed ‘s/and/and2/gw send.out’ sed_case

    ssh host1 ‘command21′

    ssh host1 ‘command22′

    ssh host2 ‘command23′ ssh and2 ssh1 and2 ssh2

    [root@localhost ~]# cat send.out

    ssh host1 ‘command21′

    ssh host1 ‘command22′

    # echo ‘#!/usr/bin/perl’ | sed ‘s=^#!.*perl=#!/usr/local/bin/perl=’

    #!/usr/local/bin/perl

    # echo ‘#!/opt/bin/perl -w’ | sed ‘s=^#!.*perl=#!/usr/local/bin/perl=’

    #!/usr/local/bin/perl –w

    这里优先匹配后面的.*

    从文件中读文本

    从文件中读文本

    处理文件时, sed允许从另一个文件中读文本,并将其文本附加在当前文件。此命令放在模式匹配行后,格式为:

    代码:

    address r filename

    sed ‘/company./r sedex.txt’ quote.txt

    提取IP地址
    # ifconfig eth0 | sed -n ‘/inet addr:/p’

    inet addr:10.50.20.100 Bcast:10.50.20.255 Mask:255.255.255.0

    # ifconfig eth0 | sed -n ‘s/.*inet addr:\([^ ]*\).*/\1/p’

    10.50.20.100

    建议参考的书籍:sed & awk

    附:http://phoenix.99tj.net/blog/article.asp?id=19 的参考

    sed是一个非交互性性文本编辑器, 它编辑文件或标准输入导出的文件拷贝。标准输入可能是来自键盘、文件重定向、字符串或变量,或者是一个管道文件。sed可以随意编辑小或大的文件,有许多 sed命令用来编辑、删除,并允许做这项工作时不在现场。sed一次性处理所有改变,因而变得很有效,对用户来说,最重要的是节省了时间sed必须通过行号和正则表达式指定要改变的文本行

    sed怎样读取数据:

        sed
    从文件的一个文本行或从标准输入的几种格式中读取数据,将之拷贝到一个编辑缓冲区,然后读命令行或脚本的第一条命令,并使用这些命令查找模式或定位行号编辑它,重复过程直到命令结束

    sed命令的调用:

       
    在命令行键入命令;sed命令插入脚本文件,然后调用sed;sed命令插入脚本文件,并使sed脚本可执行

        sed [option] sed
    命令 输入文件           
    在命令行使用sed命令,实际命令要加单引号

        sed [option] -f sed
    脚本文件 输入文件     使用sed脚本文件

        sed
    脚本文件 [option] 输入文件           
    第一行具有sed命令解释器的sed脚本文件

        option
    如下:

          n
    不打印; sed不写编辑行到标准输出,缺省为打印所有行(编辑和未编辑),p命令可以用来打印编辑行

          c
    下一命令是编辑命令,使用多项编辑时加入此选项

          f
    如果正在调用sed脚本文件,使用此选项,此选项通知sed一个脚本文件支持所用的sed命令,

              sed -f myscript.sed
    input_file 
    这里myscript.sed即为支持sed命令的文件

       
    使用重定向文件即可保存sed的输出

    使用sed在文本中定位文本的方式:

        x       x
    为一行号,比如1

        x,y    
    表示行号范围从xy,2,5表示从第2行到第5

        /pattern/   
    查询包含模式的行,/disk//[a-z]/

        /pattern/pattern/  
    查询包含两个模式的行,/disk/disks/

        /pattern/,x  
    在给定行号上查询包含模式的行,/disk/,3

        x,/pattern/ 
    通过行号和模式查询匹配行, 3,/disk/

        x,y!    
    查询不包含指定行号xy的行

    基本sed编辑命令:

        p     
    打印匹配行                     
    c\    
    用新文本替换定位文本

        =     
    显示文件行号                    s    
    使用替换模式替换相应模式

        a\    
    在定位行号后附加新文本信息       
    r    
    从另一个文本中读文本

        i\    
    在定位行号后插入新文本信息       
    w    
    写文本到一个文件

        d     
    删除定位行                     
    q    
    第一个模式匹配完成后退出或立即退出

        l     
    显示与八进制ASCII代码等价的控制字符       
    传送字符

        n     
    从另一个文本中读文本下一行,并附加在下一行  
    {}    
    在定位行执行的命令组

        g     
    将模式2粘贴到/pattern n/

    基本sed编程举例:

       
    使用p(rint)显示行: sed
    -n ’2p’ temp.txt  
    只显示第2,使用选项n

       
    打印范围:  sed
    -n ’1,3p’ temp.txt        
    打印第1行到第3

       
    打印模式
    sed -n ‘/movie/’p temp.txt    
    打印含movie的行

       
    使用模式和行号查询
    sed -n ’3,/movie/’p temp.txt  
    只在第3行查找movie并打印

       
    显示整个文件
    sed -n ’1,$’p temp.txt      $
    为最后一行

       
    任意字符:  sed
    -n ‘/.*ing/’p temp.txt     
    注意是.*ing,而不是*ing

       
    打印行号:  sed -e ‘/music/=’ temp.txt

       
    附加文本 :( 创建sed脚本文件)chmod
    u+x script.sed
    ,
    运行时./script.sed temp.txt

            #!/bin/sed -f

            /name1/
    a\             #a\
    表示此处换行添加文本

           
    HERE ADD NEW LINE.     #
    添加的文本内容

       
    插入文本: /name1/ a\ 改成 4 i\ 4表示行号,i插入

       
    修改文本: /name1/ a\ 改成 /name1/ c\ 将修改整行,c修改

       
    删除文本: sed ’1d’ temp.txt  或者 sed ’1,4d’ temp.txt

       
    替换文本: sed ‘s/source/OKSTR/’ temp.txt     source替换成OKSTR

                 sed
    ‘s/\$//g’
    temp.txt             
    将文本中所有的$符号全部删除

                 sed
    ‘s/source/OKSTR/w temp2.txt’ temp.txt
    将替换后的记录写入文件temp2.txt

       
    替换修改字符串: sed ‘s/source/”ADD BEFORE” &/p’ temp.txt

                 
    结果将在source字符串前面加上“ADD BEFORE”,这里的&表示找到的source字符并保存

       
    sed结果写入到文件: sed ’1,2 w temp2.txt’ temp.txt

                        
    sed ‘/name/ w temp2.txt’ temp.txt

       
    从文件中读文本: sed ‘/name/r temp2.txt’ temp.txt

       
    在每列最后加文本: sed ‘s/[0-9]*/& Pass/g’ temp.txt

       
    shellsed传值: echo $NAME | sed “s/go/$REP/g”   注意需要使用双引号

    快速一行命令:

       
    ‘s/\.$//g’         
    删除以句点结尾行

        ‘-e /abcd/d’      
    删除包含abcd的行

        ‘s/[][][]*/[]/g’  
    删除一个以上空格,用一个空格代替

        ‘s/^[][]*//g’     
    删除行首空格

        ‘s/\.[][]*/[]/g’  
    删除句号后跟两个或更多的空格,用一个空格代替

       
    ‘/^$/d’           
    删除空行

       
    ‘s/^.//g’         
    删除第一个字符,区别  ‘s/\.//g’删除所有的句点

        ‘s/COL/(…\)//g’ 
    删除紧跟COL的后三个字母

        ‘s/^\///g’        
    删除路径中第一个\

    分类: Linux 标签: , ,

    Linux服务器系统监控框架与MSN、E-mail、手机短信报警的实现

    2008年7月8日 Galaxy 2 条评论

    http://blog.s135.com/read.php/354.htm

    Linux服务器系统监控框架与MSN、E-mail、手机短信报警的实现[原创]

    [文章作者:张宴 本文版本:v1.0 最后修改:2008.06.25]最近,在我原有的“Linux服务器系统监控程序”基础上,完善了HTTP、TCP、MySQL主动监控与MSN、E-mail、手机短信报警。监控程序以shell和PHP程序编写,以下为主要框架与部分代码:

    一、系统监控接口程序(interface.php)具有的报警方式
    1、MSN实时报警
    ①、监控程序每次检测到故障存在、或者故障恢复,都会发送短消息到管理员的MSN。
    点击在新窗口中浏览此图片

    点击在新窗口中浏览此图片

    发送MSN短消息用了一个PHP类:sendMsg,使用该PHP类发消息,必须将发送、接收双方的MSN加为联系人,发送中文时,先用iconv将字符集转为UTF-8:

    引用
    $sendMsg->sendMessage(iconv(“GBK”, “UTF-8″, $message), ‘Times New Roman’, ’008000′);

    2、手机短信报警
    ①、工作日早上10点之前,晚上6点之后,以及周六、周日,监控程序检测到故障,会调用手机短信接口,发送短信给管理员的手机。
    ②、如果监控程序多次检测到同一台服务器的同一类故障,只会在第一次检测到故障时发送一条“故障报警”短信。服务器故障恢复后,监控程序会再发送一条“故障恢复”短信。

    如果没有手机短信网关接口,可以试试中国移动通信的www.139.com邮箱,具有免费的邮件到达手机短信通知功能,可以将收到的邮件标题以短信的形式发送到手机上。


    3、电子邮件报警
    ①、如果监控程序多次检测到同一台服务器的同一类故障,只会在第一次检测到故障时发送一封“故障报警”邮件。服务器故障恢复后,监控程序会再发送一封“故障恢复”邮件。

    系统监控接口程序interface.php(核心部分,仅提供部分代码):

    1. <?php
    2. //HTTP服务器监控
    3. if (htmlspecialchars($_POST["menu"]) == “http”)
    4. {
    5. $date = htmlspecialchars($_POST["date"]);
    6. $ip = htmlspecialchars($_POST["ip"]);
    7. $port = htmlspecialchars($_POST["port"]);
    8. $status = htmlspecialchars($_POST["status"]);//状态,0表示无法访问,1表示正常,2表示无法访问但能ping通
    9. //…下一步处理(省略)…
    10. }
    11. //TCP服务器监控
    12. if (htmlspecialchars($_POST["menu"]) == “tcp”)
    13. {
    14. $date = htmlspecialchars($_POST["date"]);
    15. $ip = htmlspecialchars($_POST["ip"]);
    16. $port = htmlspecialchars($_POST["port"]);
    17. $status = htmlspecialchars($_POST["status"]);//状态,0表示无法访问,1表示正常,2表示无法访问但能ping通
    18. //…下一步处理(省略)…
    19. }
    20. //MySQL服务器监控
    21. if (htmlspecialchars($_POST["menu"]) == “mysql”)
    22. {
    23. $date = htmlspecialchars($_POST["date"]);
    24. $ip = htmlspecialchars($_POST["ip"]);
    25. $port = htmlspecialchars($_POST["port"]);
    26. $abstract = htmlspecialchars($_POST["abstract"]);//故障摘要(必须为全角)
    27. $info = htmlspecialchars($_POST["info"]);//故障详细描述
    28. $failback = htmlspecialchars($_POST["failback"]);//如果服务器存活,此处接收的值为active
    29. //…下一步处理(省略)…
    30. }
    31. ?>


    二、主动探测监控(“监控机”主动探测“被监控机”)
    1、HTTP服务器监控
    脚本:/data0/monitor/http.sh

    引用
    #!/bin/sh
    LANG=C

    #被监控服务器、端口列表
    server_all_list=(\
    192.168.1.1:80 \
    192.168.1.2:80 \
    192.168.1.3:80 \
    )

    date=$(date -d “today” +”%Y-%m-%d_%H:%M:%S”)

    #采用HTTP POST方式发送检测信息给接口程序interface.php,接口程序负责分析信息,决定是否发送报警MSN消息、手机短信、电子邮件。
    send_msg_to_interface()
    {
    /usr/bin/curl -m 600 -d menu=http -d date=$date -d ip=$server_ip -d port=$server_port -d status=$status http://127.0.0.1:8888/interface.php
    }

    server_all_len=${#server_all_list[*]}
    i=0
    while [ $i -lt $server_all_len ]
    do
    server_ip=$(echo ${server_all_list[$i]} | awk -F ‘:’ ‘{print $1}’)
    server_port=$(echo ${server_all_list[$i]} | awk -F ‘:’ ‘{print $2}’)
    if curl -m 10 -G http://${server_all_list[$i]}/ > /dev/null 2>&1
    then
    #status: 0,http down 1,http ok 2,http down but ping ok
    status=1
    echo “服务器${server_ip},端口${server_port}能够正常访问!”
    else
    if curl -m 30 -G http://${server_all_list[$i]}/ > /dev/null 2>&1
    then
    status=1
    echo “服务器${server_ip},端口${server_port}能够正常访问!”
    else
    if ping -c 1 $server_ip > /dev/null 2>&1
    then
    status=2
    echo “服务器${server_ip},端口${server_port}无法访问,但是能够Ping通!”
    else
    status=0
    echo “服务器${server_ip},端口${server_port}无法访问,并且无法Ping通!”
    fi
    fi
    fi
    send_msg_to_interface
    let i++
    done


    2、TCP服务器监控
    脚本:/data0/monitor/tcp.sh

    引用
    #!/bin/sh
    LANG=C

    #被监控服务器、端口列表
    server_all_list=(\
    192.168.1.4:11211 \
    192.168.1.5:11211 \
    192.168.1.6:25 \
    192.168.1.7:25 \
    )

    date=$(date -d “today” +”%Y-%m-%d_%H:%M:%S”)

    #采用HTTP POST方式发送检测信息给接口程序interface.php,接口程序负责分析信息,决定是否发送报警MSN消息、手机短信、电子邮件。
    send_msg_to_interface()
    {
    /usr/bin/curl -m 600 -d menu=tcp -d date=$date -d ip=$server_ip -d port=$server_port -d status=$status http://127.0.0.1:8888/interface.php
    }

    server_all_len=${#server_all_list[*]}
    i=0
    while [ $i -lt $server_all_len ]
    do
    server_ip=$(echo ${server_all_list[$i]} | awk -F ‘:’ ‘{print $1}’)
    server_port=$(echo ${server_all_list[$i]} | awk -F ‘:’ ‘{print $2}’)
    if nc -vv -z -w 3 $server_ip $server_port > /dev/null 2>&1
    then
    #status: 0,http down 1,http ok 2,http down but ping ok
    status=1
    echo “服务器${server_ip},端口${server_port}能够正常访问!”
    else
    if nc -vv -z -w 10 $server_ip $server_port > /dev/null 2>&1
    then
    status=1
    echo “服务器${server_ip},端口${server_port}能够正常访问!”
    else
    if ping -c 1 $server_ip > /dev/null 2>&1
    then
    status=2
    echo “服务器${server_ip},端口${server_port}无法访问,但是能够Ping通!”
    else
    status=0
    echo “服务器${server_ip},端口${server_port}无法访问,并且无法Ping通!”
    fi
    fi
    fi
    send_msg_to_interface
    let i++
    done


    3、MySQL服务器监控
    ①、MySQL是否能够连接
    ②、MySQL是否发生表损坏等错误
    ③、MySQL活动连接数是否过多
    ④、MySQL从库是否同步正常
    ⑤、MySQL从库同步延迟时间是否过大
    脚本:/data0/monitor/mysql.php

    1. <?php
    2. //$server_list[]=”服务器地址:端口:帐号:密码”;
    3. $server_list[]=“192.168.1.11:3306:root:password”;
    4. $server_list[]=“192.168.1.12:3306:root:password”;
    5. $server_list[]=“192.168.1.13:3306:root:password”;
    6. $database=“mysql”;
    7. $curl = new Curl_Class();
    8. foreach ($server_list as $server) {
    9. $status=1;//初始化,正常状态
    10. unset($data);
    11. $data["menu"] = “mysql”;
    12. $data["info"] = “”;
    13. list($data["ip"], $data["port"], $username, $password) = explode(“:”, $server);
    14. $connect = @mysql_connect($data["ip"].“:”.$data["port"], $username, $password);
    15. if(! $connect)
    16. {
    17. $status=0;
    18. $data["info"] = $data["info"] . “无法连接MySQL服务器\r\n”;
    19. }
    20. $select = @mysql_select_db($database, $connect);
    21. $result = @mysql_query(“show slave status”);
    22. $rs_slave = @mysql_fetch_array($result);
    23. $result = @mysql_query(“show global status like ‘Threads_running’”);
    24. $rs_threads = @mysql_fetch_array($result);
    25. if($rs_slave["Slave_SQL_Running"] == “No”)
    26. {
    27. $status=0;//故障状态
    28. $data["abstract"] = “从库不同步”;
    29. $data["info"] = $data["info"] . “Slave_SQL_Running = No\r\n”;
    30. }
    31. if($rs_slave["Slave_IO_Running"] == “No”)
    32. {
    33. $status=0;
    34. $data["abstract"] = “从库不同步”;
    35. $data["info"] = $data["info"] . “Slave_IO_Running = No\r\n”;
    36. }
    37. if($rs_slave["Last_Error"] != “”)
    38. {
    39. $status=0;
    40. $data["abstract"] = “从库同步出错”;
    41. $data["info"] = $data["info"] . “Last_Error = “.substr($rs_slave["Last_Error"], 0, 40).“\r\n”;
    42. }
    43. if($rs_slave["Seconds_Behind_Master"] > 180)
    44. {
    45. $status=0;
    46. $data["abstract"] = “从库同步延迟时间高达”.$rs_slave["Seconds_Behind_Master"].“秒”;
    47. $data["info"] = $data["info"] . “Seconds_Behind_Master = “.$rs_slave["Seconds_Behind_Master"].“\r\n”;
    48. }
    49. if($rs_threads["Value"] > 60)
    50. {
    51. $status=0;
    52. $data["abstract"] = “活动连接数多达”.$rs_threads["Value"];
    53. $data["info"] = $data["info"] . “Threads_running = “.$rs_threads["Value"].“\r\n”;
    54. }
    55. $data["date"] = date(“Y-m-d_H:i:s”);
    56. if($status == 0)
    57. {
    58. $post = @$curl->post(“http://127.0.0.1:8888/interface.php”, $data);
    59. echo “MySQL服务器“”.$data["ip"].“:”.$data["port"].“”发生故障!\n”;
    60. print_r($post);
    61. }
    62. else
    63. {
    64. $data["failback"] = “active”;//服务器正常,发送通知信息
    65. $post = @$curl->post(“http://127.0.0.1:8888/interface.php”, $data);
    66. echo “MySQL服务器“”.$data["ip"].“:”.$data["port"].“”运行正常!\n”;
    67. print_r($post);
    68. }
    69. }
    70. /**
    71. *********************************************************************
    72. * Curl_Class :curl 类
    73. *********************************************************************/
    74. class Curl_Class
    75. {
    76. function Curl_Class()
    77. {
    78. return true;
    79. }
    80. function execute($method, $url, $fields = , $userAgent = , $httpHeaders = ,
    81. $username = , $password = )
    82. {
    83. $ch = Curl_Class::create();
    84. if (false === $ch)
    85. {
    86. return false;
    87. }
    88. if (is_string($url) && strlen($url))
    89. {
    90. $ret = curl_setopt($ch, CURLOPT_URL, $url);
    91. }
    92. else
    93. {
    94. return false;
    95. }
    96. //是否显示头部信息
    97. curl_setopt($ch, CURLOPT_HEADER, false);
    98. //
    99. curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
    100. if ($username != )
    101. {
    102. curl_setopt($ch, CURLOPT_USERPWD, $username . ‘:’ . $password);
    103. }
    104. $method = strtolower($method);
    105. if (‘post’ == $method)
    106. {
    107. curl_setopt($ch, CURLOPT_POST, true);
    108. if (is_array($fields))
    109. {
    110. $sets = array();
    111. foreach ($fields as $key => $val)
    112. {
    113. $sets[] = $key . ‘=’ . urlencode($val);
    114. }
    115. $fields = implode(‘&’, $sets);
    116. }
    117. curl_setopt($ch, CURLOPT_POSTFIELDS, $fields);
    118. }
    119. else
    120. if (‘put’ == $method)
    121. {
    122. curl_setopt($ch, CURLOPT_PUT, true);
    123. }
    124. //curl_setopt($ch, CURLOPT_PROGRESS, true);
    125. //curl_setopt($ch, CURLOPT_VERBOSE, true);
    126. //curl_setopt($ch, CURLOPT_MUTE, false);
    127. curl_setopt($ch, CURLOPT_TIMEOUT, 600);
    128. if (strlen($userAgent))
    129. {
    130. curl_setopt($ch, CURLOPT_USERAGENT, $userAgent);
    131. }
    132. if (is_array($httpHeaders))
    133. {
    134. curl_setopt($ch, CURLOPT_HTTPHEADER, $httpHeaders);
    135. }
    136. $ret = curl_exec($ch);
    137. if (curl_errno($ch))
    138. {
    139. curl_close($ch);
    140. return array(curl_error($ch), curl_errno($ch));
    141. }
    142. else
    143. {
    144. curl_close($ch);
    145. if (!is_string($ret) || !strlen($ret))
    146. {
    147. return false;
    148. }
    149. return $ret;
    150. }
    151. }
    152. function post($url, $fields, $userAgent = , $httpHeaders = , $username = ,
    153. $password = )
    154. {
    155. $ret = Curl_Class::execute(‘POST’, $url, $fields, $userAgent, $httpHeaders, $username,
    156. $password);
    157. if (false === $ret)
    158. {
    159. return false;
    160. }
    161. if (is_array($ret))
    162. {
    163. return false;
    164. }
    165. return $ret;
    166. }
    167. function get($url, $userAgent = , $httpHeaders = , $username = , $password =
    168. )
    169. {
    170. $ret = Curl_Class::execute(‘GET’, $url, , $userAgent, $httpHeaders, $username,
    171. $password);
    172. if (false === $ret)
    173. {
    174. return false;
    175. }
    176. if (is_array($ret))
    177. {
    178. return false;
    179. }
    180. return $ret;
    181. }
    182. function create()
    183. {
    184. $ch = null;
    185. if (!function_exists(‘curl_init’))
    186. {
    187. return false;
    188. }
    189. $ch = curl_init();
    190. if (!is_resource($ch))
    191. {
    192. return false;
    193. }
    194. return $ch;
    195. }
    196. }
    197. ?>


    4、主动监控守护进程
    脚本:/data0/monitor/monitor.sh

    引用
    #!/bin/sh
    while true
    do
    /bin/sh /data0/monitor/http.sh > /dev/null 2>&1
    /bin/sh /data0/monitor/tcp.sh > /dev/null 2>&1
    /usr/local/php/bin/php /data0/monitor/mysql.php > /dev/null 2>&1
    sleep 10
    done

    启动主动监控守护进程:

    /usr/bin/nohup /bin/sh /data0/monitor/monitor.sh 2>&1 > /dev/null &

    三、被动报告监控(“被监控机”采集数据发送给“监控机”)
    1、磁盘空间使用量监控
    2、磁盘Inode使用量监控
    3、Swap交换空间使用量监控
    4、系统负载监控
    5、Apache进程数监控

    被动监控这部分,在我的文章《写完“Linux服务器监控系统 ServMon V1.1” 》中已经实现,就不再详细写出。

    分类: Linux 标签: , , , ,
    Locations of visitors to this page