最近两个月都沉迷于shell脚本中,这从博客更新就看得出来。
开始是延时播入vpn的脚本,它解决了开机时网络不通的情况下播入vpn的问题。理论上用/etc/network/interfaces配置文件也应可以完成,但我设置了if-up还是有问题,所以就转而考虑shell脚本。
第二个shell脚本是用于中文内码转换的。平时下载得到txt文件大多是gbk编码的,但使用统一的utf8必将更加方便。iconv可以完成这个工作,但它每次只能对一个文件进行处理,显然增加了我的工作量。于是我利用脚本,对通配符进行循环并配合上tellenc对输入文件的内码进行猜测。现在的问题是tellenc的结果不一定很准确,这是只根据前10行进行猜测造成的。可能我会在这方面加入更多硬编码的干预,或者写一个更强大的tellenc来准确的得到编码。
然后就是Google离开中国时写下的一个监控工具。也就是不断的通过域名解析,ping,首页分析,反向dns等方法来观察gfw什么时候,用什么方式对Google下手。这个脚本经过几次强化已经比较完善,稍微修改一下就可以对其他的站点进行同样的监控。
还有一个脚本是用于满足我下列需要:在Apache的.htaccess文件中添加和更新若干Allow From XXX.XXX.XXX.XXX,其中XXX.XXX.XXX.XXX应该是指定的动态域名的ip。在写这个脚本的过程中,我学习到了sed的复杂用法。需要面对的是Apache配置文件的注释风格——只有行首的#被认为是注释的开始。因此我需要在每一个Allow From的上一行加上一个动态域名的md5用于识别,sed将替换掉这个md5的下一行,sed -e “/$md5/N” -e “/$md5/c# $domain : $md5\nAllow From $ip”。
还有一个小作品和这个主机分享计划的发起者Michael(bemike.org)有那么一点关系。和他在msn上的聊天中我猜测他有那么一个工具能够截屏并上传到图片分享网站。这很是让人羡慕Mac软件的优秀。于是我写了一个shell脚本来完成同样的事情:scrot用来截取屏幕,yfrog的python api将图片上传,notify-send将url在屏幕上显示,xclip用于将url复制到剪切板。最后,我还用Compiz把PrtScn,Alt+PrtScn都绑定到了这个脚本上。
最终章用于满足我下载的需求——登录到路由器上检查是否有其他电脑接入了网络。然后根据这一点来控制打开和关闭amuled。既不影响上网网速,又最大程度的利用网络,如果路由器能够对流量就进行统计就更好了。
小礼物:bash tips,如果有疑问的话请请先看这个视频。
预告:shell脚本暂时告一段落,下面Python脚本和Go语言即将登台演出。
Post by : cooper
Post under : Coding, bash, linux, script, shell
on February 1st, 2010 | No Comments »
Google正要离开中国。
计划今天晚上去来福士16楼为Google献上一束鲜花。
Audio clip: Adobe Flash Player (version 9 or above) is required to play this audio clip. Download the latest version here. You also need to have JavaScript enabled in your browser.

Flowers for Google
此外,还特意写了一个bash脚本来记录下这一切。以一个程序员的方法来纪念。
#!/bin/bash
export PATH="/bin:/usr/bin"
LOG=~/google.log
TMP=/tmp/google.index.html
FMT="+%Y-%m-%d %H:%M:%S"
HOST=www.g.cn
NS=202.96.209.5
while [ 1 ]
do
date "$FMT" | tee -a $LOG
ips=`dig @$NS $HOST | sed -n -r 's/^.*IN\s+A\s+(.*)$/\1/p'`
if [ -n "$ips" ]
then
for ip in $ips
do
wget -O $TMP $ip > /dev/null 2> /dev/null
google=`cat $TMP | sed -n -r "s/^.*Google.*$/OK/p" \
| sed -n -r '1p'`
if [ -n "$google" ]
then
echo "$ip OK" | tee -a $LOG
else
echo "$ip ERROR" | tee -a $LOG
fi
done
else
echo "Can't resolve the host: $HOST" | tee -a $LOG
fi
sleep 2
done
Updated on 15th Jan 2010:
升级了一下脚本,使得: 1.通过反向解析检测Google是否遭到域名劫持; 2. 支持同时检测多个Google旗下的域名.
#!/bin/bash
export PATH="/bin:/usr/bin"
LOG=~/google.log
TMP=/tmp/google.index.html
FMT="+%Y-%m-%d %H:%M:%S"
GOOGLE_DOMAINS=("www.g.cn" "www.google.cn" "www.google.com")
NS=202.96.209.5
while [ 1 ]
do
date "$FMT" | tee -a $LOG
for domain in ${GOOGLE_DOMAINS[@]}
do
echo $domain | tee -a $LOG
ips=`dig @$NS $domain \
| sed -n -r 's/^.*IN\s+A\s+(.*)$/\1/p'`
if [ -n "$ips" ]
then
for ip in $ips
do
server=`nslookup -q=ptr $ip \
| sed -n -r 's/^.*name = (.*)$/\1/p'`
is_server_1e100=`echo $server \
| sed -n -r 's/^.+\.1e100\.net\./OK/p'`
if [ "$is_server_1e100" = "OK" ]
then
wget -O $TMP $ip > /dev/null 2> /dev/null
is_google=`cat $TMP \
| sed -n -r "s/^.*Google.*$/OK/p" | sed -n -r '1p'`
if [ -n "$is_google" ]
then
echo "$ip OK" | tee -a $LOG
else
echo "$ip ERROR: NOT GOOGLE PAGE" | tee -a $LOG
fi
else
echo "$ip ERROR: DONAME HIJACK" | tee -a $LOG
fi
done
else
echo "ERROR: STOP RESOLVE: $domain" | tee -a $LOG
fi
done
echo "" | tee -a $LOG
sleep 2
done
Post by : cooper
Post under : Coding, Talking, bash, GFW, Google, linux, script, shell
on January 13th, 2010 | No Comments »
Notice : The music in the above article is offered just for trial, and not published under the general license of this blog.
I tied to study the shell script a few times. But on that time, I didn’t get enough knowledge to deal with it. Now, I’m back.
Situation 1
I want to startup the vpn service when the computer startup. I added pon vpn_name to rc.local. However, this can be failed because when this line execute, the network may not be ready. So I decide to write a script to do this. It will wait until the Internet up. Here’s it.
#!/bin/bash
sleep_time=1
export PATH=$PATH:/usr/bin
while [ 1 ]
do
ping_success=`ping -c 1 -n vpn.yegong.net | \
sed -n -r 's/^.* (.) received.*$/\1/p'`
if [ $ping_success -eq 1 ]
then
pon yegong
exit 0
fi
sleep $sleep_time
sleep_time=$(expr $sleep_time + 1)
done
- export PATH is very important.
- `ping -c 1 -n vpn.yegong.net | sed -n -r ’s/^.* (.) received.*$/\1/p’`, using ` surround the command to get the output text.
- sed -n -r ’s/^.* (.) received.*$/\1/p’, using sed to simplify the output. It’s the regular expression. Very similar with VIM replace syntax, isn’t it?
- if [ $ping_success -eq 1 ], [ condition ] means the test program, equivalent to test condition, so man test will show more usage.
- sleep_time=$(expr $sleep_time + 1), it seems that every variable in shell is a string, so you can’t simply write x=x+1. Instead of, expr program read a string expression and output the results. Please notice the space in the expression.
Situation 2
For each text files in a directory, convert the file encoding to utf8.
There’s a simple util can guess the file encoding. It can be found at Wu Yongwei’s Programming Page (Can’t access when I write the article). Then I just need a script to combine the tellenc and iconv.
TMP_FILE="/tmp/utf8lize.output"
ENCODING="utf-8"
if [ $# == 0 ]
then
echo "Usage: utf8lize FILES"
exit 1
fi
for f in "$@"
do
if [ -f "$f" ]
then
enc=`tellenc "$f"`
if [ $enc != $ENCODING ] && [ $enc != "binary" ]
then
echo $f : $enc
cp "$f" "$f.bak"
iconv -f "$enc" -t "$ENCODING" -o "$TMP_FILE" "$f"
cp "$TMP_FILE" "$f"
rm -f "$TMP_FILE"
fi
fi
done
- $# results the number of arguments when it been executed.
- for f in “$@” is the for-each loop. And “$@” indicates the all program arguments. In addition, when you run the program utf8lize *, * will convert to filenames array. Using the ” to surrounding $@ can deal the filename with space.
Post by : cooper
Post under : Coding, bash, linux, script, study, tutorial, 笔记
on December 15th, 2009 | No Comments »
作为一款历史悠久的编辑器,VIM拥有数量众多的脚本插件。山多出杂木,人多出怪物,今天我就遇到一个比较雷人的插件vimim。
这名字就够神奇,如果把它写成VimIM的话,就容易理解多了。这正是一个给Vim提供输入法的插件。按作者的说法,输入汉字再也不需要操作系统了,只要能显示,就能在Vim中输入。换作Emacs,倒还是可以考虑一下。现在这种状况,发一封邮件难道还要复制粘贴……确实是很囧
Post by : cooper
Post under : Coding, Emacs, plugin, script, VIM, vimim, 脚本, 输入法
on February 6th, 2009 | 1 Comment »
曾经写过一个VIM的时间戳脚本,用于自动在源代码文件中添加和更新时间戳,也就是Last Change的注释。前段时间重新写.vimrc,把这个脚本又完善了一下,下载请点。
PS. 最近VIM又学到不少技巧。觉得最有用的:!grep可以把visual模式下选中的行用grep工具过滤。其次可以把ii设置成命令模式和插入模式的开关。少了遥远的<Esc>效率高好多,就算不清醒,这个命令也基本上是无害的。
function! TimeStamp(...)
let sbegin = ''
let send = ''
if a:0 >= 1
let sbegin = a:1.' '
endif
if a:0 >= 2
let send = ' '.a:2
endif
let pattern = sbegin . 'Last Change: .\+'
\. send
let pattern = '^\s*' . pattern . '\s*$'
let row = search(pattern, 'n')
let now = strftime('%Y-%m-%d %H:%M:%S',
\localtime())
let now = sbegin . 'Last Change: '
\. now . send
if row == 0
call append(0, now)
else
call setline(row, now)
endif
endfunction
au BufWritePre _vimrc,*.vim call TimeStamp('"')
au BufWritePre *.c,*.h call TimeStamp('//')
au BufWritePre *.cpp,*.hpp call TimeStamp('//')
au BufWritePre *.cxx,*.hxx call TimeStamp('//')
au BufWritePre *.java call TimeStamp('//')
au BufWritePre *.rb call TimeStamp('#')
au BufWritePre *.py call TimeStamp('#')
au BufWritePre Makefile call TimeStamp('#')
au BufWritePre *.php
\call TimeStamp('<?php //', '?>')
au BufWritePre *.html,*htm
\call TimeStamp('<!--', '-->')
Post by : cooper
Post under : Coding, script, VIM, 下载, 脚本
on November 11th, 2008 | 2 Comments »