<?xml version="1.0" encoding="utf-8"?>
<rss version="2.0">
    <channel>
        <title>Blog ^A jianingy&apos;s</title>
        <link>http://blog.jianingy.com/</link>
        <description>A System Administrator With Programming Ability</description>
        <language>en</language>
        <copyright>Copyright 2008</copyright>
        <lastBuildDate>Tue, 22 Jul 2008 13:40:40 +0800</lastBuildDate>
        <generator>http://www.sixapart.com/movabletype/</generator>
        <docs>http://www.rssboard.org/rss-specification</docs>
        
        <item>
            <title>Mutt with multiple smtp server (让Mutt使用多个smtp服务器)</title>
            <description><![CDATA[<p>msmtp本身是支持多个msmtp的。这些smtp的可以通过mutt的set from='xxx'来选取。因此，mutt能否使用多个smtp的问题就等价于是mutt能否根据不同情况改变from的值。事实上，mutt的send hook整好可以用来解决这个问题。请看我的mutt配置文件</p>

<pre><code>set sendmail=&quot;/usr/bin/msmtp&quot;
set use_from=yes
set realname=&quot;Jianing Yang&quot;
set envelope_from=yes
set from=mycompany@email.com

send-hook '~f detrox@gmail.com' 'set from=detrox@gmail.com'
send-hook '~t detrox@gmail.com' 'set from=detrox@gmail.com'
send-hook '~t [^@]+@jianingy.com' 'set from=detrox@gmail.com'</code></pre>

<p>通过上面的配置，mutt在发送邮件时会根据如下条件改变from地址：</p>

<p>1.邮件来自detrox@gmail.com<br />
2.邮件是发往detrox@gmail.com<br />
3.邮件是发往@jianingy.com域的</p>]]></description>
            <link>http://blog.jianingy.com/2008/07/muttsmtp.html</link>
            <guid>http://blog.jianingy.com/2008/07/muttsmtp.html</guid>
            
                <category domain="http://www.sixapart.com/ns/types#category">Linux Application</category>
            
            
                <category domain="http://www.sixapart.com/ns/types#tag">email</category>
            
                <category domain="http://www.sixapart.com/ns/types#tag">msmtp</category>
            
                <category domain="http://www.sixapart.com/ns/types#tag">mutt</category>
            
            <pubDate>Tue, 22 Jul 2008 13:40:40 +0800</pubDate>
        </item>
        
        <item>
            <title>用xargs加速grep</title>
            <description><![CDATA[<p>xargs有个开关-P，意思是同时启动多少个子进程。借助xargs的这个特性可以加速grep文件的速度。例如，</p>

<pre><code>grep  -r &quot;libm.so.2&quot; *</code></pre>

<p>可以改写为</p>

<pre><code>find . -type f | xargs -n 1 -P 20 grep &quot;libm.so.2&quot;</code></pre>

<p>这样就会有20个进程同时查找了。</p>]]></description>
            <link>http://blog.jianingy.com/2008/07/xargsgrep.html</link>
            <guid>http://blog.jianingy.com/2008/07/xargsgrep.html</guid>
            
                <category domain="http://www.sixapart.com/ns/types#category">FreeBSD</category>
            
                <category domain="http://www.sixapart.com/ns/types#category">Linux Application</category>
            
                <category domain="http://www.sixapart.com/ns/types#category">System Administration</category>
            
            
                <category domain="http://www.sixapart.com/ns/types#tag">grep</category>
            
                <category domain="http://www.sixapart.com/ns/types#tag">xargs</category>
            
            <pubDate>Fri, 11 Jul 2008 21:04:11 +0800</pubDate>
        </item>
        
        <item>
            <title>彻底删除daemontools启动的服务</title>
            <description><![CDATA[<p>一直感觉删除一个daemontools启动的服务好麻烦。昨天strace了一下svscan和svc等程序，然后搞了个脚本专门来删这种服务。</p>

<p>具体细节请看: <a href="http://www.jianingy.com/killdaemontools.html">http://www.jianingy.com/killdaemontools.html</a></p>]]></description>
            <link>http://blog.jianingy.com/2008/06/daemontools-1.html</link>
            <guid>http://blog.jianingy.com/2008/06/daemontools-1.html</guid>
            
                <category domain="http://www.sixapart.com/ns/types#category">Bash Script</category>
            
                <category domain="http://www.sixapart.com/ns/types#category">System Administration</category>
            
            
                <category domain="http://www.sixapart.com/ns/types#tag">daemontools</category>
            
            <pubDate>Wed, 18 Jun 2008 10:12:04 +0800</pubDate>
        </item>
        
        <item>
            <title>罪恶的Admin(一): 调戏你的用户</title>
            <description><![CDATA[<p>作为罪恶的Admin，一定要有罪恶的脚本。当那个讨厌的用户又登录了你的server，不要pkill -9 -f "sshd: the_user". 如果你这么做了，那是粗鲁而不是罪恶。罪恶的admin要调戏(molest)他的用户。让我们发挥SIGSTOP和SIGCONT的威力吧。找到那家伙的sshd，kill -STOP，sleep 0.1，kill -CONT.让他的终端像9C的魔兽世界一样卡。从精神上打垮他。当然我们需要sleep的真实一些，让这看起来真的像网络故障。于是moluser脚本出现了:</p>

<pre><code>#!/bin/bash
# molest user by SIGSTOP and SIGCONT his sshd

GUY=&quot;$1&quot;
MAXSLEEP=&quot;$2&quot;
MAXSLEEP=${MAXSLEEP:0:10}
ZERO=&quot;0000000000&quot;
if [ -z &quot;$GUY&quot; ]
then
    echo &quot;Usage: moluser &lt;username&gt; [max sleep time(millionseconds)]&quot;
    echo
    echo &quot;Molest a user py kill -STOP his sshd&quot;
    echo '$Id$'
    exit 0
fi

[ -z &quot;$MAXSLEEP&quot; ] &amp;&amp; SLEEP=1000

while true
do
    SLEEP=$(expr $RANDOM % $MAXSLEEP)
    SLEEP=&quot;${ZERO:0:$(expr ${#MAXSLEEP} - ${#SLEEP})}$SLEEP&quot;
    SLEEP=&quot;${SLEEP:0:1}.${SLEEP:1}&quot;
    _UID=&quot;$(id -u $GUY 2&gt;/dev/null)&quot;
    pkill -SIGSTOP -U $_UID sshd
    sleep $SLEEP
    pkill -SIGCONT -U $_UID sshd
done</code></pre>]]></description>
            <link>http://blog.jianingy.com/2008/06/admin.html</link>
            <guid>http://blog.jianingy.com/2008/06/admin.html</guid>
            
                <category domain="http://www.sixapart.com/ns/types#category">Evil Administrator</category>
            
            
                <category domain="http://www.sixapart.com/ns/types#tag">moluser</category>
            
            <pubDate>Fri, 06 Jun 2008 14:31:44 +0800</pubDate>
        </item>
        
        <item>
            <title>scp回拷文件</title>
            <description><![CDATA[<p>如果登录了一台机器，想把上面某个文件copy回自己的机器，有懒得ifconfig找自己机器的IP。可以用: </p>

<pre><code>scp file  ${SSH_CONNECTION%% *}:~/</code></pre>]]></description>
            <link>http://blog.jianingy.com/2008/05/scp.html</link>
            <guid>http://blog.jianingy.com/2008/05/scp.html</guid>
            
                <category domain="http://www.sixapart.com/ns/types#category">System Administration</category>
            
            
                <category domain="http://www.sixapart.com/ns/types#tag">scp</category>
            
            <pubDate>Mon, 19 May 2008 18:18:20 +0800</pubDate>
        </item>
        
        <item>
            <title>【转】rxvt-unicode (urxvt) 字间距过宽的patch</title>
            <description><![CDATA[<p>依据 http://lists.schmorp.de/pipermail/rxvt-unicode/2007q4/000514.html 的说法。rxvt-unicode的字间距比其他terminal要大出很多，是因为计算公式有错误。使用如下patch即可消除这个问题。</p>

<pre><code>diff -NBupr rxvt-unicode-9.02/src/rxvtfont.C rxvt-unicode-9.02-fixed/src/rxvtfont.C
--- rxvt-unicode-9.02/src/rxvtfont.C    2008-01-26 23:07:30.000000000 +0800
+++ rxvt-unicode-9.02-fixed/src/rxvtfont.C      2008-05-11 21:47:56.000000000 +0800
@@ -1198,9 +1198,14 @@ rxvt_font_xft::load (const rxvt_fontprop
           g.width -= g.x;

           int wcw = WCWIDTH (ch);
+/*
+ * see: http://lists.schmorp.de/pipermail/rxvt-unicode/2007q4/000514.html
           if (wcw &gt; 0) g.width = (g.width + wcw - 1) / wcw;
-
           if (width    &lt; g.width       ) width    = g.width;
+*/
+          if (wcw &gt; 1) g.xOff = g.xOff / wcw;
+          if (width &lt; g.xOff) width = g.xOff;
+
           if (height   &lt; g.height      ) height   = g.height;
           if (glheight &lt; g.height - g.y) glheight = g.height - g.y;
         }</code></pre>]]></description>
            <link>http://blog.jianingy.com/2008/05/rxvtunicode-urxvt-patch.html</link>
            <guid>http://blog.jianingy.com/2008/05/rxvtunicode-urxvt-patch.html</guid>
            
                <category domain="http://www.sixapart.com/ns/types#category">Linux Application</category>
            
            
                <category domain="http://www.sixapart.com/ns/types#tag">patch</category>
            
                <category domain="http://www.sixapart.com/ns/types#tag">rxvt-unicode</category>
            
                <category domain="http://www.sixapart.com/ns/types#tag">urxvt</category>
            
            <pubDate>Mon, 12 May 2008 21:24:30 +0800</pubDate>
        </item>
        
        <item>
            <title>杀掉由NFS造成Uninterruptible的进程</title>
            <description><![CDATA[<p>一台机器上mount了一很多nfs的分区，但是其中一个nfs server挂了(硬件问题一时启动不起来)。结果几个df进程就跟着挂起了，并且用kill -9也杀不掉。当时的进程状态是:</p>

<pre><code>[jianingy(0)@xxxxxx ~]$ ps ax -o pid,wchan,s,command | grep df$
3505 rpc_ex D df
3844 rpc_ex D df
4162 rpc_ex D df

[jianingy(0)@xxxxxx ~]$ pstree
init─┬─acpid
    ├─agetty
    ├─atd
    ├─crond
    ├─dbus-daemon-1
    ├─3*[df]
...</code></pre>

<p>所有df都wait在了rpc_execute。进程都在uninterruptible sleep(即ps的D状态)，因此不会处理任何信号。经过广泛的搜索，发现rpc_execute所需数据由rpciod提供。因此只要killall -KILL rpciod就可以终止rpc_execute调用, 而rpciod在被杀掉后会自己重启过来。</p>

<p>另外出现这种情况大多因为使用默认方式mount了nfs, 这种情况下连接失败时nfs客户端会不停尝试连接服务器。在mount时使用intr选项可以避免这类问题的出现。下面贴一段nfs mount option的说明</p>

<pre><code>       soft           If  an  NFS  file operation has a major timeout then report an I/O error to the calling
                      program.  The default is to continue retrying NFS file operations indefinitely.

       hard           If an NFS file operation has a major timeout then report &quot;server not responding&quot; on the
                      console and continue retrying indefinitely.  This is the default.

       intr           If an NFS file operation has a major timeout and it is hard mounted, then allow signals
                      to interupt the file operation and cause it to return EINTR  to  the  calling  program.
                      The default is to not allow file operations to be interrupted.</code></pre>]]></description>
            <link>http://blog.jianingy.com/2008/04/nfsuninterruptible.html</link>
            <guid>http://blog.jianingy.com/2008/04/nfsuninterruptible.html</guid>
            
                <category domain="http://www.sixapart.com/ns/types#category">System Administration</category>
            
            
                <category domain="http://www.sixapart.com/ns/types#tag">nfs</category>
            
            <pubDate>Tue, 22 Apr 2008 13:38:13 +0800</pubDate>
        </item>
        
        <item>
            <title>Linux &amp; BSD上获取本机IP地址</title>
            <description><![CDATA[<pre><code>ifconfig | awk '/inet (addr:)?/{sub(&quot;addr:&quot;,&quot;&quot;);print $2;exit}'</code></pre>

<p>需要拿多个IP的话，把exit去掉即可</p>]]></description>
            <link>http://blog.jianingy.com/2008/04/linux-bsdip.html</link>
            <guid>http://blog.jianingy.com/2008/04/linux-bsdip.html</guid>
            
                <category domain="http://www.sixapart.com/ns/types#category">Bash Script</category>
            
            
                <category domain="http://www.sixapart.com/ns/types#tag">ifconfig</category>
            
            <pubDate>Wed, 16 Apr 2008 15:03:12 +0800</pubDate>
        </item>
        
        <item>
            <title>Keep Tunnelling - 不灭的隧道</title>
            <description><![CDATA[<p>我们用daemontools来控制ssh tunnel确保tunnel能在意外断开后主动连接上。在daemon中做tunnel最大的问题就是如何输入密码。这个问题可以使用以前的 <a href="http://blog.jianingy.com/2007/05/sshagent.html">ssh-attach</a> 脚本来解决。</p>

<p>首先创建一个连接脚本(tunnel.sh):</p>

<pre><code>#!/bin/sh
HOME=/home/jianingy
eval `$HOME/bin/ssh-attach`
ssh -p 23456 -b 0.0.0.0 -R 12345:localhost:143 xxx.xxx.xxx.xxx &quot;vmstat 60&quot;</code></pre>

<p>再建立daemontools的run脚本:</p>

<pre><code>#!/bin/sh

exec setuidgid jianingy ./tunnel.sh</code></pre>

<p>用加载ssh-agent的用户(这里是jianingy)来执行tunnel.sh(即用setuidgid jianingy在指定)，酱紫tunnel.sh中调用的ssh-attach便能复用已有的ssh-agent了，保证tunnel连接无须输入密码.</p>]]></description>
            <link>http://blog.jianingy.com/2008/03/keep-tunnelling.html</link>
            <guid>http://blog.jianingy.com/2008/03/keep-tunnelling.html</guid>
            
                <category domain="http://www.sixapart.com/ns/types#category">System Administration</category>
            
            
                <category domain="http://www.sixapart.com/ns/types#tag">ssh</category>
            
                <category domain="http://www.sixapart.com/ns/types#tag">tunnel</category>
            
            <pubDate>Sun, 09 Mar 2008 21:02:10 +0800</pubDate>
        </item>
        
        <item>
            <title>daemontools 常用操作</title>
            <description><![CDATA[<p>这里可说的是DJB写的 <a href="http://cr.yp.to/daemontools.html">daemontools</a> , 不是DAEMON Tools那个虚拟光驱哦.</p>

<h1><strong>启停daemon</strong></h1>

<pre><code>svc -t /service/lighttpd # 重启lighttpd
svc -u /service/lighttpd # 启动lighttpd
svc -d /service/lighttpd # 停止lighttpd</code></pre>

<h1><strong>删除daemon</strong></h1>

<pre><code>cd /service/lighttpd
rm -rf /service/lighttpd
svc -dx .</code></pre>

<h1><strong>查看daemon的状态</strong></h1>

<pre><code>svstat /service</code></pre>

<h1><strong>查看daemon log</strong></h1>

<pre><code>tailn64log /service/lighttpd/log/main/current</code></pre>

<p><span class="caps">PS. </span>用daemontools管理lighttpd再好不过了，能够准确的定位多个lighttpd服务中你想要的那个～</p>]]></description>
            <link>http://blog.jianingy.com/2008/01/daemontools.html</link>
            <guid>http://blog.jianingy.com/2008/01/daemontools.html</guid>
            
                <category domain="http://www.sixapart.com/ns/types#category">System Administration</category>
            
            
                <category domain="http://www.sixapart.com/ns/types#tag">daemon</category>
            
                <category domain="http://www.sixapart.com/ns/types#tag">maintainance</category>
            
            <pubDate>Fri, 11 Jan 2008 22:11:37 +0800</pubDate>
        </item>
        
        <item>
            <title>Perl Module 的编写</title>
            <description><![CDATA[<pre><code><span class="category1">package</span> YourModule; 
<span class="linecomment"># gives you Exporter's import() method directly</span>
<span class="category1">use</span> Exporter 'import'; 
@EXPORT_OK = <span class="category3">qw</span>(munge frobnicate);
@EXPORT = <span class="category3">qw</span>(sth);</code></pre>

<p>@EXPORT_OK 中声明的函数需要在use YourModule后加入qw//来申请进入全局。而@EXPORT 中声明的函数是默认就进入全局的。</p>]]></description>
            <link>http://blog.jianingy.com/2008/01/noteperl-module-template.html</link>
            <guid>http://blog.jianingy.com/2008/01/noteperl-module-template.html</guid>
            
                <category domain="http://www.sixapart.com/ns/types#category">Perl</category>
            
            
                <category domain="http://www.sixapart.com/ns/types#tag">perl</category>
            
            <pubDate>Wed, 09 Jan 2008 11:01:49 +0800</pubDate>
        </item>
        
        <item>
            <title>linux的TCP状态里各种WAIT的含义</title>
            <description><![CDATA[<p>netstat -ant 显示的连接状态有几种WAIT: <span class="caps">FIN</span>_WAIT_1,FIN_WAIT_2,CLOSE_WAIT和TIME_WAIT. 他们的含义要从TCP的连接中断过程说起</p>

<pre><code>Server              Client
  -------- FIN --------&gt;
  &lt;------- ACK ---------
  &lt;------- FIN ---------
  -------- ACK --------&gt;</code></pre>

<p>对于服务器主动关闭连接(Active Close): </p>


<ol>
<li>服务器首先向客户机发送FIN包，然后服务器进入FIN_WAIT_1状态。</li>
<li>客户机向服务器确认FIN包收到，向服务器发送FIN/ACK，客户机进入CLOSE_WAIT状态。</li>
<li>服务器收到来自客户机的FIN/ACK后，进入FIN_WAIT_2状态</li>
<li>现在客户机进入被动关闭("passive close")状态，客户机OS等待他上面的应用程序关闭连接。一旦连接被关<br />
闭，客户端会发送FIN包到服务器</li>
<li>当服务器收到FIN包后，服务器会向客户机发送FIN/ACK确认，然后进入著名的TIME_WAIT状态</li>
<li>由于在连接关闭后，还不能确定所有连接关闭前的包都被服务器接受到了(包的接受是没有先后顺序的)，因此有了TIME_WAIT状态。在这个状态中，服务器仍然在等待客户机发送的但是还未到达服务器的包。这个状态dl. </li>
<li>将保持2*MSL的时间，这里的MSL指的是一个TCP包在网络中存在的最长时间。一般情况下2*MSL=240秒。 </li>
</ol>

]]></description>
            <link>http://blog.jianingy.com/2007/11/linuxtcptime.html</link>
            <guid>http://blog.jianingy.com/2007/11/linuxtcptime.html</guid>
            
                <category domain="http://www.sixapart.com/ns/types#category">System Administration</category>
            
            
                <category domain="http://www.sixapart.com/ns/types#tag">network</category>
            
            <pubDate>Fri, 23 Nov 2007 11:11:29 +0800</pubDate>
        </item>
        
        <item>
            <title>自动调用sudo的shell函数</title>
            <description><![CDATA[<p>很多脚本需要以root来，因此当当前用户不是root的时候可以提示并引导用户获得root权限再执行。至少比看到一对Permission Denied要有好一些。(当然是引导那些有sudo priviledge的用户去sudo咯)</p>

<p>自动调用sudo的shell函数:</p>

<pre><code>invoke_sudo() 
{ 
    if [ &quot;`id -u`&quot; != &quot;`id -u $1`&quot; ]; then 
        echo &quot;`whoami`: you need $1 priviledge to run this application.&quot; 
        if [ &quot;$AUTO_INVOKE_SUDO&quot; == &quot;yes&quot; ]; then 
            echo &quot;Invkoing sudo ...&quot; 
            sudo -u &quot;#`id -u $1`&quot; bash -c &quot;$2&quot; 
        fi 
        exit 0 
    fi 
}</code></pre>

<p>使用方法是</p>

<pre><code>invoke_sudo root &quot;$0 $@&quot;</code></pre>]]></description>
            <link>http://blog.jianingy.com/2007/11/sudoshell.html</link>
            <guid>http://blog.jianingy.com/2007/11/sudoshell.html</guid>
            
                <category domain="http://www.sixapart.com/ns/types#category">System Administration</category>
            
            
                <category domain="http://www.sixapart.com/ns/types#tag">shell</category>
            
            <pubDate>Thu, 22 Nov 2007 14:45:34 +0800</pubDate>
        </item>
        
        <item>
            <title>[QUOTE]subversion仓库的迁移</title>
            <description><![CDATA[<p><a href="http://eastviking.javaeye.com/blog/32899">原文地址:http://eastviking.javaeye.com/blog/32899</a></p>


<p><span class="caps">SVN</span>迁移可能有很多原因, 可能是我们想换Repository目录, 或者是想换一台机器, 等等.<br />
<span class="caps">SVN</span>迁移很容易做, 按照下面步骤就可以:</p>


<ol>
<li>将原来的Repository导出为一个文件dumpfile &gt; svnadmin dump path/to/old-repo &gt; dumpfile</li>
<li>创建新的Repository, 创建方法可以参考 Windows 平台安装Subversion server</li>
<li>将dumpfile导入到新的Repository &gt; svnadmin load path/to/new-repo &lt; dumpfile</li>
<li>检查新的Repository的conf/目录下的配置文件, 检查hooks/目录下的构子程序等等... </li>
</ol>

]]></description>
            <link>http://blog.jianingy.com/2007/11/ztsvn.html</link>
            <guid>http://blog.jianingy.com/2007/11/ztsvn.html</guid>
            
                <category domain="http://www.sixapart.com/ns/types#category">System Administration</category>
            
            
                <category domain="http://www.sixapart.com/ns/types#tag">svn</category>
            
            <pubDate>Tue, 20 Nov 2007 14:12:09 +0800</pubDate>
        </item>
        
        <item>
            <title>Apache优化之KeepAlive</title>
            <description><![CDATA[<p>KeepAlive功能是在HTTP/1.1协议中要求实现的，用来保持客户机和服务器的长连接，执子之手与子偕老。通过减少建立TCP Session的次数来提高性能。常用的配置参数有{KeepAlive, KeepAliveTimeout, MaxKeepAliveRequests}。逐个说来：KeepAlive决定是否开启KeepAlive支持(On/Off)；KeepAliveTimeout决定一个KeepAlive的连接的无请求状态最长保持的时间(以秒为单位)， 时间一到就shutdown连接，若之后又有数据传输则必须再建立新的连接了；MaxKeepAliveRequests于 KeepAliveTimeout相似，意思是服务多少个请求就shutdown连接。看个例子：</p>

<pre><code>KeepAlive On
KeepAliveTimeout 5</code></pre>

<p>意思是说，打开KeepAlive，每个连接只保持5秒就中断。</p>

<p>对于KeepAlive的配置需要慎重，错误的参数可能导致严重的性能问题。一个高负载的Server，如果建立很多长连接将无法继续服务新的连接。因此需要根据server的性质调整KeepAliveTimeout或是MaxKeepAliveRequests的值。</p>

<p>例如：你的网页上有三幅图画2个外部javascript，他们都存放在你自己的server上。因此将MaxKeepAliveRequests设置为7比较合适。3幅图 2个js各一个link，网页本身一个link，还有firefox传说中的favicon.ico。当然还是要有KeepAliveTimeout的。如果客户机用了该死的IE并且设置了某个该死的选项，IE是不会向服务器发送HEAD请求查看图片（或是其他资源）是否过期的，而是直接使用本地图片。这个时候服务器是不会计算Request的(因为压根就没有Request嘛)。再如果只有MaxKeepAliveRequests参数，服务器会默认等待5秒才结束KeepAlive连接。通常这5秒可能玩死一个高负载的服务器。因此打开Firefox，启动Firebug，看看你的站究竟需要多少次请求，再决定KeepAlive吧。</p>]]></description>
            <link>http://blog.jianingy.com/2007/11/apachekeepalive.html</link>
            <guid>http://blog.jianingy.com/2007/11/apachekeepalive.html</guid>
            
                <category domain="http://www.sixapart.com/ns/types#category">System Administration</category>
            
            
                <category domain="http://www.sixapart.com/ns/types#tag">apache</category>
            
            <pubDate>Mon, 19 Nov 2007 08:55:44 +0800</pubDate>
        </item>
        
    </channel>
</rss>
