Dnsmasq设置简介

说是简介其实也不想详细介绍, 具体官网上都有, 一搜便知. 这里只是简单地罗列下常用配置, 以供参考.

#不读取/etc/resolv.conf文件
no-resolv

#不扫描/etc/resolv.conf和/etc/dnsmasq.conf文件的改动,如果有改动直接重启程序即可
no-poll

#设置dns服务器
server=8.8.8.8

#指定*.domain.name用8.8.8.8解析
server=/domain.name/8.8.8.8
注意不是server=/*.domain.name/8.8.8.8

#解析*.domain.name到127.0.0.1
address=/domain.name/127.0.0.1

#无效的DNS服务器, 用于反DNS劫持
bogus-nxdomain=127.0.0.1

下列一个典型的配置文件, 用于tomato, 要使其生效请开启截获DNS端口.

#覆盖掉原有DNS设置
no-resolv

#对baidu.com及其子域名使用中国电信的DNS
server=/baidu.com/218.2.135.1

#对其它的域名使用Google DNS
server=8.8.8.8
Advertisement

C#控制台输出实时重定向

.Net Framework中的Process类和ProcessStartInfo类可以方便地控制进程的启动, 还可以方便地将控制台程序的输出重定向到Stream中, 然后显示到TextBox中或者记录到文件中. 不过要实时显示每一行的输出还得用点技巧, 方法如下.

启动进程前的准备.

//设置待启动程序的路径和要传递的参数
ProcessStartInfo info = new ProcessStartInfo(path, args));

//将标准输出流重定向, 需同时把UseShellExecute设置为false
info.RedirectStandardOutput = true;

//不使用操作系统外壳程序启动
info.UseShellExecute = false;

//不创建窗体
info.CreateNoWindow = true;

为了做到实时捕获, 需在进程结束前一直搜索输出流, 如有新的一行便读取并引发一个事件以让主程序窗体能够响应并将这行添加至TextBox.

if (process.Start())
{
    while (!process.HasExited)
    {
        string line = process.StandardOutput.ReadLine();
        if (line != null)
            OutputLineGet(line);
    }
    process.WaitForExit();
}

为了不让窗体假死, 将调用上述循环放至另一个的单独线程中.

public void Start()
{
    new System.Threading.Thread(new System.Threading.ThreadStart(this.StartConsoleProgram)).Start();
}


然后便是窗体响应该事件, 注意到是跨线程调用GUI, 需用委托.

public MainForm()
{
  InitializeComponent();

  //注册事件
  this.OutputLineGet += new OnOutputLineGetDelegate(MainForm_OutputLineGet);
}

public delegate void OnOutputLineGetDelegate(string line);
public event OnOutputLineGetDelegate OutputLineGet;

private void MainForm_OutputLineGet(string line)
{
    if (this.InvokeRequired)
    {
        this.Invoke(new OnOutputLineGetDelegate(MainForm_OutputLineGet), line);
    }
    else
    {
        txtLog.AppendText(line);

        //添加换行符
        txtLog.AppendText("rn");
    }
}

这样便能一行一行实时捕获输出了, 而且主程序也可以响应窗体消息不至于假死.

LilyBot

10.1期间写了LilyBot, 用来定时抓取教务网的最新通知和百合上特定板块的帖子, 然后生成RSS. 从此系版和教务网上的最新通知都可以统一抓到Google Reader中, 我等收不到飞信不用人人不逛BBS的人终于也可以与时俱进了><. 无奈10.1期间vps抽得厉害, 掉包率40%~80%, ping值能上4000ms, 根本没法ssh上去调试, 于是拖到了现在. 目前抓取目标如下:

1. 教务网通知;
2. 百合DII版;
3. 百合Pictures版;
4. 百合M_Academic版.

百合限制了单位时间内同一ip的连接数, 抓帖子内容比较慢, 这些抓一遍大概2min(其实应该能更快, 保险起见设置了抓一贴sleep(1)), 所以暂时就先抓这么多, 谁有需求我再加.

Firefox可以直接把RSS订阅到书签栏. Chrome有RSS Live Links扩展. IE也可以直接订阅, 而且还能同时在桌面小工具里显示.

教务网通知只抓了标题, 啥时有空把内容也抓了好了><~

jQuery实现滑动效果

最近网上似乎开始流行滑动效果, 比如说M$主页上的这个. 虽然M$的这个是为了配合Metro的主题, 但是滑动展示却确实广泛应用于各大网站的主页上. 网上实现滑动效果的js插件一抓一大把, 但是既然我们用了jQuery做Ajax, 何不想想jQuery框架内就能解决的方案.

解决大体思路是: 在一个wrapper div里放N个等大的sub div, 并列放置, 多余部分不显示, 滑动时改变各个sub div的水平位置即可实现slide. 当然为了做成"滑动", 要用到jQuery的.animate()方法(当然别的框架也可以).

并列放置一般来说是把每个sub div的float设成left, 不过float其实并不是并列排版的最佳方案, 因为sub div从wrapper中"浮"了出来不再属于wrapper, 造成wrapper包不住sub. 需在某处应用clear, 典型的方法是新建个空div应用clear: both. 这样做未免有点Hack的味道, 空的div也不容易理解.

另一个方法是将每个sub div的position设成relative, 然后将后一个的top设成-300px(如每个sub div高度为300px). 这里的top是相对于前一个div而言的, 所以后面第二个的top应设为-600px. 关于relative的排版参见这里.

CSS3中对于元素并列放置有更好的解决方案: display: inline-block. 允许像div这种块级元素拥有inline的特性. 强烈建议对于块级元素的并列排放使用inline-block而不是float.

我用了第二种方法(虽然事实上第三种方法更好), 不过怎么排版其实并不重要, 排成一排就行了.

对于wrapper, 用overflow: hidden隐藏多余的sub div.

向左滑动时, 在js中对所有sub div调用.animate({"left", "-=300px"}).
向右滑动时, 在js中对所有sub div调用.animate({"left", "+=300px"}).

未防滑过头, 滑动之前需判断是否已到底.

其它方法可能调用.animate()时渐变的属性略有不同, 相应调整即可. 不过.animate()可调的属性限于几个可以连续变化的数值属性, 具体可参阅jQuery的文档.

简言之, 选择一个合适的方法并列排版sub div, 遮掉多余部分, 滑动时左右调整位置, 就这么简单.

附: Source Code

Lake At Sunset

最近练车, 开去了昆承湖, 湖风吹着非常舒服, 等台风过了一定再去. 贴图4张, 手机渣画质.

PS: 本文顺便测试下colorbox插件, 非常靠谱, 在IE下没有fancybox的js错误问题. 另外wordpress自带的相册功能也非常不错, 可惜只能在自带的编辑器下插入, 回头试试能不能用CKeditor插入相册, 自带的编辑器插代码实在是不好用啊.

nginx泛二级域名配置

nginx有着非常强大的rewrite功能, 结合正则表达式可以定义非常灵活的泛二级域名.

假设/home/www中分别有company1/和company2/两个网站, 希望分别有各自的二级域名.

在nginx配置文件中使用如下语句即可分离出二级域名, 保存至变量$subdomain, 默认为company1.

set $subdomain company1;
if ( $http_host ~* "^(.*).archangelsdy.com$") {
    set $subdomain $1;
}

之后用root语句定位至对应的主目录.

root /home/www/$subdomain;

同样, fastcgi的转发也相应修改为:

fastcgi_param  SCRIPT_FILENAME  /home/www/$subdomain$fastcgi_script_name;

如上配置后, 对于某个二级域名便可重定向置/home中对应的目录. 显然, 用这种方便配置后, 以后添加二级域名只需要配置好域名解析并在/home中建立相应目录即可, 不需要修改nginx的配置文件也不需要重启nginx, 可批量添加二级域名三级域名等, 缺点是对于每个二级域名下的网站配置都是相同的.

双层SSH隧道研究

学校的内网无法直接出校, 需拨某VPN才能访问外网, 对外统一为一个ip. 然而最近由于那啥升级导致学校的国际出口及其不稳, 无法通过此VPN挂SSH proxy. 手头有一系服务器(Server A)对外有独立ip, 然而没有root权限, 基本上只能ls/cp/mv/rm/scp. 突然想到既然可以ssh上此服务器当然可以当成proxy出校, 而且由于独立ip基本没有对外访问的请求应该不至于触发某计数器, 于是尝试在此ssh tunnel中再与vps(Server B)构造一层tunnel.

由于没有root权限也改不了iptables, Server A自然只能当成ssh proxy出校用了, 在本地8000端口监听:

ssh -qTfnN -D 8000 user@server-a.com

尝试让本地的ssh请求走8000端口的proxy, 然而全局代理无效, 只能另想办法.

Google了一圈发现proxychains, 支持HTTP/SOCKS4/SOCKS5, 支持ssh/telnet/wget/ftp/apt/vnc/nmap等命令的转发, 再合适不过了.

直接apt-get装完, 编辑/etc/proxychains.conf如下, 具体可参照该文件内的注释:

dynamic_chain
chain_len=1
proxy_dns 
tcp_read_time_out 15000
tcp_connect_time_out 10000

[ProxyList]
socks5 	127.0.0.1 8000
socks4  127.0.0.1 8000

配置完后就可以在通过代理使用ssh了:

sudo proxychains ssh -qTfnN -D 7070 user@server-b.com

此后配置浏览器通过7070端口使用代理, 即可正常访问.

C++判断输入结束的讨论

先看2段代码:

[cpp title=”Method 1″]

int a;
while(cin>>a)
{
cout<<a<<endl;
}

[/cpp]

[cpp title=”Method 2″]

int a;
while(cin.good())
{
cin>>a;
cout<<a<<endl;
}

[/cpp]

乍一看, 两者似乎都能判断出输入结束, 然而, 当输入出现错误时, 看下列例子:

input:
1 2 a
output 1:
1
2
output 2:
1
2
2

第二种方法却多了一个输出. 仔细观察, 发现两者从输入流读取和判断结束的顺序存在不同:

Method 1:
从输入流读取->判断流的状态->输出->…
Method 2:
判断流的状态->从输入流读取->输出->…

当循环进行到第三次时, Method 1先进行读取, 发现’a’不满足int, 于是返回0, 跳出循环, 故有2次输出. 而Method 2 先进行判断, 由于此时刚刚成功读完第二个数据, 第三个还未读, 流的状态cin.good()为true, 故进入第三个循环, 尝试读入一个数, 发现’a’不满足int, 于是a的值不会被覆盖, a的值仍为2, 故又输出一个2. 之后由于刚才读取失败置cin.good()为false, 跳出循环.
可见, 用cin.good()判断输入结束是可能存在问题的, 需作如下修改:

[cpp title=”Method 3″]
int a;
cin>>a;
while(cin.good())
{
cout<<a<<endl;
}

[/cpp]

此时先进行读取再判断流的状态, 可以正常判断输入结束.

另外, 参考http://www.cplusplus.com的解释, 如下情况时cin.good()会被置false:

“The function returns true if none of the stream’s error flags (eofbit, failbit and badbit) are set.”

即eofbit, failbit, badbit中任何一个被触发即置cin.good()为false.
注意到cin.bad()并不是cin.good()的反面, 它只对应badbit.
关于这三个标志何时被触发有下表:

flag error
eofbit The end of the source of characters is reached during its operations.
failbit The input obtained could not be interpreted as an element of the appropriate type.

Notice that some eofbit cases will also set failbit.

badbit An error other than the above happened.

输入结束将导致eofbit和failbit, 输入类型不符将导致failbit, 其它将导致badbit.

吐槽: 这货害我在ZOJ上浪费了不下30次submit…

Acer 5935G 显卡折腾系列之二

黑屏…又黑屏…明明我什么都没干…我只是从Windows切到了Linux然后又切了回来…黑屏了- –

还是Logo后黑屏死机, 看来还是显卡的问题.

于是, 果断使出上回总结出的重启大法, 然后在重复按了N次电源开关后, 居然无效!

(拍桌)Windows里积了一个视频一个ppt明天要交差啊~怎么可以这么不给力啊~!

无奈, 进BIOS把显卡改成Integrated, Logo后冒出来个磁盘扫描, 直接Cancel了登陆成功.

不过Integrated的显卡没法用啊, 于是又重启换回Discrete, 黑屏- -…

无奈再改成Hyper SLI, 磁盘扫描又蹦了出来, 扫就扫吧, 扫完成功进入系统.

等等! 该不会就是这货吧?! 该不会就是这货让独显驱动死在那了吧?!

果断重启改成Discrete, 成功进入系统Orz…

感想:

卧槽以后扫个磁盘就得黑一次屏么- -那我硬盘岂不是C0蹭蹭蹭往上涨?!

(这次涨了2, 我用了一年多才15, Acer乃不能这么黑我啊啊啊…)

Acer 5935G 显卡折腾记

在虚拟机中用了3个月Ubuntu后, 终于忍不住想往硬盘里装了(我果然是命令行控?!).  为此, 需要解决2大矛盾:

1. 硬盘空间问题;

2. 显卡问题;

果断把Vista那个盘清了, 于是有了20G的空闲空间. 问题是这货还不能直接格式化或把分区删了, 因为bootmgr, 格了就没法引导了, 于是只能十分一个个文件夹慢慢删, 期间还有各种蛋疼权限问题, 不过这不是重点, 我只要划20个G出来就行了, 分区留着就留着好了, 当引导专区好了.

然后是显卡, Acer 5935G用的是GT240M+GMA4500 Hybrid SLI, 不知是当时混合SLI技术不成熟还是Insyde的BIOS太不给力这货用不了公版驱动, 只能用Acer官网上的开不了PhyX的渣驱动. 试想Windows下的驱动都仅此一种Linux下实在是不敢想象, 我可没那热情在Linux下折腾混合驱动. 欲练此功果然要先自废武功Orz, 果断进BIOS把显卡改成Discrete Graphic模式废掉了SLI, 然后进Windows, Logo后黑屏.

重启进安全模式, 黑屏. 640模式, 黑屏. 我可不想把Windows也重做一遍, 于是进BIOS改回来, 正常Log on.

卸掉nVidia驱动, 重启改成Discrete, 黑屏.

重启, 改成Integrated, 可以Log on. 分辨率不可调, 系统自动安装Intel驱动. 网上有人说这个是独显, 我还怀疑了下我的词汇水平, 试装N卡驱动, 压根显示没找到对应显卡= =… 我可不想废了独显用集显. 重启, 继续折腾.

改回Discrete, Logo后黑屏, 重启.

重启后提示我是否需要修复, 那就修修看吧, 然后30min后提示我无法发现问题修复失败= =.

重启, 对着硬盘灯发呆(之前Logo后硬盘灯直接灭了不动了), 等了半天居然一直在读! 然后蹦出来登陆界面……

原来, 电脑不需要修, 不断重启就好…

Log On之后安装公版驱动, 检测到显卡, 然后说由于系统正在安装硬件无法继续(搞不懂换个显卡而已怎么自动重装了一大堆驱动Orz…), 等了5s, 黑屏, Caps Lock无反应, 系统假死…

重启回来, 等系统把硬盘光驱读卡器统统装完, 顺利按上nVidia公版驱动, 提示重启(我看到这2个字都怕了= =).

进入桌面, 终于看到了nVidia控制面板, GPU-Z也显示PhyX开启, 显卡折腾宣告结束.

感想: 遇到问题先重启.