新的wiki,新的blog

作者:Ajian 发布时间:May 31, 2013 分类:生活记事

前言: 
之前更新blog都是到后台更新,非的常的不方便,如果用离线的linux和mac又支持得不好,而且后台的编辑器,如果是复制粘贴还会出各种格式问题.所以一直找一个更简单的办法,不用苦于编辑器等问题.所以最后有了这个新的wiki http://wiki.ohlinux.com 左上角有个绿色的链接.
问题发于:
http://segmentfault.com/q/1010000000201240
成型于:
http://wiki.ohlinux.com/wiki/tool/sitebuild/ohlinuxwiki.html
改进:
在成型的基础上
  • 添加了uyan 留言;
  • 添加vimrc的命令,在保存的时候进行make和时间插入;
  • 还可以添加google搜索等;
  • 进行了一些seo的优化和扒了新的皮肤
  • 用go语言写了一个web服务和自动make(自动make可以不用了,vim保存就make了).
以后基本多会更新wiki了,想到哪写到哪,时时是在写更新不一定,写的东西成一些文了就同步.
另外markdown转pdf也都已经完成.
下一步计划:
  • 将相关的服务进行打包,生成一键安装.

纪念我的第一次马拉松

作者:Ajian 发布时间:November 26, 2012 分类:生活记事

赛前:
  马拉松marathon 是我一 直就想跑的,之前老是因为工作忙或者有其它事,没能如愿,去年就想好今年一定要跑,结果我从5月份(因为往年都是从这个时候开始报名)一直盼到11月份,就是没有看到报名,最后某大确定什么时候结束马拉松才确定了时间。我还差点没报上。11月10号我报上名了,比赛时间为11月25号,而且天气会特别的冷,我纠结了一会要不要报,最后我报了,不为别的就当先体验下。
  15天准备时间,之前因为一直没有报上名,所以也没有做系统的训练,这几天我每隔两天进行了一次10公里以上的测试,每天都会进行力量训练,进行了19和28公里的长距离测试,最后一次的28公里测试在赛前一个星期,结果伤了点左腿,在比赛前我还一直担心我的左小腿,因为稍微用力都痛。最后一个星期进行了几次寒冷测试,都是20分钟左右不能高强度,因为之前都是在健身房,环境跟真实的完全不一样,所以要让自己提前感受下。
  通过这15天的准备,我发现我原来的鞋子不能承担这次的马拉松,而且短衣短裤也很难应对这个寒冷的天气。所以我为自己购置了一双asics gel radience 6 很不错的鞋子到底是做专业跑步的。后来为保险我还花血本买了一套李宁 skins A200 ,这样不管是在保暖和肌肉的保护上面都要好很多。最后证明这些装备都是很值得的,我也见识了科技的力量。
  比赛前因为有广州的马拉松事件,很多人开始跟我说要保重啊,要活着回来啊,要注意乳贴啊,哈哈,谢谢那些关心我的朋友们,不过我被你们吓到了,我原来是预计4小时以内完成比赛,后来我的心里底线都降到5小时,甚至6小时了。
   比赛前一天,我将跑步过程中要用的东西都准备好了,还安排了两个朋友在20公里和30公里处帮我送吃的,吃的有香蕉,士力架,蛋白粉。我在前一周就开始注意歌曲的收集,遇到好的歌曲就下载下来,并删除不适合跑步的音乐,我的跑步是少不了音乐的。悲剧的事情,我前一天插在电脑上充电,最后睡觉的时候把电脑关了,早晨起来,MP3的电都放光了,而且出现了音频错误,歌曲也导不出来。早晨出发的时候没办法,拿了一个户外的小音响,可以手握,但我也很久没用,也没有充电估计使用不了多久。
  25号早晨6点起床到7点多出发,天还是黑的,到达起跑地,依旧还是灰蒙蒙的,今天有3-4级的风,而且没有太阳,真是恶劣的天气。
  因为封路的关系,和老胡很久才碰到面,而且他们都是不能进去的,只好在地铁出口的地方给他们分配了东西,我就一个挤进人群了,挤了好久,从mini马拉松一路挤到半程马拉松,还没有到全程,就听到说开跑了,OMG,人真是超多的。
 
赛中:
  我就跟着人群慢慢的挪啊,就当热身吧,都还没有拉身,也没有压韧带,下次还是要提早进行会比较好。大概跑了30多分钟,mini马拉松终点都到了人群还没有散开,前后距离也没有怎么拉开。
 我也没有开音响,因为要节省电。但一路其实挺好玩的,有各种各样的参赛的人,各种打扮,有打赤脚的,有超人,美国队长,还有背旗子的,男扮女装的等等。一路也有很多开音箱的。路边的参观人员也很激情,所以前面完全是非常轻松的,好好去享受那种气氛,当然有人群也不会太冷的。
 第一个10公里,第一个10公里用了近一小时,状态良好,身也热得差不多了,从我家楼下经过的时候没有看到我的室友啊,肯定是睡懒觉了。人群也散开了,我开始提速,音响打开,一路赶超了好多人。
 21公里处,这里是我跟老胡约的地方,但我知道我错了,我看路线的时候弄错了一条街,果然我在中关村没有看到他的身影,当时心里就凉了,这个时候要补充一些东西了,我已经感觉到饿了,看来我要再坚持到30公里处。前面主办方都是没有提供吃的,只有水和饮料。跑着跑着我看到前面路人有免费提供香蕉的,我一上去就抱了三个(是切段的,组起来也就是一个),吃了立马感觉好多了,真的要感谢那些在路上免费提供食物的人 。在26公里处,我左脚小趾如约的破的了水泡,真是给面子,太准时了。痛了一阵子也就没有什么感觉了。
 32公里处,我就按之前的速度一路跑,不过中间老是会停下来补充水和食物,因为都是杯子,也跑不动一跑就会出来,只好停下来,一停下来速度就会受影响。到达30公里之后,就差不多是奥体了,但我看到周边都是没有人群的,而且没有其它交通,我心理凉了,小夏肯定赶不到这来。31公里音响突然没声了,我知道没电了,唉真是不争气啊。就当我放弃了所有念头的时候,一个声音在叫我,哇是小夏,那个激动啊,没想到他走了10公里到这里,太感谢了,吃了东西之后,身上立刻就暖和多了。音响给了他,我也用不上了。到这里我已经用了3小时,别了小夏继续我的马拉松。
 最后的折磨,最后的10公里真的是很折磨, 首先是有一段向北的,是逆风,而且风也有点大,眼睛都被吹了几次东西;再是没有了音乐,没有了音乐我的注意力就一直在腿上面,就觉得更痛了,而且只能听到自己跑步声;还有到达这里的人大多已经是精疲力尽,有倒下的,有抽筋的,有走路的,没有人群没有喝采,两边都是公园的树那么的安静,整个气氛都很消沉。我也是走走跑跑,尤其这里还有些小坡,上坡我就走上去,下坡就跑。脚上的泡都可以感觉得到,大腿和膝盖都在承受着疼痛。不过唯一让我有动力的就是过一会可以看到写着公里数的牌子,知道没有多远了。最后10公里我才真切的感受到skins衣服的好处,我停下来走的时候,身上都是热的一点也不会觉得冷,跑动中也不会有汗在身上的感觉。
 最后100米,终于快到了,突然开始慢慢加速,整个身体都轻了起来,越跑越快,没想到最后我还能有这种速度,不过我跑太快了,老胡相机没有跟上啊,应该录像的,太悲剧了。最后成绩4小时16分。
赛后:
 其实回去的路才是最艰难的啊,没有比赛号码的人是进不了场地的,我就只拿到一件羽绒服,还没有穿裤子,裤子在小夏手里,他还没有走回来,我就一瘸一拐走了好久才到地铁站,从来没有想过原来有这么远。后来在北土城和他们汇合,才穿上裤子。 回去我就先喝了一个甜粥一个咸粥一杯豆浆,吃了不少水果,肚子一直没有饱的状态啊。最悲剧的是,我住的地方在6层是没有电梯的。想想这几天我就得这样上上下下就心理抖了下。
 我的第一次马拉松,我并没抱什么目标,也就是一种参与的心态,不过比我想象中还是好多了。而且各种准备都是必需的,这次我唯一没准备好的就是我的mp3和袜子,让我磨出了不少水泡。写这篇日志也就是纪念下我的第一次,多年以后还可以回顾下我的第一次是怎么过来的,哈哈,也是别有一番味道。
 有人跟我说,你为什么一定要跑呢,你这是自残,你这是没有必要的。其实我本身一直很喜欢奔跑的感觉,只有奔跑可以让我感受到血液还在我的身体流躺,奔跑让我追赶了很多东西,也让我度过那些最难过的时刻。做任何事,我一直都觉得自己并不是最聪明的,我的智商也不高,但我认定的事情我就会坚持去完成,我赢得的东西很多都是我坚持得来的。我以后还会继续,不管做什么事。
 
PS::这篇文章差点要重写,删除了,全没了,好不容易从系统的历史中找回来的,不知道qzone能不能通过,也不知道是什么敏感的关键词。

《Go语言编程》第五章完整示例修改版

作者:Ajian 发布时间:October 26, 2012 分类:Golang

      最近一直在看《Go语言编程》这本书,书的结构和内容都是很不错的,可惜小毛病不少,而且可能不太适合编程初学的人学习,我的编程功底不高,加上之前对于C C++类的语言写得较少,所以也看得挺费劲的。第五章的完整示例是一个不错的学习例子,层层递进,讲得很不错。最后的示例代码可能多种原因,并不能直接的使用,现在进行了修改可以使用,动静分离的还没有测试,这个例子还在丰富,做一个小相册出来玩玩。

下面是具体的示例,

具体的FAQ看 http://sf.com  http://segmentfault.com/q/1010000000129720  有本书的作者进行解答。

package main

import (
    "io"
    "os"
    "log"
    "net/http"
    "io/ioutil"
    "html/template"
    "path"
    "strings"
    "runtime/debug"
)

const(
    UPLOAD_DIR = "./uploads"
    TEMPLATE_DIR = "./views"
    ListDir= 0x0001
)

var templates = map[string]*template.Template{}

func init(){
    fileInfoArr,err := ioutil.ReadDir( TEMPLATE_DIR )
    if err != nil {
        panic( err )
        return
    }
    var templateName,templatePath string 
    for _,fileInfo := range fileInfoArr{
        templateName = fileInfo.Name()
        if ext := path.Ext( templateName);ext != ".html" {
            continue
        }
        templatePath= TEMPLATE_DIR + "/" +templateName
        log.Println( "Loading template:",templatePath )
        t := template.Must( template.ParseFiles( templatePath))
        tmpl := strings.Split( templateName,".html" )[0]
        templates[tmpl] = t
    }
}

func check( err error ){
    if err!=nil{
        panic( err )
    }
}

func renderHtml( w http.ResponseWriter,tmpl string,locals map[string]interface{}) ( err error) {
        err = templates[tmpl].Execute( w,locals )
        check( err )
        return
}

func isExists( path string ) bool {
    _,err := os.Stat( path )
    if err == nil {
        return true
    }
    return os.IsExist( err )
}

func uploadHandler( w http.ResponseWriter,r *http.Request ){
    if r.Method == "GET" {
        err := renderHtml( w,"upload",nil )
        check( err )
//        io.WriteString( w,"<html><body><form method=\"POST\" action=\"/upload\" enctype=\"multipart/form-data\">"+
//        "Choose an image to upload:<input name=\"image\" type=\"file\" />"+
//        "<input type=\"submit\" value=\"Upload\" />"+
//        "</form></body></html>")
        return
    }

    if r.Method == "POST" {
        f,h,err := r.FormFile( "image" )
        check( err )
        filename := h.Filename
        defer f.Close()
        t,err := os.Create( UPLOAD_DIR + "/" + filename  )
        check( err )
        defer t.Close()
        _,err = io.Copy( t,f )
        check( err ) 
        http.Redirect( w,r,"/view?id="+filename,
        http.StatusFound)
    }
}

func viewHandler( w http.ResponseWriter,r *http.Request ){
    imageId := r.FormValue( "id" )
    imagePath := UPLOAD_DIR + "/" +imageId
    if exists := isExists( imagePath );!exists{
        http.NotFound( w,r )
        return
    }
    w.Header().Set( "Content-Type","image/png" )
    http.ServeFile( w,r,imagePath )
}

func listHandler( w http.ResponseWriter,r *http.Request){
    fileInfoArr,err := ioutil.ReadDir( "./uploads" )
    check( err )
    locals := make( map[string]interface{})
    images:=[]string{}
    for _,fileInfo := range fileInfoArr{
        images = append( images,fileInfo.Name() )
    }

    locals["images"] = images
    err = renderHtml( w,"list",locals )
    check( err )
//    t,err:=template.ParseFiles( "list.html" )
//    var listHtml string
//    for _,fileInfo := range fileInfoArr{
//        imgid := fileInfo.Name()
//        listHtml += "<li><a href=\"/view?id="+imgid+"\">"+imgid+"</a></li>"
//    }
//    io.WriteString( w,"<html><ol>"+listHtml+"</ol></html>" )
}

func safeHandler( fn http.HandlerFunc ) http.HandlerFunc{
    return func( w http.ResponseWriter,r *http.Request ){
        defer func(){
            e := recover()
            if err,ok:= e.(error);ok{
                http.Error( w,err.Error(),http.StatusInternalServerError )
                log.Println( "WARN: panic in %v. - %v",fn,err )
                log.Println( string( debug.Stack() ) )
            }
        }()
        fn( w,r )
    }
}

func staticDirHandler( mux *http.ServeMux,prefix string,staticDir string,flags int ){
    mux.HandleFunc( prefix,func( w http.ResponseWriter,r *http.Request) {
        file := staticDir + r.URL.Path[len( prefix )-1:]
        if( flags & ListDir )== 0{
            if exists := isExists( file );!exists{
                http.NotFound( w,r )
                return
            }
        }
        http.ServeFile( w,r,file )
    })
}

func main(){
    mux := http.NewServeMux()
    staticDirHandler( mux,"/assets/","./public",0 )
    mux.HandleFunc("/",safeHandler(listHandler))
    mux.HandleFunc("/view",safeHandler(  viewHandler ))
    mux.HandleFunc("/upload",safeHandler( uploadHandler ))
    err := http.ListenAndServe( ":8080",mux )
    if err != nil {
        log.Fatal( "ListenAndServe: ",err.Error() )
    }
}

[Shell]服务器信息收集与整理输出wiki和excel

作者:Ajian 发布时间:August 28, 2012 分类:Shell

   前言:服务器信息的收集是认识你的工作环境的第一步,有了服务器的相关信息就知道如何去分配他们,更好的取舍,发挥每一台服务器的优点。之前一直有不同服务器信息收集脚本,最近又做了一次修改,主要采用awk,减少了各种管道和中间的过程,并且尽量的可以智能匹配,还有update wiki(redmine)和excel和输出更好的进行整理和对比。

Notice:由于脚本修改比较快,很多awk里面的变量没有什么规范,有时间再去整理吧,如果你对awk使用很熟练的话不会有什么问题的,真心发现awk越用越简单,使用了很多awk的特性,也发现awk不同版本造成的问题,像脚本中有一段是awk 4 支持关联数组 而awk 3不支持。就当是一次awk的脚本练习。

PS:最早期的脚本可见 http://www.ohlinux.com/archives/331/ 

服务器信息收集脚本 

ServerInfo_wiki_v2.sh

#!/bin/bash 
LANG=C

echo -e "{{>toc}} \n"

if [ ! `which dmidecode` ] || [ ! -e /usr/sbin/dmidecode ] ;then
if [ `which yum`];then yum -y install dmidecode > /dev/null 2>&1
else
echo "Please install dmidecode at first!! Exit."
exit
fi fi #OS Information if [ -e /etc/slackware-version ];then OS=`cat /etc/slackware-version | head -1` elif [ -e /etc/debian_version ]; then OS="Debian `cat /etc/debian_version`" elif [ -e /etc/redhat-release ]; then OS=`cat /etc/redhat-release` elif [ -e /etc/SuSE-release ]; then OS=`cat /etc/SuSE-release |head -n1` elif [ -e /etc/gentoo-release ]; then OS=`< /etc/gentoo-release` elif [ -e /etc/issue ]; then OS=`cat /etc/issue | head -1` elif [ -z $OS ] ;then OS='unknown' fi echo " h2. Base Infomation |_. Hostname | `/bin/hostname`|" #network Information /sbin/ifconfig -a | awk 'BEGIN{ in_section=0 end=1 }{ if (!end){ if (in_section){ if ( $0 ~ /^$/ ){ end=1 }else{ if ($0 ~ /inet addr:/){ split($2,ip,":") net=net""nic":"ip[2]" " } } } }else if (!($0 ~ /^ / || /lo/)){ end=0 in_section=1 nic=$1 } }END{ print "|_. Network |",net,"|" }' echo "|_. System kernel | `/bin/uname -sr`| |_. OS Name | $OS | |_. OS bit| `/bin/uname -m`|" #CPU Information cat /proc/cpuinfo | awk -F\: \ -v systembit=`/bin/uname -m` \ '{ if ($0 ~ /processor/){ cpucore++ } if ($0 ~ /model name/){ cputype=$2 } if ($0 ~ /physical id/){ cpuphy[$2]++ } if ($0 ~ /flags/){ if ($2 ~ /lm/){ cpubit=64 }else if ($2 ~/pm/){ cpubit=32 }else if($2 ~ /rm/){ cpubit=16 }else if (systembit ~ /i386|i586|i686/){ cpubit=32 }else{ cpubit=systembit } } }END{ cpu_phy=length(cpuphy) if (cpu_phy == 0 ){ cpu_phy=1 } print "|_. CPU Bit|",cpubit,"|" print "|_. CPU Type|",cputype,"|" print "|_. CPU Num|",cpu_phy,"|" print "|_. CPU Core|",cpucore,"|" }' #for awk above 4 version ,about dmidecode Information #/usr/sbin/dmidecode | awk -F\: 'BEGIN{ # in_section=0 # end=1 # num=1 # area["System Information"]="Product Name:,Manufacturer:" # area["Memory Device"]="Type:,Size:" # }{ # if (!end){ # if (in_section){ # if ( $0 ~ /^$/ ){ # end=1 # }else{ # for (k in info){ # if ( $0 ~ info[k] ){ # key=areainfo" "info[k] # if ( key in result) { # if ($2 in result[key]){ # result[key][$2]++ # }else{ # result[key][$2]=1 # } # }else{ # result[key][$2]=1 # } # } # } # } # } # }else if ($0 in area ){ # end=0 # in_section=1 # areainfo=$0 # split(area[$0],info,",") # } #}END{ # for (row1 in result){ # row3="" # for (row2 in result[row1]){ # if (result[row1][row2] > 1){ # row3=row3" "row2"*"result[row1][row2] # }else{ # row3=row3" "row2 # } # } # print "|_. "row1,"|",row3,"|" # } #} #' #for awk 3 version ,about dmidecode Information /usr/sbin/dmidecode | awk -F\: 'BEGIN{ in_section=0 end=1 num=1 area["System Information"]="Product Name:,Manufacturer:" area["Memory Device"]="Type:,Size:" }{ if (!end){ if (in_section){ if ( $0 ~ /^$/ ){ end=1 }else{ for (k in info){ if ( $0 ~ info[k] ){ key=areainfo" "info[k]"|"$2 if ( key in result) { result[key]++ }else{ result[key]=1 } } } } } }else if ($0 in area ){ end=0 in_section=1 areainfo=$0 split(area[$0],info,",") } }END{ for (key in result){ split(key,row,"|") if (row[1] in arr){ if (result[key] > 1){ arr[row[1]]=arr[row[1]]" "row[2]"*"result[key] }else{ arr[row[1]]=arr[row[1]]" "row[2] } }else{ if (result[key] > 1){ arr[row[1]]=row[2]"*"result[key] }else{ arr[row[1]]=row[2] } } } for (k in arr){ print "|_.",k,"|",arr[k],"|" } } ' #Disk Information df -hPT -x tmpfs -x devtmpfs -x rootfs | awk '{ if($0 ~ /dev/){ disk=disk""$1"=>"$7"=>"$3" " } }END{ print "|_. Disk |",disk,"|" }' echo #Show Hard_Info echo -e "h2. Filesystems \n" df -hPT -x tmpfs -x devtmpfs -x rootfs | awk '{print "|" $1 " |" $2 " |" $3 " | " $6 " | " $7 " |"}' echo #IDE devices information echo -e "h2. IDE devices \n" if [ "$(ls -1d /proc/ide/hd* 2> /dev/null)" ]; then for DEV in `ls -1d /proc/ide/hd* |sed 's/.*\///'` do MODEL=`cat /proc/ide/$DEV/model` if [ -e /proc/ide/$DEV/capacity ]; then SIZE=`cat /proc/ide/$DEV/capacity` SIZE=`expr $SIZE / 2097152` else if [ -e /sys/block/$DEV/size ]; then SIZE=`cat /sys/block/$DEV/size` SIZE=`expr $SIZE / 2097152` else SIZE='(unknown)' fi fi echo "| /dev/$DEV | $MODEL | $SIZE GB |" done fi echo #SCSI devices infomation if [ "$(ls -1d /sys/block/sd* 2> /dev/null)" ]; then echo -e "h2. SCSI devices \n" echo "| devices |_. Model |_. Size |" for DEV in `ls -1d /sys/block/sd* |sed 's/.*\///'` do MODEL=`cat /sys/block/$DEV/device/model` SIZE=`cat /sys/block/$DEV/size` SIZE=`expr $SIZE / 2097152` echo "| /dev/$DEV | $MODEL | $SIZE GB |" done fi echo #open port and services #notice need root permission echo -e "h2. Open Port and Serivce \n" /bin/netstat -tln | awk '{ if($0 ~ /^tcp/){ split($4,port,":") num=length(port) cmd="lsof -i :"port[num] while(( cmd | getline foo ) > 0 ){ if(!(foo ~ /^COMMAND/ )){ split(foo,ccc," ") abc[port[num]]=ccc[1]" "abc[port[num]] } } close(cmd) } }END{ print "| Port | Service|" for (key in abc){ value="" split(abc[key],com," ") for ( a in com){ uniqcmd[com[a]]++ } for (b in uniqcmd){ value=b"*"uniqcmd[b]" "value } delete uniqcmd print "|",key,"|",value,"|" } print "" }' function grep_towiki(){ if [ -f $1 ];then echo -e "h3. $1 \n" echo "<pre>" /bin/egrep -v "^#|^$" $1 echo "</pre>" echo fi } echo -e "h2. Auto Start \n" grep_towiki /etc/rc.local echo -e "h3. chkconfig \n" echo "<pre>" /sbin/chkconfig --list |awk '{if ($0 ~ /3:on/){print $1}}' echo "</pre>" echo echo -e "h2. Crond Tab \n" for file in /var/spool/cron/* ;do grep_towiki $file done echo -e "h2. System Kernel File \n" grep_towiki /etc/sysctl.conf echo -e "h2. Rsync Config \n" grep_towiki /etc/rsyncd.conf

更新redmine wiki 

批量更新redmine的服务器信息 结合pssh

#!/bin/bash 
#shell import wiki
#need bash
author_id=3
wiki_id=6
protected=0
default_page_id=215
log_dir=/tmp/serversout
hostlist=$1

export PATH=/usr/kerberos/sbin:/usr/kerberos/bin:/usr/local/sbin:/usr/local/bin:/sbin:/bin:/usr/sbin:/usr/bin:/root/bin:/usr/local/bin:/usr/local/webserver/mysql/bin

pssh -t 600 -h $hostlist -l root -o $log_dir "bash /home/sh/ServerInfo_wiki_v2.sh"

SQL()
{
mysql -h192.168.1.253 -uUser -pPassword redmine <<EOF
$1
EOF
}


for ip in `cat $hostlist | grep -v "#"`
do
    title=`echo $ip | sed 's/\.//g'`
    text=`cat $log_dir/$ip | awk '{printf($0"\\n");}'`
    updated_on=`date +%Y"-"%m"-"%d" "%k":"%M:"%S"`

    wiki_page_select="select id from wiki_pages where title='$title';"

    echo $wiki_page_select

    page_id=`echo $(SQL "$wiki_page_select") | awk '{print $2}'`

    #echo $page_id

    if [ ! -z $page_id ] ;then

        wiki_content_id=$page_id

        wiki_contents_update_SQL="update wiki_contents set text='$text',updated_on='$updated_on' where page_id=$page_id "

        wiki_version_select="select version from wiki_content_versions where page_id=$page_id"

        version=`echo $(SQL "$wiki_version_select") | awk '{print $NF+1}'`

        wiki_versions_insert_SQL="insert into wiki_content_versions values('','$wiki_content_id','$page_id','$author_id','$text','','','$updated_on','$version')"

        #deBug
        #echo $wiki_contents_update_SQL
        #echo $wiki_versions_insert_SQL

        SQL "$wiki_contents_update_SQL"
        SQL "$wiki_versions_insert_SQL"

        echo "[INFO] $ip is updated "

    else

        version=1
        wiki_pageid_select="select page_id from wiki_contents where id=(select max(id) from wiki_contents); "
        default_page_id=`echo $(SQL "$wiki_pageid_select") | awk '{print $2}'`

        ((default_page_id=${default_page_id}+1))

        wiki_content_id=$default_page_id
        echo content_id=$wiki_content_id

        #insert wiki_page
        wiki_page_SQL="insert into wiki_pages values('','$wiki_id','$title','$updated_on','$protected',NULL)"

        #insert wiki_contents
        wiki_contents_SQL="insert into wiki_contents values('','$default_page_id','$author_id','$text','','$updated_on','$version')"

        #insert wiki_content_versions
        wiki_content_versions_SQL="insert into wiki_content_versions values('','$wiki_content_id','$default_page_id','$author_id','$text','','','$updated_on','$version')"


        #deBug
        #echo $wiki_page_SQL
        #echo $wiki_contents_SQL
        #echo $wiki_content_versions_SQL

        SQL "$wiki_page_SQL"
        SQL "$wiki_contents_SQL"
        SQL "$wiki_content_versions_SQL"

        echo "[INFO] $ip is inserted "
    fi
done

执行 bash servers_to_wiki_mysql.sh /tmp/cn.list

 该脚本可以新建也可以更新redmine wiki中的服务器信息, 但一定要注意参数变量的替换 不然会破坏原有的redmine哦

output wiki

 

输出excel格式

如果是服务器信息对比这样看wiki也是挺累的,可能你比较习惯用excel的格式进行排序尤其是大量服务器的时候。

我们再将输出的数据转换成excel来进行对比查看。

#!/bin/bash 
#shell import excel
#need bash
log_dir=/tmp/serversout
hostlist=$1
outexcel=$2

#export PATH=/usr/kerberos/sbin:/usr/kerberos/bin:/usr/local/sbin:/usr/local/bin:/sbin:/bin:/usr/sbin:/usr/bin:/root/bin:/usr/local/bin:/usr/local/webserver/mysql/bin

#pssh -t 600 -h $hostlist -l root -o $log_dir "bash /home/server/code/ServerInfo/ServerInfo_wiki_v2.sh"

#print title 
for ip in  `grep -v "#" $hostlist | head -1` 
do
    cat $log_dir/$ip | awk -F\| \
        -v out=$outexcel \
        '{
     if($0 ~ /^\|_./){
         split($2,ti,"_.")
        printf "%s|",ti[2] > out
    }
    
}'
done
echo  >> $outexcel
for ip in `grep -v "#" $hostlist`
do
    cat $log_dir/$ip | awk -F\|  \
    -v out=$outexcel \
    '{
    if($0 ~ /^\|_./){
        info[row1]=info[row1]$3"|"
    }
}END{
    for (key in info){
        print key""info[key] >> out
    }
}'
    done

执行 bash servers_to_excel.sh /tmp/cn.list /tmp/cn.xls

得到如下列表 这样就很方便的进行比较和取舍了。PS:打开cn.xls 使用 | 为分割符就可以了。

output excel

 

Shell: 管理相片和视频的脚本

作者:Ajian 发布时间:June 20, 2012 分类:Shell

  有时需要修改大量的相片或者视频,就会写点小脚本进行批量的处理,没有太整理,像有批量下载,批量修改后缀,视频格式转换。今天处理的时候用了这两个脚本,不注意的时候放在目录里面都快找不到了。

脚本一:

相片的后缀修改,像我的松下LX5保存的相片为大写的JPG,可是很多网站上传都不知道大写的,我就郁闷,多匹配一个大写的会需要多少代码。只好自己修改了。将后缀的大写转换为小写

#!/bin/sh
#basename changesuffix.sh
##change the file suffix [A-Z] to [a-z]
dir=$1

for a in `find $dir -type f -name "*.*"`
do
 suffixname=`echo $a | awk -F. '{print $NF}'`
echo $suffixname
 fsuffixname=`echo $suffixname | tr "[A-Z]" "[a-z]"`
echo $fsuffixname
 holdname=`echo $a | awk -F. '{print $1}'`
echo $holdname
if [ $suffixname != $fsuffixname ];then
echo "change the $a"
mv $a $holdname.$fsuffixname
fi
done

脚本二:

我在You(你明白的)tube上下载了大量的MP4,想放到MP3里面听听,而且传输也要小很多,默认的MP4很高清体积很大。弄个批量转换的相当不错。

#!/bin/bash
srcDir=/root/Videos/Music
desDir=/root/MP3

cd $srcDir
for file in *.mp4 
do 
    filename=`echo "$file" | awk -F'.mp4' '{print $1}'`
    if [ ! -e  $desDir/"$filename".mp3 ];then
        ffmpeg -i "$file" -f mp3 -ab 192000 -vn $desDir/"$filename".mp3
    fi
done

脚本都是应需求很快写的,很简单没有格式没有扩展,还有些现在找不到了,哈哈,哪天看到了再说。