<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0"
	xmlns:content="http://purl.org/rss/1.0/modules/content/"
	xmlns:wfw="http://wellformedweb.org/CommentAPI/"
	xmlns:dc="http://purl.org/dc/elements/1.1/"
	xmlns:atom="http://www.w3.org/2005/Atom"
	xmlns:sy="http://purl.org/rss/1.0/modules/syndication/"
	xmlns:slash="http://purl.org/rss/1.0/modules/slash/"
	>

<channel>
	<title>Dutor &#187; Unix/Linux</title>
	<atom:link href="http://www.dutor.net/index.php/category/unix-linux/feed/" rel="self" type="application/rss+xml" />
	<link>http://www.dutor.net</link>
	<description>熟读而精思，循序而渐进，厚积而薄发。</description>
	<lastBuildDate>Tue, 17 Jan 2012 14:44:19 +0000</lastBuildDate>
	<language>en</language>
	<sy:updatePeriod>hourly</sy:updatePeriod>
	<sy:updateFrequency>1</sy:updateFrequency>
	<generator>http://wordpress.org/?v=3.3.1</generator>
		<item>
		<title>gcc同时使用动态和静态链接</title>
		<link>http://www.dutor.net/index.php/2011/12/mix-dynamic-and-static-linking/</link>
		<comments>http://www.dutor.net/index.php/2011/12/mix-dynamic-and-static-linking/#comments</comments>
		<pubDate>Sun, 25 Dec 2011 15:03:56 +0000</pubDate>
		<dc:creator>dutor</dc:creator>
				<category><![CDATA[Unix/Linux]]></category>
		<category><![CDATA[动态链接]]></category>

		<guid isPermaLink="false">http://www.dutor.net/?p=2691</guid>
		<description><![CDATA[　　场景是这样的。我在写一个Nginx模块，该模块使用了MySQL的C客户端接口库libmysqlclient，当然mysqlclient还引用了其他的库，比如libm, libz, libcrypto等等。对于使用mysqlclient的代码来说，需要关心的只是mysqlclient引用到的动态库。大部分情况下，不是每台机器都安装有libmysqlclient，所以我想把这个库静态链接到Nginx模块中，但又不想把mysqlclient引用的其他库也静态的链接进来。
　　我们知道gcc的-static选项可以使链接器执行静态链接。但简单地使用-static显得有些'暴力'，因为他会把命令行中-static后面的所有-l指明的库都静态链接，更主要的是，有些库可能并没有提供静态库（.a），而只提供了动态库（.so）。这样的话，使用-static就会造成链接错误。
　　在StackOverflow上面提了<a href="http://stackoverflow.com/questions/8623283/how-to-do-partial-linking" target="_blank">How to do partial linking</a>这个问题，但两天都没人搭理我，大概那些哥们儿也像中国人一样，圣诞狂欢呢吧。但最后一个叫Employed Russian的哥们给了<a href="http://stackoverflow.com/questions/2954387/can-i-mix-static-and-shared-object-libraries-when-linking" target="_blank">一个链接</a>，和我的问题相似（你很少能遇到独一无二的问题）。这个帖子唯一的一个解答解决了问题。
　　我之前的链接选项大致是这样的，
<pre lang="bash" line="1">
CORE_LIBS="$CORE_LIBS -L/usr/lib64/mysql -lmysqlclient -lz -lcrypt -lnsl -lm -L/usr/lib64 -lssl -lcrypto"
</pre>]]></description>
			<content:encoded><![CDATA[<p>　　场景是这样的。我在写一个Nginx模块，该模块使用了MySQL的C客户端接口库libmysqlclient，当然mysqlclient还引用了其他的库，比如libm, libz, libcrypto等等。对于使用mysqlclient的代码来说，需要关心的只是mysqlclient引用到的动态库。大部分情况下，不是每台机器都安装有libmysqlclient，所以我想把这个库静态链接到Nginx模块中，但又不想把mysqlclient引用的其他库也静态的链接进来。<br />
　　我们知道gcc的-static选项可以使链接器执行静态链接。但简单地使用-static显得有些&#8217;暴力&#8217;，因为他会把命令行中-static后面的所有-l指明的库都静态链接，更主要的是，有些库可能并没有提供静态库（.a），而只提供了动态库（.so）。这样的话，使用-static就会造成链接错误。<br />
　　在StackOverflow上面提了<a href="http://stackoverflow.com/questions/8623283/how-to-do-partial-linking" target="_blank">How to do partial linking</a>这个问题，但两天都没人搭理我，大概那些哥们儿也像中国人一样，圣诞狂欢呢吧。但最后一个叫Employed Russian的哥们给了<a href="http://stackoverflow.com/questions/2954387/can-i-mix-static-and-shared-object-libraries-when-linking" target="_blank">一个链接</a>，和我的问题相似（你很少能遇到独一无二的问题）。这个帖子唯一的一个解答解决了问题。<br />
　　我之前的链接选项大致是这样的，</p>

<div class="wp_codebox"><table><tr id="p26911"><td class="line_numbers"><pre>1
</pre></td><td class="code" id="p2691code1"><pre class="bash" style="font-family:monospace;"><span style="color: #007800;">CORE_LIBS</span>=<span style="color: #ff0000;">&quot;<span style="color: #007800;">$CORE_LIBS</span> -L/usr/lib64/mysql -lmysqlclient -lz -lcrypt -lnsl -lm -L/usr/lib64 -lssl -lcrypto&quot;</span></pre></td></tr></table></div>

<p>修改过是这样的，</p>

<div class="wp_codebox"><table><tr id="p26912"><td class="line_numbers"><pre>1
2
</pre></td><td class="code" id="p2691code2"><pre class="bash" style="font-family:monospace;"><span style="color: #007800;">CORE_LIBS</span>=<span style="color: #ff0000;">&quot;<span style="color: #007800;">$CORE_LIBS</span> -L/usr/lib64/mysql -Wl,-Bstatic -lmysqlclient <span style="color: #000099; font-weight: bold;">\
</span>    -Wl,-Bdynamic -lz -lcrypt -lnsl -lm -L/usr/lib64 -lssl -lcrypto&quot;</span></pre></td></tr></table></div>

<p>　　其中用到的两个选项：-Wl,-Bstatic和-Wl,-Bdynamic。这两个选项是gcc的特殊选项，它会将选项的参数传递给链接器，作为链接器的选项。比如-Wl,-Bstatic告诉链接器使用-Bstatic选项，该选项是告诉链接器，对接下来的-l选项使用静态链接；-Wl,-Bdynamic就是告诉链接器对接下来的-l选项使用动态链接。下面是man gcc对-Wl,option的描述，</p>
<pre>
       -Wl,option
           Pass option as an option to the linker.  If option contains commas, it is
           split into multiple options at the commas.  You can use this syntax to pass
           an argument to the option.  For example, -Wl,-Map,output.map passes -Map output.map
           to the linker.  When using the GNU linker, you can also get the same effect with
           -Wl,-Map=output.map.
</pre>
<p>下面是man ld分别对-Bstatic和-Bdynamic的描述，</p>
<pre>
       -Bdynamic
       -dy
       -call_shared
           Link against dynamic libraries. You may use this option multiple times on the
           command line: it affects library searching for -l options which follow it.

       -Bstatic
       -dn
       -non_shared
       -static
           Do not link against shared libraries. You may use this option multiple times on
           the command line: it affects library searching for -l options which follow it.
           This option also implies --unresolved-symbols=report-all.  This option can be
           used with -shared.  Doing so means that a shared library is being created but
           that all of the library's external references must be resolved by pulling in
           entries from static libraries.
</pre>
<p>　　值得注意的是对-static的描述：-static和-shared可以同时存在，这样会创建共享库，但该共享库引用的其他库会静态地链接到该共享库中。</p>
]]></content:encoded>
			<wfw:commentRss>http://www.dutor.net/index.php/2011/12/mix-dynamic-and-static-linking/feed/</wfw:commentRss>
		<slash:comments>2</slash:comments>
		</item>
		<item>
		<title>一个致命字符串的解析</title>
		<link>http://www.dutor.net/index.php/2011/11/lethal-string-pipe-machanism/</link>
		<comments>http://www.dutor.net/index.php/2011/11/lethal-string-pipe-machanism/#comments</comments>
		<pubDate>Wed, 02 Nov 2011 06:40:10 +0000</pubDate>
		<dc:creator>dutor</dc:creator>
				<category><![CDATA[Unix/Linux]]></category>
		<category><![CDATA[命令]]></category>

		<guid isPermaLink="false">http://www.dutor.net/?p=2661</guid>
		<description><![CDATA[<h4>一个致命字符串</h4>
　　传说中，存在这么一串神秘的字符，你把它们放到终端，然后回车，不消太久，你的机器就变植物人只能低电平复位重启了。这串神秘的字符看起来是这样的，
<pre lang="bash" line="1">
dutor@home: ~$ :(){ :&#124;:; };:&#038; 
</pre>
　　这是神马玩意儿呢？好的，现在听我的，把你的脑袋面对显示器逆时针旋转四分之一圆周，像不像一个张着血盆大口的长袍老怪？
　　严肃点，你看懂它的真相了吗？换种等价的写法，
<pre lang="bash" line="1">
dutor@home: ~$ foo(){ foo&#124;foo; };foo&#038; 
</pre>
　　其实就是“声明”了一个函数，然后在后台执行这个函数。在函数体内部，以管道的形式调用递归调用自身。第一种写法只是把函数名换成":"产生的怪胎。]]></description>
			<content:encoded><![CDATA[<h4>一个致命字符串</h4>
<p>　　传说中，存在这么一串神秘的字符，你把它们放到终端，然后回车，不消太久，你的机器就变植物人只能低电平复位重启了。这串神秘的字符看起来是这样的，</p>

<div class="wp_codebox"><table><tr id="p26613"><td class="line_numbers"><pre>1
</pre></td><td class="code" id="p2661code3"><pre class="bash" style="font-family:monospace;">dutor<span style="color: #000000; font-weight: bold;">@</span>home: ~$ :<span style="color: #7a0874; font-weight: bold;">&#40;</span><span style="color: #7a0874; font-weight: bold;">&#41;</span><span style="color: #7a0874; font-weight: bold;">&#123;</span> :<span style="color: #000000; font-weight: bold;">|</span>:; <span style="color: #7a0874; font-weight: bold;">&#125;</span>;:<span style="color: #000000; font-weight: bold;">&amp;</span></pre></td></tr></table></div>

<p>　　这是神马玩意儿呢？好的，现在听我的，把你的脑袋面对显示器逆时针旋转四分之一圆周，像不像一个张着血盆大口的长袍老怪？<br />
　　严肃点，你看懂它的真相了吗？换种等价的写法，</p>

<div class="wp_codebox"><table><tr id="p26614"><td class="line_numbers"><pre>1
</pre></td><td class="code" id="p2661code4"><pre class="bash" style="font-family:monospace;">dutor<span style="color: #000000; font-weight: bold;">@</span>home: ~$ foo<span style="color: #7a0874; font-weight: bold;">&#40;</span><span style="color: #7a0874; font-weight: bold;">&#41;</span><span style="color: #7a0874; font-weight: bold;">&#123;</span> foo<span style="color: #000000; font-weight: bold;">|</span>foo; <span style="color: #7a0874; font-weight: bold;">&#125;</span>;foo<span style="color: #000000; font-weight: bold;">&amp;</span></pre></td></tr></table></div>

<p>　　其实就是“声明”了一个函数，然后在后台执行这个函数。在函数体内部，以管道的形式调用递归调用自身。第一种写法只是把函数名换成&#8221;:&#8221;产生的怪胎。<br />
　　就这么简单吗？函数体里面，以管道连接的第二个foo会被执行吗？这需要了解Unix终端下的管道机制，在这之前，先观察一下这些进程的进程树。为了不致于死的那么快，对这个函数稍加修改，</p>

<div class="wp_codebox"><table><tr id="p26615"><td class="line_numbers"><pre>1
2
</pre></td><td class="code" id="p2661code5"><pre class="bash" style="font-family:monospace;">dutor<span style="color: #000000; font-weight: bold;">@</span>home: ~$ :<span style="color: #7a0874; font-weight: bold;">&#40;</span><span style="color: #7a0874; font-weight: bold;">&#41;</span><span style="color: #7a0874; font-weight: bold;">&#123;</span> <span style="color: #c20cb9; font-weight: bold;">sleep</span> <span style="color: #000000;">30</span>;:<span style="color: #000000; font-weight: bold;">|</span>:; <span style="color: #7a0874; font-weight: bold;">&#125;</span>;:<span style="color: #000000; font-weight: bold;">&amp;</span>
<span style="color: #7a0874; font-weight: bold;">&#91;</span><span style="color: #000000;">1</span><span style="color: #7a0874; font-weight: bold;">&#93;</span> <span style="color: #000000;">12345</span></pre></td></tr></table></div>

<p>　　接下来使用pstree命令，查看进程12345的子进程树。</p>

<div class="wp_codebox"><table><tr id="p26616"><td class="line_numbers"><pre>1
</pre></td><td class="code" id="p2661code6"><pre class="bash" style="font-family:monospace;">dutor<span style="color: #000000; font-weight: bold;">@</span>home: ~$ watch <span style="color: #c20cb9; font-weight: bold;">pstree</span> <span style="color: #660033;">-c</span> <span style="color: #000000;">12345</span></pre></td></tr></table></div>

<p>　　每隔30秒左右，进程树变化一次，依次，</p>
<pre>
bash---sleep

bash-+-bash---sleep
     `-bash---sleep

bash-+-bash-+-bash---sleep
     |      `-bash---sleep
     `-bash-+-bash---sleep
            `-bash---sleep

bash-+-bash-+-bash-+-bash---sleep
     |      |      `-bash---sleep
     |      `-bash-+-bash---sleep
     |             `-bash---sleep
     `-bash-+-bash-+-bash---sleep
            |      `-bash---sleep
            `-bash-+-bash---sleep
                   `-bash---sleep
</pre>
<p>　　可见，该进程树以二叉树的形式进行扩展。间接说明了，以管道连接的两个命令并不是一次执行的，即两个命令的执行是并发的，时间上是有交叠的。</p>
<h4>终端下的管道机制</h4>
<p>　　Unix终端下管道的实现使用了进程间通讯的一种，即匿名管道。由于匿名管道是匿名的，所以只能用在有亲缘关系的进程之间。通常是父进程创建匿名管道，然后fork出子进程，这时父子进程共享匿名管道的描述符。然后父进程向管道中写数据，子进程从管道中读数据。<br />
　　具体到bash中的管道：bash首先解析用户的输入，比如foo | bar。然后，bash使用fork创建子进程P1，必要时使用wait族系统调用等待子进程结束。由P1创建匿名管道，然后P1再次fork出P2进程。接着，P1关闭匿名管道的读端，并将写端的文件描述符复制到标准输出（dup系统调用）；P2关闭匿名管道的写端，并将读端的文件描述符复制到标准输入。最后，P1使用exec族系统调用执行foo，覆盖当前进程空间；P2使用执行bar。这样，最终foo的标准输出就被管道连接到了bar的标准输入上了。<br />
　　要注意的是，这里foo和bar谁是父谁是子是取决于实现的，不变的是管道流始终是自左向右的。<br />
下面是一段示例代码，</p>

<div class="wp_codebox"><table><tr id="p26617"><td class="line_numbers"><pre>1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
</pre></td><td class="code" id="p2661code7"><pre class="c" style="font-family:monospace;"><span style="color: #666666; font-style: italic;">//~ foo.c</span>
<span style="color: #993333;">int</span>
main<span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span>
<span style="color: #009900;">&#123;</span>
    write<span style="color: #009900;">&#40;</span><span style="color: #0000dd;">1</span><span style="color: #339933;">,</span> <span style="color: #ff0000;">&quot;message<span style="color: #000099; font-weight: bold;">\n</span>&quot;</span><span style="color: #339933;">,</span> <span style="color: #0000dd;">8</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
    <span style="color: #b1b100;">return</span> <span style="color: #0000dd;">0</span><span style="color: #339933;">;</span>
<span style="color: #009900;">&#125;</span>
<span style="color: #666666; font-style: italic;">//~ bar.c</span>
<span style="color: #993333;">int</span>
main<span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span>
<span style="color: #009900;">&#123;</span>
    <span style="color: #993333;">char</span> buf<span style="color: #009900;">&#91;</span><span style="color: #0000dd;">9</span><span style="color: #009900;">&#93;</span> <span style="color: #339933;">=</span> <span style="color: #009900;">&#123;</span><span style="color: #0000dd;">0</span><span style="color: #009900;">&#125;</span><span style="color: #339933;">;</span>
    read<span style="color: #009900;">&#40;</span><span style="color: #0000dd;">0</span><span style="color: #339933;">,</span> buf<span style="color: #339933;">,</span> <span style="color: #993333;">sizeof</span><span style="color: #009900;">&#40;</span>buf<span style="color: #009900;">&#41;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
    buf<span style="color: #009900;">&#91;</span><span style="color: #0000dd;">0</span><span style="color: #009900;">&#93;</span> <span style="color: #339933;">-=</span> <span style="color: #0000dd;">32</span><span style="color: #339933;">;</span>
    write<span style="color: #009900;">&#40;</span><span style="color: #0000dd;">1</span><span style="color: #339933;">,</span> buf<span style="color: #339933;">,</span> <span style="color: #0000dd;">8</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
    <span style="color: #b1b100;">return</span> <span style="color: #0000dd;">0</span><span style="color: #339933;">;</span>
<span style="color: #009900;">&#125;</span>
<span style="color: #666666; font-style: italic;">//~ main.c</span>
<span style="color: #993333;">int</span>
main<span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span>
<span style="color: #009900;">&#123;</span>
    pid_t pid<span style="color: #339933;">;</span>
    <span style="color: #b1b100;">if</span> <span style="color: #009900;">&#40;</span><span style="color: #009900;">&#40;</span>pid <span style="color: #339933;">=</span> fork<span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span><span style="color: #009900;">&#41;</span> <span style="color: #339933;">==</span> <span style="color: #0000dd;">0</span><span style="color: #009900;">&#41;</span> <span style="color: #009900;">&#123;</span>
        <span style="color: #666666; font-style: italic;">//~ child will establish a pipe</span>
        <span style="color: #993333;">int</span> fd<span style="color: #009900;">&#91;</span><span style="color: #0000dd;">2</span><span style="color: #009900;">&#93;</span><span style="color: #339933;">;</span>
        pipe<span style="color: #009900;">&#40;</span>fd<span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
        <span style="color: #b1b100;">if</span> <span style="color: #009900;">&#40;</span>fork<span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span> <span style="color: #339933;">==</span> <span style="color: #0000dd;">0</span><span style="color: #009900;">&#41;</span> <span style="color: #009900;">&#123;</span>
            <span style="color: #666666; font-style: italic;">//~ child of child</span>
            close<span style="color: #009900;">&#40;</span>fd<span style="color: #009900;">&#91;</span><span style="color: #0000dd;">1</span><span style="color: #009900;">&#93;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span> <span style="color: #666666; font-style: italic;">//~ only read</span>
            dup2<span style="color: #009900;">&#40;</span>fd<span style="color: #009900;">&#91;</span><span style="color: #0000dd;">0</span><span style="color: #009900;">&#93;</span><span style="color: #339933;">,</span> <span style="color: #0000dd;">0</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span> <span style="color: #666666; font-style: italic;">//~ dupliate 'in-endian' of the pipe to 'stdin'</span>
            execv<span style="color: #009900;">&#40;</span><span style="color: #ff0000;">&quot;./bar&quot;</span><span style="color: #339933;">,</span> NULL<span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span> <span style="color: #666666; font-style: italic;">//~ execute 'bar'</span>
        <span style="color: #009900;">&#125;</span>
        close<span style="color: #009900;">&#40;</span>fd<span style="color: #009900;">&#91;</span><span style="color: #0000dd;">0</span><span style="color: #009900;">&#93;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span> <span style="color: #666666; font-style: italic;">//~ only write</span>
        dup2<span style="color: #009900;">&#40;</span>fd<span style="color: #009900;">&#91;</span><span style="color: #0000dd;">1</span><span style="color: #009900;">&#93;</span> <span style="color: #339933;">,</span> <span style="color: #0000dd;">1</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span> <span style="color: #666666; font-style: italic;">//~ duplicate 'out-endian' of the pipe to 'stdout'</span>
        execv<span style="color: #009900;">&#40;</span><span style="color: #ff0000;">&quot;./foo&quot;</span><span style="color: #339933;">,</span> NULL<span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span> <span style="color: #666666; font-style: italic;">//~ execute 'foo'</span>
        wait<span style="color: #009900;">&#40;</span>NULL<span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
    <span style="color: #009900;">&#125;</span>
    <span style="color: #666666; font-style: italic;">//~ parent will wait.</span>
    wait<span style="color: #009900;">&#40;</span>NULL<span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
    <span style="color: #b1b100;">return</span> <span style="color: #0000dd;">0</span><span style="color: #339933;">;</span>
<span style="color: #009900;">&#125;</span></pre></td></tr></table></div>


<div class="wp_codebox"><table><tr id="p26618"><td class="line_numbers"><pre>1
2
3
4
5
</pre></td><td class="code" id="p2661code8"><pre class="bash" style="font-family:monospace;">dutor<span style="color: #000000; font-weight: bold;">@</span>home: ~$ <span style="color: #c20cb9; font-weight: bold;">cc</span> foo.c <span style="color: #660033;">-o</span> foo <span style="color: #000000; font-weight: bold;">&amp;&amp;</span> <span style="color: #c20cb9; font-weight: bold;">cc</span> bar.c <span style="color: #660033;">-o</span> bar <span style="color: #000000; font-weight: bold;">&amp;&amp;</span> <span style="color: #c20cb9; font-weight: bold;">cc</span> main.c <span style="color: #660033;">-o</span> main
dutor<span style="color: #000000; font-weight: bold;">@</span>home: ~$ .<span style="color: #000000; font-weight: bold;">/</span>foo
message
dutor<span style="color: #000000; font-weight: bold;">@</span>home: ~$ .<span style="color: #000000; font-weight: bold;">/</span>main
Message</pre></td></tr></table></div>

<h4>总结</h4>
<p>　　关于终端下的管道，它的简洁和强大自不必说。需要清楚的是，管道中各进程的启动是没有一定的次序的，执行时间是交叠的。一旦知道这些，下面的命令的结果就不会出乎意料。</p>

<div class="wp_codebox"><table><tr id="p26619"><td class="line_numbers"><pre>1
</pre></td><td class="code" id="p2661code9"><pre class="bash" style="font-family:monospace;">dutor<span style="color: #000000; font-weight: bold;">@</span>home: ~$ <span style="color: #c20cb9; font-weight: bold;">cat</span> main.c <span style="color: #000000; font-weight: bold;">|</span> <span style="color: #c20cb9; font-weight: bold;">sed</span> <span style="color: #ff0000;">'s#//.*##'</span> <span style="color: #000000; font-weight: bold;">&gt;</span> main.c <span style="color: #666666; font-style: italic;">#warning: main.c may be truncated.</span></pre></td></tr></table></div>

<p>　　这个命令可以并行的执行某个程序，</p>

<div class="wp_codebox"><table><tr id="p266110"><td class="line_numbers"><pre>1
2
3
4
</pre></td><td class="code" id="p2661code10"><pre class="bash" style="font-family:monospace;"><span style="color: #666666; font-style: italic;"># 如果run.sh产生大量标准输出时，只有最后一个进程的输出会显示到终端</span>
<span style="color: #666666; font-style: italic;"># 其他的都会'堆积'到匿名管道中(如果run.sh不从标准输入读取数据的话)</span>
<span style="color: #666666; font-style: italic;"># 这可能导致进程阻塞</span>
dutor<span style="color: #000000; font-weight: bold;">@</span>home: ~$ .<span style="color: #000000; font-weight: bold;">/</span>run.sh <span style="color: #000000; font-weight: bold;">|</span> .<span style="color: #000000; font-weight: bold;">/</span>run.sh <span style="color: #000000; font-weight: bold;">|</span> .<span style="color: #000000; font-weight: bold;">/</span>run.sh <span style="color: #000000; font-weight: bold;">|</span> .<span style="color: #000000; font-weight: bold;">/</span>run.sh</pre></td></tr></table></div>

]]></content:encoded>
			<wfw:commentRss>http://www.dutor.net/index.php/2011/11/lethal-string-pipe-machanism/feed/</wfw:commentRss>
		<slash:comments>5</slash:comments>
		</item>
		<item>
		<title>求问</title>
		<link>http://www.dutor.net/index.php/2011/06/q-about-session/</link>
		<comments>http://www.dutor.net/index.php/2011/06/q-about-session/#comments</comments>
		<pubDate>Sat, 11 Jun 2011 05:12:14 +0000</pubDate>
		<dc:creator>dutor</dc:creator>
				<category><![CDATA[Unix/Linux]]></category>
		<category><![CDATA[Arch]]></category>

		<guid isPermaLink="false">http://www.dutor.net/?p=2606</guid>
		<description><![CDATA[　　换了Arch Linux，感觉很清爽，但也有不少问题，但大多都能在Arch Wiki上面得到解决，但仍有一个问题。
　　我使用slim登陆管理器，登陆后由.xinitrc启动openbox-session，没有问题。但在slim启动之前，会出现短暂的终端登陆界面，但slim登陆界面随即被启动。登陆后（slim），在命令行，who命令没有输出。执行halt命令关机时，桌面立即退出，立即显示一个终端的登陆界面（而不是关机时的相关信息），几秒钟后机器正常被关闭。
　　可是为什么who命令没有输出呢？我觉得这可能是session的有关问题（但不确定），我对session的理解不是很清晰，希望知道事情真相的朋友能够帮到我，谢谢！
<pre lang="bash" line="1">
#! /bin/bash

xscreensaver &#038;
rl=$(runlevel &#124; grep -o [0-6])

case $rl in
	4) exec openbox-session;;
	5) exec gnome-session;;
#4) exec ck-lauch-session openbox-session;;
#5) exec ck-lauch-session gnome-session;;
esac
</pre>]]></description>
			<content:encoded><![CDATA[<p>　　换了Arch Linux，感觉很清爽，但也有不少问题，但大多都能在Arch Wiki上面得到解决，但仍有一个问题。<br />
　　我使用slim登陆管理器，登陆后由.xinitrc启动openbox-session，没有问题。但在slim启动之前，会出现短暂的终端登陆界面，但slim登陆界面随即被启动。登陆后（slim），在命令行，who命令没有输出。执行halt命令关机时，桌面立即退出，立即显示一个终端的登陆界面（而不是关机时的相关信息），几秒钟后机器正常被关闭。<br />
　　可是为什么who命令没有输出呢？我觉得这可能是session的有关问题（但不确定），我对session的理解不是很清晰，希望知道事情真相的朋友能够帮到我，谢谢！<br />
　　附上我的/etc/rc.conf:</p>
<pre>
#
# /etc/rc.conf - Main Configuration for Arch Linux
#
...
# -----------------------------------------------------------------------
# DAEMONS
# -----------------------------------------------------------------------
#
# Daemons to start at boot-up (in this order)
#   - prefix a daemon with a ! to disable it
#   - prefix a daemon with a @ to start it up in the background
#
DAEMONS=(syslog-ng @network netfs dbus !bluetooth @crond @alsa @wicd @hal @slim)
</pre>
<p>还有.xinitrc:</p>

<div class="wp_codebox"><table><tr id="p260611"><td class="line_numbers"><pre>1
2
3
4
5
6
7
8
9
10
11
</pre></td><td class="code" id="p2606code11"><pre class="bash" style="font-family:monospace;"><span style="color: #666666; font-style: italic;">#! /bin/bash</span>
&nbsp;
xscreensaver <span style="color: #000000; font-weight: bold;">&amp;</span>
<span style="color: #007800;">rl</span>=$<span style="color: #7a0874; font-weight: bold;">&#40;</span>runlevel <span style="color: #000000; font-weight: bold;">|</span> <span style="color: #c20cb9; font-weight: bold;">grep</span> <span style="color: #660033;">-o</span> <span style="color: #7a0874; font-weight: bold;">&#91;</span><span style="color: #000000;">0</span>-<span style="color: #000000;">6</span><span style="color: #7a0874; font-weight: bold;">&#93;</span><span style="color: #7a0874; font-weight: bold;">&#41;</span>
&nbsp;
<span style="color: #000000; font-weight: bold;">case</span> <span style="color: #007800;">$rl</span> <span style="color: #000000; font-weight: bold;">in</span>
	<span style="color: #000000;">4</span><span style="color: #7a0874; font-weight: bold;">&#41;</span> <span style="color: #7a0874; font-weight: bold;">exec</span> openbox-session<span style="color: #000000; font-weight: bold;">;;</span>
	<span style="color: #000000;">5</span><span style="color: #7a0874; font-weight: bold;">&#41;</span> <span style="color: #7a0874; font-weight: bold;">exec</span> gnome-session<span style="color: #000000; font-weight: bold;">;;</span>
<span style="color: #666666; font-style: italic;">#4) exec ck-lauch-session openbox-session;;</span>
<span style="color: #666666; font-style: italic;">#5) exec ck-lauch-session gnome-session;;</span>
<span style="color: #000000; font-weight: bold;">esac</span></pre></td></tr></table></div>

<p>　　另外，在xinitrc中，执行exec ck-lauch-session openbox-session时，总无法登陆：从slim登陆后又会出现slim登陆界面。</p>
]]></content:encoded>
			<wfw:commentRss>http://www.dutor.net/index.php/2011/06/q-about-session/feed/</wfw:commentRss>
		<slash:comments>12</slash:comments>
		</item>
		<item>
		<title>拥抱Arch Linux</title>
		<link>http://www.dutor.net/index.php/2011/06/ubuntu-to-arch-linux/</link>
		<comments>http://www.dutor.net/index.php/2011/06/ubuntu-to-arch-linux/#comments</comments>
		<pubDate>Sun, 05 Jun 2011 18:07:43 +0000</pubDate>
		<dc:creator>dutor</dc:creator>
				<category><![CDATA[Unix/Linux]]></category>
		<category><![CDATA[Arch]]></category>

		<guid isPermaLink="false">http://www.dutor.net/?p=2604</guid>
		<description><![CDATA[
　　从Ubuntu 7.04/7.10开始接触Linux，从Ubuntu 8.04开始使用Linux作为桌面，在一定程度上见证了Ubuntu的成长，更重要的是自己也在成长，感谢Ubuntu的陪伴，祝愿他一切顺利。从身边和网络上的朋友了解到，Ubuntu 11.04有了相对比较大的变化，于是我也选择了变化，即使近来本人的经历已经跌宕起伏。我选择了<a href="http://www.archlinux.org/" target="_blank">Arch Linux</a>。不知Arch这个词大家是怎么是发音的，我念作/a:k/，因为Archlinux的Logo让我想到Architecture，更重要的是，我觉得这个发音很性感，像socket一样性感。嗯，我是个感官动物，我喜欢一切性感的事物，或者说我觉得我喜欢的东西都很性感。

　　做为个人使用，没有X，没有桌面的系统是不食人间烟火的系统。下面要做的就是，安装Xorg, 显卡驱动（安装X时，开源驱动会被安装，没有特殊需求的话，可不用手动安装）。安装桌面环境，重量级如GNOME、KDE之流，轻量级如xfce、lxde等等。我没有直接现成的安装桌面环境，而是分别安装窗口管理器(openbox)，登陆管理器(slim)，文件管理器(Thunar)，系统面板(tint2)等等。有了基本的桌面，还需要安装和配置系统的字体(ttf-ms-fonts, bitstream等等)，中文输入法(ibus-sunpinyin), 无线网络管理利器(wicd)。

　　再最后，就是安装最常用的应用程序了，虚拟终端(urxvt)，浏览器(chromium)，编辑器(vim/gvim/gedit)，媒体播放器(mplayer, smplayer, audacious)，pdf阅读器(evince, xpdf)，图片查看/编辑器(eog, feh, Gimp)，邮件客户端(mutt, Thunderbird)，即时通讯工具(Pidgin)，不啦不啦。]]></description>
			<content:encoded><![CDATA[<p>　　从Ubuntu 7.04/7.10开始接触Linux，从Ubuntu 8.04开始使用Linux作为桌面，在一定程度上见证了Ubuntu的成长，更重要的是自己也在成长，感谢Ubuntu的陪伴，祝愿他一切顺利。从身边和网络上的朋友了解到，Ubuntu 11.04有了相对比较大的变化，于是我也选择了变化，即使近来本人的经历已经跌宕起伏。我选择了<a href="http://www.archlinux.org/" target="_blank">Arch Linux</a>。不知Arch这个词大家是怎么是发音的，我念作/a:k/，因为Archlinux的Logo让我想到Architecture，更重要的是，我觉得这个发音很性感，像socket一样性感。嗯，我是个感官动物，我喜欢一切性感的事物，或者说我觉得我喜欢的东西都很性感。<br />
　　正经点，介绍/记录下我安装Arch的过程。之前我在VitualBox中折腾过一次，但因为虚拟机中显卡驱动的原因，X后面的东西折腾（我想这也是最折腾的地方吧）。另外，在正式安装Arch之前，我还大致浏览了一本手册，叫Arch Linux Handbook，大约一百六七十页的样子，这本手册由Dusty Philips编辑，和<a href="http://wiki.archlinux.org/" target="_blank">Archlinux Wiki</a>的新手指南大致相同，只是更加详细。<br />
　　首先，需要下载安装镜像。我使用U盘安装。有意思的是Arch的安装镜像可以直接写到U盘，而不用其他特殊的制作工具。即使用dd命令就可以制作USB的启动盘，</p>

<div class="wp_codebox"><table><tr id="p260412"><td class="code" id="p2604code12"><pre class="bash" style="font-family:monospace;">$ <span style="color: #c20cb9; font-weight: bold;">dd</span> <span style="color: #007800;">if</span>=Archlinux.iso <span style="color: #007800;">of</span>=<span style="color: #000000; font-weight: bold;">/</span>dev<span style="color: #000000; font-weight: bold;">/</span>sdb <span style="color: #007800;">bs</span>=4M</pre></td></tr></table></div>

<p>　　dd命令完成后，使用fdisk察看，会发现U盘已经存在一个分区和文件系统（当然之前的文件系统和分区就不见了），而且U盘已经被设置为可引导。我对Ubuntu, Debian和Gentoo的镜像做相似的测试，但都没有相同的效果。有兴趣的朋友可以研究一下Arch的iso的结构。<br />
　　使用制作好的可启动U盘，就可以开始安装了。对于基本系统的安装，具体的安装细节不再啰嗦，不熟悉的朋友可以参照上面说的安装手册、Arch Wiki或者其他资料进行。这里仅介绍下我在安装的过程中遇到的问题。<br />
　　首先选择安装源，可以选择光盘（这里即U盘）或者网络，网络安装是一种十分方便的方法，但对网络要求较高。我选择使用U盘作为安装源。<br />
　　接下来设置时钟，选择时区。硬件时钟的设置有UTC和localtime两种，如果你的机器需要双/多重引导，尤其是与Windows共存，应该选择localtime。<br />
　　该选择/建立分区了。由于之前我的机器是Ubuntu和Win 7双系统，对Ubuntu也要说ByeBye了，所以我直接选择之前的各Linux分区，包括：/boot, /, swap, /home, 因为之前/home下有大量数据，且只是“用户数据”，所以不需也不能格式化。而其他都需要重新格式化。在操作分区的时候，一定要慎之又慎，一定要清楚每一个操作会产生什么样的后果。例如，我选择将/dev/sda10，即Ubuntu中的/home，挂载到/home时，会有提示“是否重新建立文件系统”。<br />
　　分区的事情搞定，下面的事情就轻松多了。<br />
　　选择索要安装的软件包，其中base和base-devel是必须的，其他可选，我选择了其中无线网络支持的相关包。软件包的安装几分钟就可完成。<br />
　　建立好分区和文件系统，安装完软件包，系统的框架就已经建立起来了。下面就要对系统的各种参数进行配置。在配置之前，需要选择编辑配置文件时使用的编辑器，对vi熟悉的就选择vi，否则选nano。如果前面的操作没有错误，配置也不会太过复杂，但为了保险起见，最好检查每一个配置文件，对每一个需要配置的选项。其中可能比较重要的是网络和软件mirror的选择。根据具体情况，可以选择static和dhcp两种方式，如果选择静态，通常还要配置相应的gateway和dns。软件的镜像，我选择了网易163的开源镜像，速度很快。<br />
　　对系统进行基本的配置后，一个能够运行的基本系统就建立了，但还不能够引导，还需要安装一个bootloader。我选择使用grub，当前Arch使用的是grub 0.97，而不是grub2。所以配置grub需要察看和编辑menu.lst。如果之前分区和文件系统挂载没有问题，menu.lst也应该不会有问题。只是默认情况下，之前存在与机器上的其他系统（比如Windows）不会被列入grub的引导菜单，需要手动加入。最后将grub记录写入到MBR即可，我这里即将grub安装到/dev/sda.<br />
　　最后，重启。<br />
　　之后，登陆到系统，添加新用户。在更新整个系统之前，首先要做的就是配置网络。当时我就卡在了网络配置上了，系统中没有eth0接口，因为没有我的网卡的驱动。最终，我不得不，使用其他机器下载对应的网卡驱动，然后编译、加载和重启，才联上了网络。<br />
　　更新系统。Arch使用不同于Ubuntu/Debian的“包管理”机制，除了最常用的pacman，还有ABS, Yaourt等，使用方法见诸世界各地。</p>
<p>　　做为个人使用，没有X，没有桌面的系统是不食人间烟火的系统。下面要做的就是，安装Xorg, 显卡驱动（安装X时，开源驱动会被安装，没有特殊需求的话，可不用手动安装）。安装桌面环境，重量级如GNOME、KDE之流，轻量级如xfce、lxde等等。我没有直接现成的安装桌面环境，而是分别安装窗口管理器(openbox)，登陆管理器(slim)，文件管理器(Thunar)，系统面板(tint2)等等。有了基本的桌面，还需要安装和配置系统的字体(ttf-ms-fonts, bitstream等等)，中文输入法(ibus-sunpinyin), 无线网络管理利器(wicd)。</p>
<p>　　再最后，就是安装最常用的应用程序了，虚拟终端(urxvt)，浏览器(chromium)，编辑器(vim/gvim/gedit)，媒体播放器(mplayer, smplayer, audacious)，pdf阅读器(evince, xpdf)，图片查看/编辑器(eog, feh, Gimp)，邮件客户端(mutt, Thunderbird)，即时通讯工具(Pidgin)，不啦不啦。</p>
<p>　　“折腾”似乎无休无止，但折腾的过程中你得到了什么，失去了什么，只有自己能够体会，折腾的度要由自己把握，在好玩儿、实用和学习之间找到自己的平衡点。</p>
]]></content:encoded>
			<wfw:commentRss>http://www.dutor.net/index.php/2011/06/ubuntu-to-arch-linux/feed/</wfw:commentRss>
		<slash:comments>8</slash:comments>
		</item>
		<item>
		<title>使用make自动备份配置文件</title>
		<link>http://www.dutor.net/index.php/2011/06/make-backup-dotfiles/</link>
		<comments>http://www.dutor.net/index.php/2011/06/make-backup-dotfiles/#comments</comments>
		<pubDate>Wed, 01 Jun 2011 11:10:10 +0000</pubDate>
		<dc:creator>dutor</dc:creator>
				<category><![CDATA[Unix/Linux]]></category>
		<category><![CDATA[git]]></category>
		<category><![CDATA[make]]></category>

		<guid isPermaLink="false">http://www.dutor.net/?p=2601</guid>
		<description><![CDATA[<pre lang="make" line="1">
vpath % /home/dutor/
vpath rc /home/dutor/.lftp/
vpath vsftpd.conf /etc/
vpath openbox /home/dutor/.config/
vpath tint2 /home/dutor/.config/

BACKUP: .vimrc .vim .bashrc .Xresources .xbindkeysrc .gitconfig .bin .screenrc \
.wordump.txt vsftpd.conf openbox .tmux.conf .conkyrc tint2
	dcp $?
	touch BACKUP
</pre>
　　其中，vpath是make的命令，用于指定文件的搜索目录。BACKUP是一个空文件，每当完成备份时，使用touch命令更新其时间戳。dcp是一个脚本，将其参数指明的文件拷贝到Dotfiles目录，$?是make的自动变量，代表依赖关系中比目标更新的依赖。]]></description>
			<content:encoded><![CDATA[<p>　　make是个好同志，大多数情况下，它被用来编译源代码，生成结果代码，然后把结果代码连接起来生成可执行文件或者库文件。它读取一个或多个makefile的文件，makefile主要由一系列的“规则”组成，每个规则包括目标、目标的依赖和shell命令，目标即生成的目标，它和它的依赖的依赖关系由文件的修改时间来决定，当依赖相比目标较新时，表明目标已经过期，需要重新生成，此时相关的shell命令会由make交由其子shell来执行，通常用来重新生成目标。<br />
　　make的这种特性可以用来自动化地管理文件，例如我使用make来自动备份我的大部分配置文件。<br />
　　我的配置主要是散布于HOME下的dot文件，我利用make把它们收集于Dotfiles文件夹。使用的makefile如下，</p>

<div class="wp_codebox"><table><tr id="p260113"><td class="line_numbers"><pre>1
2
3
4
5
6
7
8
9
10
</pre></td><td class="code" id="p2601code13"><pre class="make" style="font-family:monospace;"><span style="color: #666622; font-weight: bold;">vpath</span> <span style="color: #004400;">%</span> <span style="color: #004400;">/</span>home<span style="color: #004400;">/</span>dutor<span style="color: #004400;">/</span>
<span style="color: #666622; font-weight: bold;">vpath</span> rc <span style="color: #004400;">/</span>home<span style="color: #004400;">/</span>dutor<span style="color: #004400;">/.</span>lftp<span style="color: #004400;">/</span>
<span style="color: #666622; font-weight: bold;">vpath</span> vsftpd<span style="color: #004400;">.</span>conf <span style="color: #004400;">/</span>etc<span style="color: #004400;">/</span>
<span style="color: #666622; font-weight: bold;">vpath</span> openbox <span style="color: #004400;">/</span>home<span style="color: #004400;">/</span>dutor<span style="color: #004400;">/.</span>config<span style="color: #004400;">/</span>
<span style="color: #666622; font-weight: bold;">vpath</span> tint2 <span style="color: #004400;">/</span>home<span style="color: #004400;">/</span>dutor<span style="color: #004400;">/.</span>config<span style="color: #004400;">/</span>
&nbsp;
BACKUP<span style="color: #004400;">:</span> <span style="color: #004400;">.</span>vimrc <span style="color: #004400;">.</span>vim <span style="color: #004400;">.</span>bashrc <span style="color: #004400;">.</span>Xresources <span style="color: #004400;">.</span>xbindkeysrc <span style="color: #004400;">.</span>gitconfig <span style="color: #004400;">.</span>bin <span style="color: #004400;">.</span>screenrc \
<span style="color: #004400;">.</span>wordump<span style="color: #004400;">.</span>txt vsftpd<span style="color: #004400;">.</span>conf openbox <span style="color: #004400;">.</span>tmux<span style="color: #004400;">.</span>conf <span style="color: #004400;">.</span>conkyrc tint2
	dcp <span style="color: #000088; font-weight: bold;">$?</span>
	touch BACKUP</pre></td></tr></table></div>

<p>　　其中，vpath是make的命令，用于指定文件的搜索目录。BACKUP是一个空文件，每当完成备份时，使用touch命令更新其时间戳。dcp是一个脚本，将其参数指明的文件拷贝到Dotfiles目录，$?是make的自动变量，代表依赖关系中比目标更新的依赖。dcp是这样的，</p>

<div class="wp_codebox"><table><tr id="p260114"><td class="line_numbers"><pre>1
2
3
4
5
6
</pre></td><td class="code" id="p2601code14"><pre class="bash" style="font-family:monospace;"><span style="color: #7a0874; font-weight: bold;">&#91;</span> <span style="color: #007800;">$#</span> <span style="color: #660033;">-eq</span> <span style="color: #000000;">0</span> <span style="color: #7a0874; font-weight: bold;">&#93;</span> <span style="color: #000000; font-weight: bold;">&amp;&amp;</span> <span style="color: #7a0874; font-weight: bold;">echo</span> <span style="color: #ff0000;">&quot;Usage: dcp &lt;file&gt; ...&quot;</span> <span style="color: #000000; font-weight: bold;">&amp;&amp;</span> <span style="color: #7a0874; font-weight: bold;">exit</span> <span style="color: #000000;">1</span>
<span style="color: #000000; font-weight: bold;">for</span> i
<span style="color: #000000; font-weight: bold;">do</span>
    <span style="color: #7a0874; font-weight: bold;">echo</span> <span style="color: #660033;">-n</span> <span style="color: #ff0000;">&quot; copying <span style="color: #007800;">$i</span>...&quot;</span>
    <span style="color: #c20cb9; font-weight: bold;">cp</span> <span style="color: #007800;">$i</span> <span style="color: #007800;">$DCPPATH</span> <span style="color: #660033;">-rp</span> <span style="color: #000000; font-weight: bold;">&amp;&amp;</span> <span style="color: #7a0874; font-weight: bold;">echo</span> <span style="color: #ff0000;">'done'</span>
<span style="color: #000000; font-weight: bold;">done</span></pre></td></tr></table></div>

<p>其中$DCPPATH保存了配置文件的保存目录，即Dotfiles.</p>
<p>　　另外，我还将我的配置文件放在了github.com上，使用git clone https://github.com/xdutor/Dotfiles.git可以得到。</p>
]]></content:encoded>
			<wfw:commentRss>http://www.dutor.net/index.php/2011/06/make-backup-dotfiles/feed/</wfw:commentRss>
		<slash:comments>7</slash:comments>
		</item>
		<item>
		<title>使用iconv &amp; luit转换文本编码</title>
		<link>http://www.dutor.net/index.php/2011/05/iconv-luit/</link>
		<comments>http://www.dutor.net/index.php/2011/05/iconv-luit/#comments</comments>
		<pubDate>Thu, 05 May 2011 13:21:57 +0000</pubDate>
		<dc:creator>dutor</dc:creator>
				<category><![CDATA[ToolKits]]></category>
		<category><![CDATA[Unix/Linux]]></category>
		<category><![CDATA[iconv]]></category>
		<category><![CDATA[luit]]></category>
		<category><![CDATA[命令]]></category>

		<guid isPermaLink="false">http://www.dutor.net/?p=2581</guid>
		<description><![CDATA[　　相信很多人经常遇到文件乱码，尤其是文本文件。如果你不是用编辑器打开一个二进制文件的话，这应该是一个编码问题，即文件的实际编码和编辑器查看该文件时所使用的编码不一致。这时候，咱们需要把文件的编码进行转化，或者修改使用该文件的程序采用的编码。后一种方法取决于咱们使用的具体的程序，无法一概而论。
　　这里介绍一个工具，iconv，使用它可以将一个输入文件从一种编码转换到另一种编码，同时将转化结果输出。iconv的-f选项指定源编码，-t选项指定目标编码，-o指定输出文件：
<pre lang="bash">
$ iconv -f coding1 -t coding2 file1 -o file2
</pre>
　　若file1省略，则使用标准输入；若-o选项省略，则使用标准输出。
　　例如，我想把所有GBK编码的.cue文件转化为utf8编码：
<pre lang="bash">
$ find . -name "*.cue" -exec iconv -f gbk -t utf8 {} -o {} \;
</pre>]]></description>
			<content:encoded><![CDATA[<p>　　相信很多人经常遇到文件乱码，尤其是文本文件。如果你不是用编辑器打开一个二进制文件的话，这应该是一个编码问题，即文件的实际编码和编辑器查看该文件时所使用的编码不一致。这时候，咱们需要把文件的编码进行转化，或者修改使用该文件的程序采用的编码。后一种方法取决于咱们使用的具体的程序，无法一概而论。<br />
　　这里介绍一个工具，iconv，使用它可以将一个输入文件从一种编码转换到另一种编码，同时将转化结果输出。iconv的-f选项指定源编码，-t选项指定目标编码，-o指定输出文件：</p>

<div class="wp_codebox"><table><tr id="p258115"><td class="code" id="p2581code15"><pre class="bash" style="font-family:monospace;">$ iconv <span style="color: #660033;">-f</span> coding1 <span style="color: #660033;">-t</span> coding2 file1 <span style="color: #660033;">-o</span> file2</pre></td></tr></table></div>

<p>　　若file1省略，则使用标准输入；若-o选项省略，则使用标准输出。<br />
　　例如，我想把所有GBK编码的.cue文件转化为utf8编码：</p>

<div class="wp_codebox"><table><tr id="p258116"><td class="code" id="p2581code16"><pre class="bash" style="font-family:monospace;">$ <span style="color: #c20cb9; font-weight: bold;">find</span> . <span style="color: #660033;">-name</span> <span style="color: #ff0000;">&quot;*.cue&quot;</span> <span style="color: #660033;">-exec</span> iconv <span style="color: #660033;">-f</span> gbk <span style="color: #660033;">-t</span> utf8 <span style="color: #7a0874; font-weight: bold;">&#123;</span><span style="color: #7a0874; font-weight: bold;">&#125;</span> <span style="color: #660033;">-o</span> <span style="color: #7a0874; font-weight: bold;">&#123;</span><span style="color: #7a0874; font-weight: bold;">&#125;</span> \;</pre></td></tr></table></div>

<p>　　关于编码，还有一个比较实用的工具luit：</p>

<div class="wp_codebox"><table><tr id="p258117"><td class="code" id="p2581code17"><pre class="bash" style="font-family:monospace;">$ luit <span style="color: #660033;">-encoding</span> coding COMMAND</pre></td></tr></table></div>

<p>　　luit将COMMAND命令的输出按照coding编码解释，然后转化为本地系统的编码并输出。<br />
　　例如，各个BBS的telnet输出通常是GBK编码的，直接使用telnet连接可能会出现乱码。使用luit即可，</p>

<div class="wp_codebox"><table><tr id="p258118"><td class="code" id="p2581code18"><pre class="bash" style="font-family:monospace;">$ luit <span style="color: #660033;">-encoding</span> gbk telnet bbs.dlut.edu.cn</pre></td></tr></table></div>

]]></content:encoded>
			<wfw:commentRss>http://www.dutor.net/index.php/2011/05/iconv-luit/feed/</wfw:commentRss>
		<slash:comments>1</slash:comments>
		</item>
		<item>
		<title>[命令技巧]alias</title>
		<link>http://www.dutor.net/index.php/2011/03/commands-alias/</link>
		<comments>http://www.dutor.net/index.php/2011/03/commands-alias/#comments</comments>
		<pubDate>Thu, 10 Mar 2011 06:11:17 +0000</pubDate>
		<dc:creator>dutor</dc:creator>
				<category><![CDATA[Unix/Linux]]></category>
		<category><![CDATA[命令]]></category>

		<guid isPermaLink="false">http://www.dutor.net/?p=2528</guid>
		<description><![CDATA[　　alias, 假名，别名，bash的一个内建命令，用来给常用的较长的命令定义个简短的名称。
　　alias命令的基本格式为alias [word[='command']], []内为可选项。定义word为command的别名。若='command'部分省略，则输出word之前的定义，未定义则报错。单独的alias列出当前环境中所有可用的别名。通常来讲，关于alias，知道这么多就行了。但在使用alias的过程中还有一些问题需要注意。
　　如果bash的expand_aliases选项没有被设置，那么在非交互式shell中alias不会被执行展开。也就是说，在shell脚本中，使用alias会导致"command not found"的错误。使用shopt命令来设置expand_aliases选项：
<pre lang="bash" line="1">
shopt -s expand_aliases
</pre>
设置这个选项，可以在bashrc中，也可以在需要使用alias的脚本中。]]></description>
			<content:encoded><![CDATA[<p>　　alias, 假名，别名，bash的一个内建命令，用来给常用的较长的命令定义个简短的名称。<br />
　　alias命令的基本格式为alias [word[='command']], []内为可选项。定义word为command的别名。若=&#8217;command&#8217;部分省略，则输出word之前的定义，未定义则报错。单独的alias列出当前环境中所有可用的别名。通常来讲，关于alias，知道这么多就行了。但在使用alias的过程中还有一些问题需要注意。<br />
　　如果bash的expand_aliases选项没有被设置，那么在非交互式shell中alias不会被执行展开。也就是说，在shell脚本中，使用alias会导致&#8221;command not found&#8221;的错误。使用shopt命令来设置expand_aliases选项：</p>

<div class="wp_codebox"><table><tr id="p252819"><td class="line_numbers"><pre>1
</pre></td><td class="code" id="p2528code19"><pre class="bash" style="font-family:monospace;"><span style="color: #7a0874; font-weight: bold;">shopt</span> <span style="color: #660033;">-s</span> expand_aliases</pre></td></tr></table></div>

<p>设置这个选项，可以在bashrc中，也可以在需要使用alias的脚本中。</p>
<p>　　再就是，如果在脚本中的同一行内，先定义alias，接着马上使用该alias是会产生错误的。原因就是bash在解释执行脚本过程中，每次读取至少一行命令，alias展开就是在读取时进行的，读取之后（alias展开也完成了）才开始执行命令（当然，还会有参数扩展等其他操作）。由于进行alias展开时该行的alias命令尚未执行，所以其中的alias就不会被展开。举个例子吧，</p>

<div class="wp_codebox"><table><tr id="p252820"><td class="line_numbers"><pre>1
2
</pre></td><td class="code" id="p2528code20"><pre class="bash" style="font-family:monospace;"><span style="color: #7a0874; font-weight: bold;">shopt</span> <span style="color: #660033;">-s</span> expand_aliases
<span style="color: #7a0874; font-weight: bold;">alias</span> <span style="color: #007800;">ll</span>=<span style="color: #ff0000;">'ls -lh'</span>; <span style="color: #7a0874; font-weight: bold;">alias</span> <span style="color: #007800;">e</span>=<span style="color: #ff0000;">'exit'</span>; ll; e</pre></td></tr></table></div>

<p>执行该脚本，会发现ls 和exit命令均未被执行，错误提示ll和e命令未找到。所以，脚本中，alias命令最好单独成行。<br />
　　同样的问题也出现在组合命令中，比如while, for循环等结构，</p>

<div class="wp_codebox"><table><tr id="p252821"><td class="line_numbers"><pre>1
2
3
4
5
6
7
8
9
10
11
12
</pre></td><td class="code" id="p2528code21"><pre class="bash" style="font-family:monospace;"><span style="color: #7a0874; font-weight: bold;">shopt</span> <span style="color: #660033;">-s</span> expand_aliases
<span style="color: #000000; font-weight: bold;">for</span> i <span style="color: #000000; font-weight: bold;">in</span> <span style="color: #000000; font-weight: bold;">`</span><span style="color: #c20cb9; font-weight: bold;">seq</span> <span style="color: #000000;">1</span> <span style="color: #000000;">10</span><span style="color: #000000; font-weight: bold;">`</span>
<span style="color: #000000; font-weight: bold;">do</span>
    <span style="color: #7a0874; font-weight: bold;">alias</span> <span style="color: #007800;">ll</span>=<span style="color: #ff0000;">'ls -lh'</span>
    ll <span style="color: #666666; font-style: italic;"># command ll not found.</span>
<span style="color: #000000; font-weight: bold;">done</span>
&nbsp;
<span style="color: #000000; font-weight: bold;">for</span> i <span style="color: #000000; font-weight: bold;">in</span> <span style="color: #000000; font-weight: bold;">`</span><span style="color: #c20cb9; font-weight: bold;">seq</span> <span style="color: #000000;">1</span> <span style="color: #000000;">10</span><span style="color: #000000; font-weight: bold;">`</span>
<span style="color: #000000; font-weight: bold;">do</span>
    <span style="color: #7a0874; font-weight: bold;">alias</span> <span style="color: #007800;">ll</span>=<span style="color: #ff0000;">'ls -lh'</span>
    ll <span style="color: #666666; font-style: italic;"># now ok</span>
<span style="color: #000000; font-weight: bold;">done</span></pre></td></tr></table></div>

<p>　　类似地，在shell函数中alias也会出现同样的问题。事实上，shell中的函数只不过是一种特殊的、有名字和参数的、使用{}的组合命令，所以单行函数中&#8217;}'之前是必须要有分号的，就像普通的{}组合命令一样。之所以非单行函数不需要分号，是因为换行可以代替分号。<br />
　　最后，bash中alias不可以使用位置参数（据说csh）是可以的，也就是说，不可以使用alias mkcd=&#8217;mkdir $1 &#038;&#038; cd $1&#8242;这样的命令（这种命令允许你在alias中按照自己的意愿安排参数的位置，例如对于alias ll=&#8217;ls $1 -lh&#8217;，ll file被展开为ls file -lh，而不是简单的展开为ls -lh file）。如果在bash中确实需要这样做，就应该使用函数来完成，比如，function mkcd() { &#8216;mkdir $1 &#038;&#038; cd $1; }.</p>
]]></content:encoded>
			<wfw:commentRss>http://www.dutor.net/index.php/2011/03/commands-alias/feed/</wfw:commentRss>
		<slash:comments>5</slash:comments>
		</item>
		<item>
		<title>echo &#8211;help</title>
		<link>http://www.dutor.net/index.php/2011/03/echo-help-information/</link>
		<comments>http://www.dutor.net/index.php/2011/03/echo-help-information/#comments</comments>
		<pubDate>Tue, 08 Mar 2011 02:24:43 +0000</pubDate>
		<dc:creator>dutor</dc:creator>
				<category><![CDATA[Unix/Linux]]></category>
		<category><![CDATA[命令]]></category>

		<guid isPermaLink="false">http://www.dutor.net/?p=2518</guid>
		<description><![CDATA[　　什么是shell自己版本的echo呢？原来，shell中可以使用的命令有“内建命令”（built-in）和外部命令之分。内建命令有shell本身实现，即和shell进程同属于一个地址空间执行，比如echo可能是shell中的一个函数实现的。内置命令通常是无法或者不适以外部命令的形式实现的命令，比如cd, source, alias, bind, history, set等等。外部命令是一些独立的可执行文件，由shell以fork/exec的形式执行。
　　使用type命令可以获取命令的类型。由type type可以知道type命令本身也是内建命令。

　　知道这些，通过--help选项输出echo的帮助信息就不是什么难事了，
<pre lang="bash" line="1">
~$ which echo
/bin/echo
~$ /bin/echo --help
......
</pre>
]]></description>
			<content:encoded><![CDATA[<p>　　大米洲同学给了这么个问题：使用echo命令的&#8211;help选项来显示该命令的帮助信息。这有什么嘛，“抱着试试看的心态”我试了试，得到不是帮助信息，而是赤裸裸的帮助&#8221;&#8211;help&#8221;.<br />
　　为什么呢，echo有&#8211;help选项吗？man之，</p>

<div class="wp_codebox"><table><tr id="p251822"><td class="line_numbers"><pre>1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
</pre></td><td class="code" id="p2518code22"><pre class="bash" style="font-family:monospace;">~$ <span style="color: #7a0874; font-weight: bold;">echo</span> <span style="color: #660033;">--help</span>
<span style="color: #660033;">--help</span>
~$ <span style="color: #c20cb9; font-weight: bold;">man</span> <span style="color: #7a0874; font-weight: bold;">echo</span>
ECHO<span style="color: #7a0874; font-weight: bold;">&#40;</span><span style="color: #000000;">1</span><span style="color: #7a0874; font-weight: bold;">&#41;</span>                          User Commands                         ECHO<span style="color: #7a0874; font-weight: bold;">&#40;</span><span style="color: #000000;">1</span><span style="color: #7a0874; font-weight: bold;">&#41;</span>
NAME
       <span style="color: #7a0874; font-weight: bold;">echo</span> - display a line of text
SYNOPSIS
       <span style="color: #7a0874; font-weight: bold;">echo</span> <span style="color: #7a0874; font-weight: bold;">&#91;</span>OPTION<span style="color: #7a0874; font-weight: bold;">&#93;</span>... <span style="color: #7a0874; font-weight: bold;">&#91;</span>STRING<span style="color: #7a0874; font-weight: bold;">&#93;</span>...
DESCRIPTION
       Echo the STRING<span style="color: #7a0874; font-weight: bold;">&#40;</span>s<span style="color: #7a0874; font-weight: bold;">&#41;</span> to standard output.
&nbsp;
  <span style="color: #660033;">-n</span>             <span style="color: #000000; font-weight: bold;">do</span> not output the trailing newline
  <span style="color: #660033;">-e</span>             <span style="color: #7a0874; font-weight: bold;">enable</span> interpretation of backslash escapes
  <span style="color: #660033;">-E</span>             disable interpretation of backslash escapes <span style="color: #7a0874; font-weight: bold;">&#40;</span>default<span style="color: #7a0874; font-weight: bold;">&#41;</span>
      <span style="color: #660033;">--help</span>     display this <span style="color: #7a0874; font-weight: bold;">help</span> and <span style="color: #7a0874; font-weight: bold;">exit</span>
      <span style="color: #660033;">--version</span>  output version information and <span style="color: #7a0874; font-weight: bold;">exit</span>
......
&nbsp;
NOTE: your shell may have its own version of <span style="color: #7a0874; font-weight: bold;">echo</span>, <span style="color: #c20cb9; font-weight: bold;">which</span> usually supersedes
the version described here.  Please refer to your shell<span style="color: #ff0000;">'s documentation
for details about the options it supports.
......</span></pre></td></tr></table></div>

<p>还真有&#8211;help选项。“眼尖”的同学可能注意到了，man echo输出中的NOTE说明，shell（比如bash）可能有自己的echo版本，而且可能优先于man echo的echo。<br />
　　什么是shell自己版本的echo呢？原来，shell中可以使用的命令有“内建命令”（built-in）和外部命令之分。内建命令有shell本身实现，即和shell进程同属于一个地址空间执行，比如echo可能是shell中的一个函数实现的。内置命令通常是无法或者不适以外部命令的形式实现的命令，比如cd, source, alias, bind, history, set等等。外部命令是一些独立的可执行文件，由shell以fork/exec的形式执行。<br />
　　使用type命令可以获取命令的类型。由type type可以知道type命令本身也是内建命令。</p>
<p>　　知道这些，通过&#8211;help选项输出echo的帮助信息就不是什么难事了，</p>

<div class="wp_codebox"><table><tr id="p251823"><td class="line_numbers"><pre>1
2
3
4
</pre></td><td class="code" id="p2518code23"><pre class="bash" style="font-family:monospace;">~$ <span style="color: #c20cb9; font-weight: bold;">which</span> <span style="color: #7a0874; font-weight: bold;">echo</span>
<span style="color: #000000; font-weight: bold;">/</span>bin<span style="color: #000000; font-weight: bold;">/</span><span style="color: #7a0874; font-weight: bold;">echo</span>
~$ <span style="color: #000000; font-weight: bold;">/</span>bin<span style="color: #000000; font-weight: bold;">/</span><span style="color: #7a0874; font-weight: bold;">echo</span> <span style="color: #660033;">--help</span>
......</pre></td></tr></table></div>

<p>　　BTW，man echo查看的是外部echo的信息，那怎么查看内建echo的帮助信息呢？</p>

<div class="wp_codebox"><table><tr id="p251824"><td class="line_numbers"><pre>1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
</pre></td><td class="code" id="p2518code24"><pre class="bash" style="font-family:monospace;">~$ <span style="color: #7a0874; font-weight: bold;">help</span> <span style="color: #7a0874; font-weight: bold;">echo</span>
<span style="color: #7a0874; font-weight: bold;">echo</span>: <span style="color: #7a0874; font-weight: bold;">echo</span> <span style="color: #7a0874; font-weight: bold;">&#91;</span>-neE<span style="color: #7a0874; font-weight: bold;">&#93;</span> <span style="color: #7a0874; font-weight: bold;">&#91;</span>arg ...<span style="color: #7a0874; font-weight: bold;">&#93;</span>
    Output the ARGs.  If <span style="color: #660033;">-n</span> is specified, the trailing newline is
    suppressed.  If the <span style="color: #660033;">-e</span> option is given, interpretation of the
    following backslash-escaped characters is turned on:
        \a      alert <span style="color: #7a0874; font-weight: bold;">&#40;</span>bell<span style="color: #7a0874; font-weight: bold;">&#41;</span>
        \b      backspace
        \c      suppress trailing newline
        \E      escape character
        \f      form feed
        \n      new line
        \r      carriage <span style="color: #7a0874; font-weight: bold;">return</span>
        \t      horizontal tab
        \v      vertical tab
        \\      backslash
        \0nnn   the character whose ASCII code is NNN <span style="color: #7a0874; font-weight: bold;">&#40;</span>octal<span style="color: #7a0874; font-weight: bold;">&#41;</span>.  NNN can be
                <span style="color: #000000;">0</span> to <span style="color: #000000;">3</span> octal digits
&nbsp;
    You can explicitly turn off the interpretation of the above characters
    with the <span style="color: #660033;">-E</span> option.</pre></td></tr></table></div>

<p>我们发现，内建的echo是没有&#8211;help选项的。事实上，它只有三个选项，-neE。</p>
]]></content:encoded>
			<wfw:commentRss>http://www.dutor.net/index.php/2011/03/echo-help-information/feed/</wfw:commentRss>
		<slash:comments>4</slash:comments>
		</item>
		<item>
		<title>[shell]bash脚本学习不完全拾遗</title>
		<link>http://www.dutor.net/index.php/2011/01/bash-pitfalls/</link>
		<comments>http://www.dutor.net/index.php/2011/01/bash-pitfalls/#comments</comments>
		<pubDate>Sun, 30 Jan 2011 07:27:19 +0000</pubDate>
		<dc:creator>dutor</dc:creator>
				<category><![CDATA[Unix/Linux]]></category>
		<category><![CDATA[shell]]></category>

		<guid isPermaLink="false">http://www.dutor.net/?p=2499</guid>
		<description><![CDATA[　　列位，近来俺系统地学习了一下shell编程，好家伙，那可不是一般的纷繁琐碎啊，可谓陷阱重重，防不胜防。摸索中，遇到<a href="http://mywiki.wooledge.org/BashPitfalls" target="_blank">这个页面</a>，总结了Bash编程中的很多陷阱及必要的解决技巧。在这里，结合这本GNU Bash Reference Manual，我有选择地简要地把这些个Pitfalls给您用百姓喜闻乐见的中文展示出来。由于能力有限，我也不是专职的系统管理员，肯定不能详尽地把所有问题都解释清楚，我本人也觉得没有这个必要。仅供参考而已，欢迎指正和补充。
<pre lang="bash" line="1">
for i in *.mp3
do
    COMMANDS
done
# 单行形式就是for i in *.mp3; do COMMANDS; done
# ;只是起到命令和关键字间的分割符的作用，完全可以用换行符来代替
</pre>
]]></description>
			<content:encoded><![CDATA[<p>　　列位，近来俺系统地学习了一下shell编程，好家伙，那可不是一般的纷繁琐碎啊，可谓陷阱重重，防不胜防。摸索中，遇到<a href="http://mywiki.wooledge.org/BashPitfalls" target="_blank">这个页面</a>，总结了Bash编程中的很多陷阱及必要的解决技巧。在这里，结合这本GNU Bash Reference Manual，我有选择地简要地把这些个Pitfalls给您用百姓喜闻乐见的中文展示出来。由于能力有限，我也不是专职的系统管理员，肯定不能详尽地把所有问题都解释清楚，我本人也觉得没有这个必要。仅供参考而已，欢迎指正和补充。</p>
<h4>for i in <b>$(ls *.mp3)</b>; do COMMANDS; done</h4>
<p>这个单行命令的目的对当前目录下的所有mp3文件执行由COMMANDS表示的命令。但这个命令通常达不到预期的效果，至少早我的Music目录下不会成功。我的mp3歌曲中很大一部分是从Google Music上面下载的，绝大部分英文歌曲的文件名中都包含<strong>空格</strong>，即是说，命令替换（command substitution）$(ls *.mp3)的结果可能是这样的：My Love.mp3 Shape of My Heart.mp3。这种情况下，for循环的每次迭代中，变量i的值就不是预期的My Love.mp3和Shape of My Heart.mp3，而分别会是My, Love.mp3, Shape, of, My, Heart.mp3。这样，你就会得到一大堆的No such file or directory的错误信息。为什么会这样呢？这是因为Bash在允许的情况下，会对变量的扩展结果进行分词（word splitting），规则就是根据shell变量IFS的第一个字符（默认为空格）对变量的扩展结果进行分词。<br />
将for循环改成这种形式可以解决分词的问题：</p>

<div class="wp_codebox"><table><tr id="p249925"><td class="line_numbers"><pre>1
2
3
4
5
6
</pre></td><td class="code" id="p2499code25"><pre class="bash" style="font-family:monospace;"><span style="color: #000000; font-weight: bold;">for</span> i <span style="color: #000000; font-weight: bold;">in</span> <span style="color: #000000; font-weight: bold;">*</span>.mp3
<span style="color: #000000; font-weight: bold;">do</span>
    COMMANDS
<span style="color: #000000; font-weight: bold;">done</span>
<span style="color: #666666; font-style: italic;"># 单行形式就是for i in *.mp3; do COMMANDS; done</span>
<span style="color: #666666; font-style: italic;"># ;只是起到命令和关键字间的分割符的作用，完全可以用换行符来代替</span></pre></td></tr></table></div>

<p>　　而这样防止分词是不可行的：</p>

<div class="wp_codebox"><table><tr id="p249926"><td class="line_numbers"><pre>1
2
3
4
</pre></td><td class="code" id="p2499code26"><pre class="bash" style="font-family:monospace;"><span style="color: #000000; font-weight: bold;">for</span> i <span style="color: #000000; font-weight: bold;">in</span> <span style="color: #ff0000;">&quot;<span style="color: #007800;">$(ls *.mp3)</span>&quot;</span>
<span style="color: #000000; font-weight: bold;">do</span>
    COMMANDS
<span style="color: #000000; font-weight: bold;">done</span></pre></td></tr></table></div>

<p>　　原因是这样一来ls的所有输出都会被当成一个文件名赋给变量i，这肯定不是你想要的。但这种防止分词的方法在许多情况下是值得采用的，而且有意识地对变量加上双引号是值得鼓励的。比如在这类命令中：</p>

<div class="wp_codebox"><table><tr id="p249927"><td class="line_numbers"><pre>1
</pre></td><td class="code" id="p2499code27"><pre class="bash" style="font-family:monospace;"><span style="color: #c20cb9; font-weight: bold;">cp</span> <span style="color: #007800;">$foo</span> <span style="color: #007800;">$bar</span></pre></td></tr></table></div>

<p>如果不对foo和bar加引号，当其中包含空格时，会产生意想不到且令人不快的效果。</p>
<h4>for i in <b>$*</b>; do COMMANDS; done</h4>
<p>　　$*是对所有位置参数（从$1开始）的引用，各个参数以IFS分隔，若IFS为空，则所有参数就会粘到一起。在这个for中，如果位置参数中包含空格，同样会产生分词的问题，将$*加引号更不是解决之道。正确的方法是使用$@代替$*，并使用双引号。$@和$*的不同之处在于即使IFS为空，$@中的参数们也不会粘到一起。而且，对$@加引号的效果相当于给个位置参数分别加引号。所以，这样写就能得到预期效果：</p>

<div class="wp_codebox"><table><tr id="p249928"><td class="line_numbers"><pre>1
2
3
4
</pre></td><td class="code" id="p2499code28"><pre class="bash" style="font-family:monospace;"><span style="color: #000000; font-weight: bold;">for</span> i <span style="color: #000000; font-weight: bold;">in</span> <span style="color: #ff0000;">&quot;$@&quot;</span>
<span style="color: #000000; font-weight: bold;">do</span>
    COMMANDS
<span style="color: #000000; font-weight: bold;">done</span></pre></td></tr></table></div>

<p>　　由于对位置参数进行逐一操作是如此的常用，以至于这样写是等效的：</p>

<div class="wp_codebox"><table><tr id="p249929"><td class="line_numbers"><pre>1
2
3
4
</pre></td><td class="code" id="p2499code29"><pre class="bash" style="font-family:monospace;"><span style="color: #000000; font-weight: bold;">for</span> i
<span style="color: #000000; font-weight: bold;">do</span>
    COMMANDS
<span style="color: #000000; font-weight: bold;">done</span></pre></td></tr></table></div>

<h4>&#8216;-&#8217;开头的文件名</h4>
<p>　　这是一个经常被提到的问题，对Linux熟悉的人想必都知道。为命令提供以&#8217;-'开头的参数（argument），会让该命令误以为是为其提供的选项（option），而通常这样的选项是不存在的（存在的话，问题就更隐晦了）。通常有两种解决方法，连续使用两个&#8217;-'，告诉该命令（还是shell？）后面都是参数，没选项了。另外一种方法就是为文件名（如果该参数是文件的话）加上路径。</p>

<div class="wp_codebox"><table><tr id="p249930"><td class="line_numbers"><pre>1
2
3
</pre></td><td class="code" id="p2499code30"><pre class="bash" style="font-family:monospace;"><span style="color: #c20cb9; font-weight: bold;">cp</span> <span style="color: #660033;">-foo</span> bar <span style="color: #666666; font-style: italic;"># Wrong</span>
<span style="color: #c20cb9; font-weight: bold;">cp</span> <span style="color: #660033;">--</span> <span style="color: #660033;">-foo</span> bar <span style="color: #666666; font-style: italic;"># OK</span>
<span style="color: #c20cb9; font-weight: bold;">cp</span> .<span style="color: #000000; font-weight: bold;">/</span>-foo bar <span style="color: #666666; font-style: italic;"># OK</span></pre></td></tr></table></div>

<p>　　另外，使用GDB调试程序时，可能需要向被调试程序传递参数。</p>

<div class="wp_codebox"><table><tr id="p249931"><td class="line_numbers"><pre>1
</pre></td><td class="code" id="p2499code31"><pre class="bash" style="font-family:monospace;"><span style="color: #c20cb9; font-weight: bold;">gdb</span> a.out arg1 arg2</pre></td></tr></table></div>

<p>这样是不行的，因为arg1, arg2会被当作传递给GDB的参数。GDB并不理会&#8211;，而是有自己的方法来被告知结束参数扫描，即使用&#8211;args或-args选项，</p>

<div class="wp_codebox"><table><tr id="p249932"><td class="line_numbers"><pre>1
</pre></td><td class="code" id="p2499code32"><pre class="bash" style="font-family:monospace;"><span style="color: #c20cb9; font-weight: bold;">gdb</span> <span style="color: #660033;">--args</span> a.out arg1 arg2</pre></td></tr></table></div>

<p>　　针对gdb，向被调试程序传递参数更好的方法是通过进入gdb后run或start命令来进行。</p>
<h4>&#8216;['是一个命令</h4>
<p>　　当[与if相遇，而且由于它们是如此频繁地相遇，以至于'['经常被误认为是条件表达式if的一部分。事实上，if的标准结构是这样的：</p>

<div class="wp_codebox"><table><tr id="p249933"><td class="line_numbers"><pre>1
2
3
4
5
6
7
8
</pre></td><td class="code" id="p2499code33"><pre class="bash" style="font-family:monospace;"><span style="color: #000000; font-weight: bold;">if</span> COMMANDS
<span style="color: #000000; font-weight: bold;">then</span>              <span style="color: #666666; font-style: italic;"># 必要的</span>
    SOME COMMANDS
<span style="color: #000000; font-weight: bold;">elif</span> COMMANDS     <span style="color: #666666; font-style: italic;"># 可选，且可有多个</span>
    OTHER COMMANDS
<span style="color: #000000; font-weight: bold;">else</span>              <span style="color: #666666; font-style: italic;"># 可选，但只能有一个</span>
    ELSE COMMANDS
<span style="color: #000000; font-weight: bold;">fi</span>                <span style="color: #666666; font-style: italic;"># 必要的</span></pre></td></tr></table></div>

<p>　　注意，这里并没有'['。if和elif只是根据其后的命令（组）的退出状态（exit status）来判断是否进入相应的区块。因此，在语句if [ CONDITONAL EXPRESSION ]; then COMMANDS; fi中，&#8217;[]&#8216;并不是为了组织CONDITIONAL EXPRESSION，而是为了测试其有效性。&#8217;['是shell的一个内建命令（builtin command），等价与test命令，只是'['的最后一个参数必须是']&#8216;罢了。<br />
　　正因为&#8217;['是一个命令，所以它与参数、参数之间必须是相互分开的。比如[$foo=bar], [ $foo=bar ], [ $foo =bar ]都是不正确的，[ $foo = bar ]才是正确的，因为这里$foo, =, bar, ]均是&#8217;['的参数。</p>
<h4>'['与'[['的区别</h4>
<p>　　首先，'['是一个命令，'[['是一个shell关键字：</p>

<div class="wp_codebox"><table><tr id="p249934"><td class="line_numbers"><pre>1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
</pre></td><td class="code" id="p2499code34"><pre class="bash" style="font-family:monospace;">$ <span style="color: #7a0874; font-weight: bold;">type</span> <span style="color: #7a0874; font-weight: bold;">&#91;</span>
<span style="color: #7a0874; font-weight: bold;">&#91;</span> is a shell <span style="color: #7a0874; font-weight: bold;">builtin</span>
$ <span style="color: #7a0874; font-weight: bold;">type</span> <span style="color: #7a0874; font-weight: bold;">&#91;</span><span style="color: #7a0874; font-weight: bold;">&#91;</span>
<span style="color: #7a0874; font-weight: bold;">&#91;</span><span style="color: #7a0874; font-weight: bold;">&#91;</span> is a shell keyword
$ <span style="color: #7a0874; font-weight: bold;">&#91;</span> <span style="color: #666666; font-style: italic;"># 参数错误</span>
<span style="color: #000000; font-weight: bold;">/</span>bin<span style="color: #000000; font-weight: bold;">/</span><span style="color: #c20cb9; font-weight: bold;">bash</span>: line <span style="color: #000000;">0</span>: <span style="color: #7a0874; font-weight: bold;">&#91;</span>: missing <span style="color: #000000; font-weight: bold;">`</span><span style="color: #7a0874; font-weight: bold;">&#93;</span><span style="color: #ff0000;">'
$ echo $?
2
$ [ ]
$ echo $? # 参数为空（除了'</span><span style="color: #7a0874; font-weight: bold;">&#93;</span><span style="color: #ff0000;">'），估值为1
1
$ [[ # 回车
&gt;foo ]] # PS2
$ echo $? # foo为非空string，估值为0
0</span></pre></td></tr></table></div>

<p>　　其次，'[ ]&#8216;和&#8217;[[ ]]&#8217;内均可以使用条件表达式（conditional expression）。常见的条件表达式包括：字符串比较&#8217;=', &#8216;>&#8217;, &#8216;<', '!='之类，文件测试'-f', '-d', '-z'之类, 以及逻辑关系'-a', '-o'之类，算数比较'-eq', '-le', '-gt'之类，还包括字符串本身（串为空时估值为1）。另外，在'[[ ]]'中，还可以使用'=='和'=~'进行字符串的模式匹配，右侧为模式串，左侧为待匹配串。'=='与'=~'的区别在于，前者为普通匹配，后者为扩展的正则匹配，比如*在两种匹配模式中的含义是不同的：</p>

<div class="wp_codebox"><table><tr id="p249935"><td class="line_numbers"><pre>1
2
3
4
5
6
7
8
9
10
</pre></td><td class="code" id="p2499code35"><pre class="bash" style="font-family:monospace;">$ <span style="color: #007800;">s</span>=foo
$ <span style="color: #7a0874; font-weight: bold;">&#91;</span><span style="color: #7a0874; font-weight: bold;">&#91;</span> <span style="color: #007800;">$s</span> == <span style="color: #000000; font-weight: bold;">*</span>o <span style="color: #7a0874; font-weight: bold;">&#93;</span><span style="color: #7a0874; font-weight: bold;">&#93;</span>
$ <span style="color: #7a0874; font-weight: bold;">echo</span> <span style="color: #007800;">$?</span>
<span style="color: #000000;">0</span> <span style="color: #666666; font-style: italic;"># 匹配成功</span>
$ <span style="color: #7a0874; font-weight: bold;">&#91;</span><span style="color: #7a0874; font-weight: bold;">&#91;</span> <span style="color: #007800;">$s</span> =~ <span style="color: #000000; font-weight: bold;">*</span>o <span style="color: #7a0874; font-weight: bold;">&#93;</span><span style="color: #7a0874; font-weight: bold;">&#93;</span>
$ <span style="color: #7a0874; font-weight: bold;">echo</span> <span style="color: #007800;">$?</span>
<span style="color: #000000;">2</span> <span style="color: #666666; font-style: italic;"># 匹配失败</span>
$ <span style="color: #7a0874; font-weight: bold;">&#91;</span><span style="color: #7a0874; font-weight: bold;">&#91;</span> <span style="color: #007800;">$s</span> =~ .<span style="color: #000000; font-weight: bold;">*</span>o <span style="color: #7a0874; font-weight: bold;">&#93;</span><span style="color: #7a0874; font-weight: bold;">&#93;</span>
$ <span style="color: #7a0874; font-weight: bold;">echo</span> <span style="color: #007800;">$?</span>
<span style="color: #000000;">0</span> <span style="color: #666666; font-style: italic;"># 匹配成功</span></pre></td></tr></table></div>

<p>　　&#8217;[ ]&#8216;内不可以使用&#038;&#038;, ||，而&#8217;[[ ]]&#8217;可以。即&#8217;[ a &#038;&#038; b ]&#8216;不行，&#8217;[[ a &#038;&#038; b ]]&#8217;行，但&#8217;[ ] &#038;&#038; [ ]&#8216;的形式是可行的<br />
　　还有就是，Bash会对&#8217;[ ]&#8216;内的变量进行分词，却不对&#8217;[[ ]]&#8217;进行分词：</p>

<div class="wp_codebox"><table><tr id="p249936"><td class="line_numbers"><pre>1
2
3
4
5
6
</pre></td><td class="code" id="p2499code36"><pre class="bash" style="font-family:monospace;">$ <span style="color: #007800;">s</span>=<span style="color: #ff0000;">&quot;a b&quot;</span>
$ <span style="color: #7a0874; font-weight: bold;">&#91;</span> <span style="color: #007800;">$s</span> = <span style="color: #ff0000;">&quot;a b&quot;</span> <span style="color: #7a0874; font-weight: bold;">&#93;</span>
<span style="color: #c20cb9; font-weight: bold;">bash</span>: <span style="color: #7a0874; font-weight: bold;">&#91;</span>: too many arguments
$ <span style="color: #7a0874; font-weight: bold;">&#91;</span><span style="color: #7a0874; font-weight: bold;">&#91;</span> <span style="color: #007800;">$s</span> = <span style="color: #ff0000;">&quot;a b&quot;</span> <span style="color: #7a0874; font-weight: bold;">&#93;</span><span style="color: #7a0874; font-weight: bold;">&#93;</span>
$ <span style="color: #7a0874; font-weight: bold;">echo</span> <span style="color: #007800;">$?</span>
<span style="color: #000000;">0</span></pre></td></tr></table></div>

<h4>cd dir; rm files</h4>
<p>　　这条命令的目的是进入目录dir，然后删除一些文件。如果由于某种原因cd失败了，rm还会接着执行，可能就坏事儿了。本人曾经将/etc/passwd mv到另一个地方，然后就悲剧了……<br />
为防止这类失误，在执行一些危险性动作之前，务必要检查先前的命令是否成功执行了。这里，将&#8217;;'换作&#038;&#038;即可。</p>
<h4>$foo=bar</h4>
<p>　　如果变量foo保存的值为FOO，那么实际上这里真正执行的是FOO=bar。shell中赋值不需要使用&#8217;$'，只有当&#8221;取&#8221;值时才需要使用&#8217;$'。同样的道理read $foo;通常也是不正确的。<br />
关于赋值，需要知道&#8217;='两侧不允许有空格，例如foo= bar会被shell当作一次命令的执行，命令名是foo=通常是不存在的，bar作为其参数。</p>
<h4> cat file | sed &#8216;s/foo/bar/g&#8217; > file</h4>
<p>　　这条命令的目的是将文件file中所有的foo替换为bar, 但实际上该命令并没有按照预想有cat将file内容打印到sed的标准输入，执行替换后将结果再次保存到file。事实上，sed并没有处理任何数据，在管道建立时file就被截为空文件了。<br />
解决方法就是利用中间/临时文件，</p>

<div class="wp_codebox"><table><tr id="p249937"><td class="line_numbers"><pre>1
2
</pre></td><td class="code" id="p2499code37"><pre class="bash" style="font-family:monospace;"><span style="color: #c20cb9; font-weight: bold;">cat</span> <span style="color: #c20cb9; font-weight: bold;">file</span> <span style="color: #000000; font-weight: bold;">|</span> <span style="color: #c20cb9; font-weight: bold;">sed</span> <span style="color: #ff0000;">'s/foo/bar/g'</span> <span style="color: #000000; font-weight: bold;">&gt;</span>tmp
<span style="color: #c20cb9; font-weight: bold;">mv</span> tmp <span style="color: #c20cb9; font-weight: bold;">file</span></pre></td></tr></table></div>

<p>　　更方便的是使用sed的-i选项</p>

<div class="wp_codebox"><table><tr id="p249938"><td class="line_numbers"><pre>1
</pre></td><td class="code" id="p2499code38"><pre class="bash" style="font-family:monospace;"><span style="color: #c20cb9; font-weight: bold;">sed</span> <span style="color: #660033;">-i</span> <span style="color: #ff0000;">'s/foo/bar/g'</span> <span style="color: #c20cb9; font-weight: bold;">file</span></pre></td></tr></table></div>

<p>　　事实上，sed -i也利用了临时文件，只是对用户透明罢了。<br />
　　不要在管道不同命令中读写同一文件。</p>
<h4>echo &lt;&lt;EOF</h4>

<div class="wp_codebox"><table><tr id="p249939"><td class="line_numbers"><pre>1
2
3
4
</pre></td><td class="code" id="p2499code39"><pre class="bash" style="font-family:monospace;"><span style="color: #007800;">$echo</span> <span style="color: #cc0000; font-style: italic;">&lt;&lt;EOF
Hello,
    World
EOF</span></pre></td></tr></table></div>

<p>　　立即文档(here document)提供了一种将大块的字符串连接到命令的标准输入的方法。当不幸的是echo 并不从标准输入读取数据。在这里，可以使用cat代替echo.</p>
<h4>for i in {1..$n}; do COMMANDS; done</h4>
<p>　　这里，本意是将i从1到$n迭代$n次。但这行命令无法工作，因为大括号扩展(braces expansion)先于参数扩展（parameter expansion）进行。然而，对{1..$n}进行大括号扩展时，由于1是数字而$不是数字而无法扩展，无法扩展的式子会被保留，稍后$n才会被扩展。</p>

<div class="wp_codebox"><table><tr id="p249940"><td class="line_numbers"><pre>1
2
3
4
5
</pre></td><td class="code" id="p2499code40"><pre class="bash" style="font-family:monospace;">$ <span style="color: #7a0874; font-weight: bold;">echo</span> <span style="color: #7a0874; font-weight: bold;">&#123;</span>01..10<span style="color: #7a0874; font-weight: bold;">&#125;</span>
01 02 03 04 05 06 07 08 09 <span style="color: #000000;">10</span>
$ <span style="color: #007800;">n</span>=<span style="color: #000000;">10</span>
$ <span style="color: #7a0874; font-weight: bold;">echo</span> <span style="color: #7a0874; font-weight: bold;">&#123;</span>01..<span style="color: #007800;">$n</span><span style="color: #7a0874; font-weight: bold;">&#125;</span>
<span style="color: #7a0874; font-weight: bold;">&#123;</span>01..10<span style="color: #7a0874; font-weight: bold;">&#125;</span></pre></td></tr></table></div>

<p>　　解决方法是使用for的另外一种形式,</p>

<div class="wp_codebox"><table><tr id="p249941"><td class="line_numbers"><pre>1
2
3
4
</pre></td><td class="code" id="p2499code41"><pre class="bash" style="font-family:monospace;"><span style="color: #000000; font-weight: bold;">for</span> <span style="color: #7a0874; font-weight: bold;">&#40;</span><span style="color: #7a0874; font-weight: bold;">&#40;</span><span style="color: #007800;">i</span>=<span style="color: #000000;">0</span>; i <span style="color: #000000; font-weight: bold;">&lt;</span>= n; ++i<span style="color: #7a0874; font-weight: bold;">&#41;</span><span style="color: #7a0874; font-weight: bold;">&#41;</span>
<span style="color: #000000; font-weight: bold;">do</span>
    COMMANDS
<span style="color: #000000; font-weight: bold;">done</span></pre></td></tr></table></div>

<h4>echo &#8220;~&#8221;</h4>
<p>　　这里涉及到~扩展（Tilde expansion），~会被扩展为当前用户的用户目录，&#8221;值&#8221;相当于$HOME，~user被扩展为user的用户目录。但当~在引号中时，将不被扩展，因此echo &#8220;~&#8221;仅仅输出&#8217;~'，此时应使用$HOME代替。</p>
<p>　　先就这样吧，shell这东西语法太过琐碎和诡异，写写简单的实用脚本还行，比较大的程序还是使用Python这类脚本比较方便。但使用Shell脚本的最大好处就是可以更有效地利用其它功能强大的命令，比如grep,sed,awk,find。通过管道，可以将这些工具有机的组合起来，shell脚本为这种组合操作提供了逻辑和流程控制。do one thing, do it better.</p>
]]></content:encoded>
			<wfw:commentRss>http://www.dutor.net/index.php/2011/01/bash-pitfalls/feed/</wfw:commentRss>
		<slash:comments>2</slash:comments>
		</item>
		<item>
		<title>守护进程的单例运行</title>
		<link>http://www.dutor.net/index.php/2010/09/daemon-process-singleton/</link>
		<comments>http://www.dutor.net/index.php/2010/09/daemon-process-singleton/#comments</comments>
		<pubDate>Tue, 14 Sep 2010 14:50:12 +0000</pubDate>
		<dc:creator>dutor</dc:creator>
				<category><![CDATA[Unix/Linux]]></category>
		<category><![CDATA[边走编程]]></category>
		<category><![CDATA[守护进程]]></category>

		<guid isPermaLink="false">http://www.dutor.net/?p=2432</guid>
		<description><![CDATA[　　由于<a href="http://www.dutor.net/index.php/2010/09/daemon-process/" target="_blank">守护进程</a>在后台运行，为系统或用户提供某种服务，因此通常只需要一个运行实例就可以了，而且在大部分情况下只能有一个实例在运行。例如cron进程，若有多个实例在运行，那么各个实例都会根据crontab执行一份用户指定的任务，岂不是乱了套了？还有其他很多守护进程是设备相关的，而这些设备有很可能是非共享的，所以这样的守护进程也不能运行多个。
　　文件锁和记录锁机制是一种实现守护进程单例运行的方法。如果每一个守护进程创建一个文件，并且在整个文件上加上一把锁，那就只允许创建一把这样的写锁，所以在此之后试图再创建一把这样的写锁就会失败，以此向后续守护进程的副本指明已经存在一个正在运行的副本了。守护进程终止时，这把锁将被自动删除。
<pre lang="c" line="1">
int
lockfile(int fd) //~ try to lock the file, affecting errno when it fails.
{
    struct flock fk;
    fk.l_type = F_WRLCK;
    fk.l_start = 0;
    fk.l_whence = SEEK_SET;
    fk.l_len = 0;
    return (fcntl(fd, F_SETLK, &#038;fk));
}
</pre>]]></description>
			<content:encoded><![CDATA[<p>　　由于<a href="http://www.dutor.net/index.php/2010/09/daemon-process/" target="_blank">守护进程</a>在后台运行，为系统或用户提供某种服务，因此通常只需要一个运行实例就可以了，而且在大部分情况下只能有一个实例在运行。例如cron进程，若有多个实例在运行，那么各个实例都会根据crontab执行一份用户指定的任务，岂不是乱了套了？还有其他很多守护进程是设备相关的，而这些设备有很可能是非共享的，所以这样的守护进程也不能运行多个。<br />
　　文件锁和记录锁机制是一种实现守护进程单例运行的方法。如果每一个守护进程创建一个文件，并且在整个文件上加上一把锁，那就只允许创建一把这样的写锁，所以在此之后试图再创建一把这样的写锁就会失败，以此向后续守护进程的副本指明已经存在一个正在运行的副本了。守护进程终止时，这把锁将被自动删除。</p>

<div class="wp_codebox"><table><tr id="p243242"><td class="line_numbers"><pre>1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
</pre></td><td class="code" id="p2432code42"><pre class="c" style="font-family:monospace;"><span style="color: #993333;">int</span>
lockfile<span style="color: #009900;">&#40;</span><span style="color: #993333;">int</span> fd<span style="color: #009900;">&#41;</span> <span style="color: #666666; font-style: italic;">//~ try to lock the file, affecting errno when it fails.</span>
<span style="color: #009900;">&#123;</span>
    <span style="color: #993333;">struct</span> flock fk<span style="color: #339933;">;</span>
    fk.<span style="color: #202020;">l_type</span> <span style="color: #339933;">=</span> F_WRLCK<span style="color: #339933;">;</span>
    fk.<span style="color: #202020;">l_start</span> <span style="color: #339933;">=</span> <span style="color: #0000dd;">0</span><span style="color: #339933;">;</span>
    fk.<span style="color: #202020;">l_whence</span> <span style="color: #339933;">=</span> SEEK_SET<span style="color: #339933;">;</span>
    fk.<span style="color: #202020;">l_len</span> <span style="color: #339933;">=</span> <span style="color: #0000dd;">0</span><span style="color: #339933;">;</span>
    <span style="color: #b1b100;">return</span> <span style="color: #009900;">&#40;</span>fcntl<span style="color: #009900;">&#40;</span>fd<span style="color: #339933;">,</span> F_SETLK<span style="color: #339933;">,</span> <span style="color: #339933;">&amp;</span>fk<span style="color: #009900;">&#41;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
<span style="color: #009900;">&#125;</span>
&nbsp;
<span style="color: #993333;">int</span>
already_running<span style="color: #009900;">&#40;</span><span style="color: #993333;">const</span> <span style="color: #993333;">char</span><span style="color: #339933;">*</span> fname<span style="color: #009900;">&#41;</span> <span style="color: #666666; font-style: italic;">//~ return 1, if another daemon is running</span>
<span style="color: #009900;">&#123;</span>
    <span style="color: #993333;">int</span> fd<span style="color: #339933;">;</span>
    fd <span style="color: #339933;">=</span> open<span style="color: #009900;">&#40;</span>fname<span style="color: #339933;">,</span> O_RDWR<span style="color: #339933;">|</span>O_CREAT<span style="color: #339933;">,</span> S_IRUSR<span style="color: #339933;">|</span>S_IWUSR<span style="color: #339933;">|</span>S_IRGRP<span style="color: #339933;">|</span>S_IROTH<span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
    <span style="color: #b1b100;">if</span><span style="color: #009900;">&#40;</span> fd <span style="color: #339933;">&lt;</span> <span style="color: #0000dd;">0</span> <span style="color: #009900;">&#41;</span>
    <span style="color: #009900;">&#123;</span>
        <span style="color: #666666; font-style: italic;">//~ in daemon process, you should use syslog, instead of stdout, for logging</span>
        <span style="color: #666666; font-style: italic;">//~ syslog(LOG_ERR, &quot;cannot open %s: %s&quot;, fname, strerror(errno));</span>
        fprintf<span style="color: #009900;">&#40;</span>stdout<span style="color: #339933;">,</span> <span style="color: #ff0000;">&quot;cannot open %s: %s&quot;</span><span style="color: #339933;">,</span> fname<span style="color: #339933;">,</span> strerror<span style="color: #009900;">&#40;</span>errno<span style="color: #009900;">&#41;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
        fflush<span style="color: #009900;">&#40;</span>stdout<span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
        exit<span style="color: #009900;">&#40;</span><span style="color: #0000dd;">1</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
    <span style="color: #009900;">&#125;</span>
    <span style="color: #b1b100;">if</span><span style="color: #009900;">&#40;</span> lockfile<span style="color: #009900;">&#40;</span>fd<span style="color: #009900;">&#41;</span> <span style="color: #339933;">&lt;</span> <span style="color: #0000dd;">0</span> <span style="color: #009900;">&#41;</span>
    <span style="color: #009900;">&#123;</span>
        <span style="color: #b1b100;">if</span><span style="color: #009900;">&#40;</span> errno <span style="color: #339933;">==</span> EACCES <span style="color: #339933;">||</span> errno <span style="color: #339933;">==</span> EAGAIN <span style="color: #009900;">&#41;</span>
        <span style="color: #009900;">&#123;</span>
            <span style="color: #666666; font-style: italic;">//~ syslog(LOG_ERR, &quot;cannot lock %s: %s&quot;, fname, strerror(errno));</span>
            fprintf<span style="color: #009900;">&#40;</span>stdout<span style="color: #339933;">,</span> <span style="color: #ff0000;">&quot;cannot lock %s: %s&quot;</span><span style="color: #339933;">,</span> fname<span style="color: #339933;">,</span> strerror<span style="color: #009900;">&#40;</span>errno<span style="color: #009900;">&#41;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
            close<span style="color: #009900;">&#40;</span>fd<span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
            <span style="color: #b1b100;">return</span> <span style="color: #0000dd;">1</span><span style="color: #339933;">;</span>
        <span style="color: #009900;">&#125;</span>
        <span style="color: #666666; font-style: italic;">//~ syslog(LOG_ERR, &quot;cannot lock %s: %s&quot;, fname, strerror(errno));</span>
        fprintf<span style="color: #009900;">&#40;</span>stdout<span style="color: #339933;">,</span> <span style="color: #ff0000;">&quot;cannot lock %s: %s&quot;</span><span style="color: #339933;">,</span> fname<span style="color: #339933;">,</span> strerror<span style="color: #009900;">&#40;</span>errno<span style="color: #009900;">&#41;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
        fflush<span style="color: #009900;">&#40;</span>stdout<span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
        exit<span style="color: #009900;">&#40;</span><span style="color: #0000dd;">1</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
    <span style="color: #009900;">&#125;</span>
    ftruncate<span style="color: #009900;">&#40;</span>fd<span style="color: #339933;">,</span> <span style="color: #0000dd;">0</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
    <span style="color: #993333;">char</span> buf<span style="color: #009900;">&#91;</span><span style="color: #0000dd;">16</span><span style="color: #009900;">&#93;</span><span style="color: #339933;">;</span>
    sprintf<span style="color: #009900;">&#40;</span>buf<span style="color: #339933;">,</span> <span style="color: #ff0000;">&quot;%ld&quot;</span><span style="color: #339933;">,</span> <span style="color: #009900;">&#40;</span><span style="color: #993333;">long</span><span style="color: #009900;">&#41;</span>getpid<span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
    write<span style="color: #009900;">&#40;</span>fd<span style="color: #339933;">,</span> buf<span style="color: #339933;">,</span> strlen<span style="color: #009900;">&#40;</span>buf<span style="color: #009900;">&#41;</span> <span style="color: #339933;">+</span> <span style="color: #0000dd;">1</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
    <span style="color: #b1b100;">return</span> <span style="color: #0000dd;">0</span><span style="color: #339933;">;</span>
<span style="color: #009900;">&#125;</span></pre></td></tr></table></div>

]]></content:encoded>
			<wfw:commentRss>http://www.dutor.net/index.php/2010/09/daemon-process-singleton/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Linux中实现30分钟无操作自动关机</title>
		<link>http://www.dutor.net/index.php/2010/09/linux-auto-halt/</link>
		<comments>http://www.dutor.net/index.php/2010/09/linux-auto-halt/#comments</comments>
		<pubDate>Wed, 08 Sep 2010 23:30:34 +0000</pubDate>
		<dc:creator>dutor</dc:creator>
				<category><![CDATA[Unix/Linux]]></category>
		<category><![CDATA[边走编程]]></category>
		<category><![CDATA[多线程]]></category>
		<category><![CDATA[守护进程]]></category>

		<guid isPermaLink="false">http://www.dutor.net/?p=2418</guid>
		<description><![CDATA[　　<a href="http://www.dutor.net/index.php/2010/09/daemon-process/" target="_blank">上一篇简要介绍了守护进程</a>，现在就来实践一下，写一个自动关机的小程序。该程序可以守护进程的方式运行，当用户在一定时间（比如30分钟）没有鼠标和键盘操作后就会自动关机。
　　这个程序利用了上篇文章中实现的daemonize函数，为程序创建了守护进程所需要的运行环境。
　　由于需要同时监听鼠标和键盘操作，所以需要采用多线程的方式来实现。其中两个线程分别监视鼠标和键盘，一旦检测到相应动作（鼠标点击和移动、击键等），全局时间戳stamp（time_t）就会被设成当前时间。主线程每隔一定时间（比如1秒）检查stamp，若当前时间值（time(NULL)）比stamp大30*60，则执行停机操作（使用system函数执行init 0命令，或者使用reboot函数）。
　　需要说明的是，共享变量stamp需要互斥地访问。另外，对鼠标事件的监听是借助于对设备文件/dev/input/mice的读取（阻塞方式），键盘的监听借助于对/dev/input/event3的阻塞读取，但我猜想在不同机器上可能会是其它诸如event0,event5之类的文件。
　　不足之处在于，无法对全屏模式进行判断，即是说，如果你全屏看一部较长的电影，可能会被关机……
　　如果你有好的方法来实现本文的功能，还请不吝赐教！]]></description>
			<content:encoded><![CDATA[<p>　　<a href="http://www.dutor.net/index.php/2010/09/daemon-process/" target="_blank">上一篇简要介绍了守护进程</a>，现在就来实践一下，写一个自动关机的小程序。该程序可以守护进程的方式运行，当用户在一定时间（比如30分钟）没有鼠标和键盘操作后就会自动关机。<br />
　　这个程序利用了上篇文章中实现的daemonize函数，为程序创建了守护进程所需要的运行环境。<br />
　　由于需要同时监听鼠标和键盘操作，所以需要采用多线程的方式来实现。其中两个线程分别监视鼠标和键盘，一旦检测到相应动作（鼠标点击和移动、击键等），全局时间戳stamp（time_t）就会被设成当前时间。主线程每隔一定时间（比如1秒）检查stamp，若当前时间值（time(NULL)）比stamp大30*60，则执行停机操作（使用system函数执行init 0命令，或者使用reboot函数）。</p>

<div class="wp_codebox"><table><tr id="p241843"><td class="line_numbers"><pre>1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
</pre></td><td class="code" id="p2418code43"><pre class="c" style="font-family:monospace;"><span style="color: #339933;">#include &lt;stdio.h&gt;</span>
<span style="color: #339933;">#include &lt;stdlib.h&gt;</span>
<span style="color: #339933;">#include &lt;unistd.h&gt;</span>
<span style="color: #339933;">#include &lt;sys/types.h&gt;</span>
<span style="color: #339933;">#include &lt;fcntl.h&gt; //~ O_RDWR, S_IRWXU etc.</span>
<span style="color: #339933;">#include &lt;pthread.h&gt;</span>
<span style="color: #339933;">#include &lt;time.h&gt;</span>
<span style="color: #339933;">#include &lt;limits.h&gt;</span>
<span style="color: #339933;">#include &lt;signal.h&gt;</span>
&nbsp;
<span style="color: #993333;">void</span> daemonize<span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
&nbsp;
<span style="color: #666666; font-style: italic;">//~ thread functions</span>
<span style="color: #993333;">void</span> <span style="color: #339933;">*</span>listen_ms<span style="color: #009900;">&#40;</span><span style="color: #993333;">void</span> <span style="color: #339933;">*</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
<span style="color: #993333;">void</span> <span style="color: #339933;">*</span>listen_kb<span style="color: #009900;">&#40;</span><span style="color: #993333;">void</span> <span style="color: #339933;">*</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
&nbsp;
<span style="color: #666666; font-style: italic;">//~ time stamp, keeping the time</span>
<span style="color: #666666; font-style: italic;">//~ when the last KB or Mouse event happened.</span>
<span style="color: #993333;">volatile</span> time_t stamp<span style="color: #339933;">;</span>
&nbsp;
<span style="color: #666666; font-style: italic;">//~ mutex keeping stamp consistent.</span>
pthread_mutex_t stamp_mutex<span style="color: #339933;">;</span>
&nbsp;
<span style="color: #993333;">int</span>
main<span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span>
<span style="color: #009900;">&#123;</span>
    daemonize<span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
    <span style="color: #666666; font-style: italic;">//~ initialize the mutex, stamp</span>
    pthread_mutex_init<span style="color: #009900;">&#40;</span><span style="color: #339933;">&amp;</span>stamp_mutex<span style="color: #339933;">,</span> NULL<span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
    <span style="color: #666666; font-style: italic;">//time(&amp;stamp);</span>
    stamp <span style="color: #339933;">=</span> time<span style="color: #009900;">&#40;</span>NULL<span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
&nbsp;
    <span style="color: #666666; font-style: italic;">//~ create two threads monitoring the Mouse and Keyboard.</span>
    pthread_t ms_tid<span style="color: #339933;">,</span> kb_tid<span style="color: #339933;">;</span>
    <span style="color: #b1b100;">if</span><span style="color: #009900;">&#40;</span>pthread_create<span style="color: #009900;">&#40;</span><span style="color: #339933;">&amp;</span>ms_tid<span style="color: #339933;">,</span> NULL<span style="color: #339933;">,</span> listen_ms<span style="color: #339933;">,</span> NULL<span style="color: #009900;">&#41;</span> <span style="color: #339933;">!=</span> <span style="color: #0000dd;">0</span><span style="color: #009900;">&#41;</span>
    <span style="color: #009900;">&#123;</span>
        perror<span style="color: #009900;">&#40;</span><span style="color: #ff0000;">&quot;pthread_create&quot;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
        exit<span style="color: #009900;">&#40;</span><span style="color: #0000dd;">1</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
    <span style="color: #009900;">&#125;</span>
    <span style="color: #b1b100;">if</span><span style="color: #009900;">&#40;</span>pthread_create<span style="color: #009900;">&#40;</span><span style="color: #339933;">&amp;</span>kb_tid<span style="color: #339933;">,</span> NULL<span style="color: #339933;">,</span> listen_kb<span style="color: #339933;">,</span> NULL<span style="color: #009900;">&#41;</span> <span style="color: #339933;">!=</span> <span style="color: #0000dd;">0</span><span style="color: #009900;">&#41;</span>
    <span style="color: #009900;">&#123;</span>
        perror<span style="color: #009900;">&#40;</span><span style="color: #ff0000;">&quot;pthread_create&quot;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
        exit<span style="color: #009900;">&#40;</span><span style="color: #0000dd;">1</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
    <span style="color: #009900;">&#125;</span>
&nbsp;
    <span style="color: #993333;">unsigned</span> <span style="color: #993333;">int</span> interval <span style="color: #339933;">=</span> <span style="color: #0000dd;">60</span> <span style="color: #339933;">*</span> <span style="color: #0000dd;">30</span><span style="color: #339933;">;</span>
    <span style="color: #b1b100;">while</span><span style="color: #009900;">&#40;</span><span style="color: #0000dd;">1</span><span style="color: #009900;">&#41;</span>
    <span style="color: #009900;">&#123;</span>
        sleep<span style="color: #009900;">&#40;</span><span style="color: #0000dd;">1</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
        pthread_mutex_lock<span style="color: #009900;">&#40;</span><span style="color: #339933;">&amp;</span>stamp_mutex<span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
        <span style="color: #b1b100;">if</span><span style="color: #009900;">&#40;</span> time<span style="color: #009900;">&#40;</span>NULL<span style="color: #009900;">&#41;</span> <span style="color: #339933;">-</span> stamp <span style="color: #339933;">&gt;</span> interval <span style="color: #009900;">&#41;</span>
        <span style="color: #009900;">&#123;</span>
            <span style="color: #808080; font-style: italic;">/*printf(&quot;shutdown\n&quot;);*/</span>
            <span style="color: #808080; font-style: italic;">/*fflush(stdin);*/</span>
            system<span style="color: #009900;">&#40;</span><span style="color: #ff0000;">&quot;init 0&quot;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
        <span style="color: #009900;">&#125;</span>
        pthread_mutex_unlock<span style="color: #009900;">&#40;</span><span style="color: #339933;">&amp;</span>stamp_mutex<span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
    <span style="color: #009900;">&#125;</span>
    <span style="color: #666666; font-style: italic;">//~ join the threads, though it'll never be excuted.</span>
    pthread_join<span style="color: #009900;">&#40;</span>ms_tid<span style="color: #339933;">,</span> NULL<span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
    pthread_join<span style="color: #009900;">&#40;</span>kb_tid<span style="color: #339933;">,</span> NULL<span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
&nbsp;
    <span style="color: #b1b100;">return</span> <span style="color: #0000dd;">0</span><span style="color: #339933;">;</span>
<span style="color: #009900;">&#125;</span>
&nbsp;
<span style="color: #993333;">void</span> <span style="color: #339933;">*</span>
listen_ms<span style="color: #009900;">&#40;</span><span style="color: #993333;">void</span> <span style="color: #339933;">*</span> arg<span style="color: #009900;">&#41;</span>
<span style="color: #009900;">&#123;</span>
    <span style="color: #993333;">int</span> fd <span style="color: #339933;">=</span> open<span style="color: #009900;">&#40;</span><span style="color: #ff0000;">&quot;/dev/input/mice&quot;</span><span style="color: #339933;">,</span> O_RDONLY<span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
    <span style="color: #b1b100;">if</span><span style="color: #009900;">&#40;</span>fd <span style="color: #339933;">&lt;</span> <span style="color: #0000dd;">0</span><span style="color: #009900;">&#41;</span>
    <span style="color: #009900;">&#123;</span>
        perror<span style="color: #009900;">&#40;</span><span style="color: #ff0000;">&quot;open mice&quot;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
        exit<span style="color: #009900;">&#40;</span><span style="color: #0000dd;">1</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
    <span style="color: #009900;">&#125;</span>
    <span style="color: #993333;">char</span> buf<span style="color: #009900;">&#91;</span><span style="color: #0000dd;">256</span><span style="color: #009900;">&#93;</span><span style="color: #339933;">;</span>
    <span style="color: #b1b100;">while</span><span style="color: #009900;">&#40;</span> read<span style="color: #009900;">&#40;</span>fd<span style="color: #339933;">,</span> buf<span style="color: #339933;">,</span> <span style="color: #993333;">sizeof</span><span style="color: #009900;">&#40;</span>buf<span style="color: #009900;">&#41;</span><span style="color: #009900;">&#41;</span> <span style="color: #339933;">&gt;</span> <span style="color: #0000dd;">0</span> <span style="color: #009900;">&#41;</span>
    <span style="color: #009900;">&#123;</span>
        <span style="color: #808080; font-style: italic;">/*printf(&quot;Moused Moved.\n&quot;);*/</span>
        pthread_mutex_lock<span style="color: #009900;">&#40;</span><span style="color: #339933;">&amp;</span>stamp_mutex<span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
        <span style="color: #666666; font-style: italic;">//time(&amp;stamp);</span>
        stamp <span style="color: #339933;">=</span> time<span style="color: #009900;">&#40;</span>NULL<span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
        pthread_mutex_unlock<span style="color: #009900;">&#40;</span><span style="color: #339933;">&amp;</span>stamp_mutex<span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
    <span style="color: #009900;">&#125;</span>
    close<span style="color: #009900;">&#40;</span>fd<span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
<span style="color: #009900;">&#125;</span>
&nbsp;
<span style="color: #993333;">void</span> <span style="color: #339933;">*</span>
listen_kb<span style="color: #009900;">&#40;</span><span style="color: #993333;">void</span> <span style="color: #339933;">*</span> arg<span style="color: #009900;">&#41;</span>
<span style="color: #009900;">&#123;</span>
    <span style="color: #993333;">int</span> fd <span style="color: #339933;">=</span> open<span style="color: #009900;">&#40;</span><span style="color: #ff0000;">&quot;/dev/input/event3&quot;</span><span style="color: #339933;">,</span> O_RDONLY<span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
    <span style="color: #b1b100;">if</span><span style="color: #009900;">&#40;</span>fd <span style="color: #339933;">&lt;</span> <span style="color: #0000dd;">0</span><span style="color: #009900;">&#41;</span>
    <span style="color: #009900;">&#123;</span>
        perror<span style="color: #009900;">&#40;</span><span style="color: #ff0000;">&quot;open event3&quot;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
        exit<span style="color: #009900;">&#40;</span><span style="color: #0000dd;">1</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
    <span style="color: #009900;">&#125;</span>
    <span style="color: #993333;">char</span> buf<span style="color: #009900;">&#91;</span><span style="color: #0000dd;">256</span><span style="color: #009900;">&#93;</span><span style="color: #339933;">;</span>
    <span style="color: #b1b100;">while</span><span style="color: #009900;">&#40;</span> read<span style="color: #009900;">&#40;</span>fd<span style="color: #339933;">,</span> buf<span style="color: #339933;">,</span> <span style="color: #993333;">sizeof</span><span style="color: #009900;">&#40;</span>buf<span style="color: #009900;">&#41;</span><span style="color: #009900;">&#41;</span> <span style="color: #339933;">&gt;</span> <span style="color: #0000dd;">0</span> <span style="color: #009900;">&#41;</span>
    <span style="color: #009900;">&#123;</span>
        <span style="color: #808080; font-style: italic;">/*printf(&quot;Key Hit.\n&quot;);*/</span>
        pthread_mutex_lock<span style="color: #009900;">&#40;</span><span style="color: #339933;">&amp;</span>stamp_mutex<span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
        <span style="color: #666666; font-style: italic;">//time(&amp;stamp);</span>
        stamp <span style="color: #339933;">=</span> time<span style="color: #009900;">&#40;</span>NULL<span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
        pthread_mutex_unlock<span style="color: #009900;">&#40;</span><span style="color: #339933;">&amp;</span>stamp_mutex<span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
    <span style="color: #009900;">&#125;</span>
    close<span style="color: #009900;">&#40;</span>fd<span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
<span style="color: #009900;">&#125;</span>
&nbsp;
<span style="color: #993333;">void</span>
daemonize<span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span>
<span style="color: #009900;">&#123;</span>
    <span style="color: #b1b100;">if</span><span style="color: #009900;">&#40;</span> fork<span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span> <span style="color: #339933;">&gt;</span> <span style="color: #0000dd;">0</span><span style="color: #009900;">&#41;</span>
        exit<span style="color: #009900;">&#40;</span><span style="color: #0000dd;">0</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
    setsid<span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
    close<span style="color: #009900;">&#40;</span><span style="color: #0000dd;">0</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
    close<span style="color: #009900;">&#40;</span><span style="color: #0000dd;">1</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
    close<span style="color: #009900;">&#40;</span><span style="color: #0000dd;">2</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
    <span style="color: #993333;">int</span> fd <span style="color: #339933;">=</span> open<span style="color: #009900;">&#40;</span><span style="color: #ff0000;">&quot;/dev/null&quot;</span><span style="color: #339933;">,</span> O_RDWR<span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
    <span style="color: #666666; font-style: italic;">//int fd = open(&quot;log.txt&quot;, O_RDWR);</span>
    dup2<span style="color: #009900;">&#40;</span>fd<span style="color: #339933;">,</span> <span style="color: #0000dd;">1</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
    dup2<span style="color: #009900;">&#40;</span>fd<span style="color: #339933;">,</span> <span style="color: #0000dd;">2</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
    chdir<span style="color: #009900;">&#40;</span><span style="color: #ff0000;">&quot;/&quot;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
    umask<span style="color: #009900;">&#40;</span><span style="color: #0000dd;">0</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
    signal<span style="color: #009900;">&#40;</span>SIGCHLD<span style="color: #339933;">,</span> SIG_IGN<span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
<span style="color: #009900;">&#125;</span></pre></td></tr></table></div>

<p>　　需要说明的是，共享变量stamp需要互斥地访问。另外，对鼠标事件的监听是借助于对设备文件/dev/input/mice的读取（阻塞方式），键盘的监听借助于对/dev/input/event3的阻塞读取，但我猜想在不同机器上可能会是其它诸如event0,event5之类的文件。<br />
　　不足之处在于，无法对全屏模式进行判断，即是说，如果你全屏看一部较长的电影，可能会被关机……<br />
　　如果你有好的方法来实现本文的功能，还请不吝赐教！</p>
]]></content:encoded>
			<wfw:commentRss>http://www.dutor.net/index.php/2010/09/linux-auto-halt/feed/</wfw:commentRss>
		<slash:comments>3</slash:comments>
		</item>
		<item>
		<title>守护进程</title>
		<link>http://www.dutor.net/index.php/2010/09/daemon-process/</link>
		<comments>http://www.dutor.net/index.php/2010/09/daemon-process/#comments</comments>
		<pubDate>Wed, 08 Sep 2010 15:29:10 +0000</pubDate>
		<dc:creator>dutor</dc:creator>
				<category><![CDATA[Unix/Linux]]></category>
		<category><![CDATA[边走编程]]></category>
		<category><![CDATA[OS基础]]></category>
		<category><![CDATA[守护进程]]></category>

		<guid isPermaLink="false">http://www.dutor.net/?p=2415</guid>
		<description><![CDATA[　　守护进程（daemon process，又称精灵进程），是一种运行在后台，不需要与用户进行交互的程序，其特性与Windows中的<strong>服务</strong>类似。Linux/Unix系统中运行着很多这样的进程，且很多此类进程的进程名都采用name<strong><em>d</em></strong>的形式，比如httpd, vsftpd, inetd等。但这只是一种命名惯例，你完全可以采用其它的命名形式。
<h4>守护进程的特性</h4>
　　守护进程有种种特性，使之成为守护进程。
　　<strong>运行周期较长。</strong>守护进程通常在系统启动时由/etc/rc*.d中的启动脚本或者用户在终端手动启动，在系统结束时停止或由用户手动停止。不像普通进程那样在用户退出终端后就被停止，守护进程会一直运行（下面会看到守护进程在启动后会脱离执行它的终端）。
　　<strong>脱离其运行环境。</strong>守护进程没有控制终端。进程在创建时（fork）会继承父进程的PCB（进程控制块），因此会同时拥有父进程的许多资源和关系，比如打开的文件描述符、socket、环境变量、控制终端、进程组、登录会话等。而守护进程需要关闭这些资源、脱离这些关系。]]></description>
			<content:encoded><![CDATA[<p>　　守护进程（daemon process，又称精灵进程），是一种运行在后台，不需要与用户进行交互的程序，其特性与Windows中的<strong>服务</strong>类似。Linux/Unix系统中运行着很多这样的进程，且很多此类进程的进程名都采用name<strong><em>d</em></strong>的形式，比如httpd, vsftpd, inetd等。但这只是一种命名惯例，你完全可以采用其它的命名形式。</p>
<h4>守护进程的特性</h4>
<p>　　守护进程有种种特性，使之成为守护进程。<br />
　　<strong>运行周期较长。</strong>守护进程通常在系统启动时由/etc/rc*.d中的启动脚本或者用户在终端手动启动，在系统结束时停止或由用户手动停止。不像普通进程那样在用户退出终端后就被停止，守护进程会一直运行（下面会看到守护进程在启动后会脱离执行它的终端）。<br />
　　<strong>脱离其运行环境。</strong>守护进程没有控制终端。进程在创建时（fork）会继承父进程的PCB（进程控制块），因此会同时拥有父进程的许多资源和关系，比如打开的文件描述符、socket、环境变量、控制终端、进程组、登录会话等。而守护进程需要关闭这些资源、脱离这些关系。</p>
<h4>创建守护进程</h4>
<p>　　鉴于守护进程的这些特性，一个普通进程若想成为守护进程，就需要做一些特殊的操作。</p>
<h5>脱离控制终端</h5>
<p>　　多数用户进程都是从终端运行的，它由与终端关联的shell（用户登录时由login执行的，比如bash程序）经过fork/exec启动。用户程序启动后shell会等待该进程（wait或waitpid等）结束，如果该进程为后台运行，shell会立即返回命令提示符等待用户的其它操作，否则shell会在用户进程结束时才打印命令提示符。<br />
　　所以，为了能使守护进程运行后shell立即返回，通常在程序的入口采用下面的代码来完成：</p>

<div class="wp_codebox"><table><tr id="p241544"><td class="line_numbers"><pre>1
2
</pre></td><td class="code" id="p2415code44"><pre class="c" style="font-family:monospace;"><span style="color: #b1b100;">if</span><span style="color: #009900;">&#40;</span> fork<span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span> <span style="color: #339933;">&gt;</span> <span style="color: #0000dd;">0</span><span style="color: #009900;">&#41;</span>
    exit<span style="color: #009900;">&#40;</span><span style="color: #0000dd;">0</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span></pre></td></tr></table></div>

<p>　　程序fork产生新进程，父进程立即返回（shell等待的就是父进程），shell进程的wait也会成功返回，而子进程则会继续执行。注意，此时子进程的父进程已经过继成为init进程（进程号为1）的子进程了。</p>
<h5>另立门户</h5>
<p>　　执行的上面的操作后，用户进程（子进程）并未真正脱离控制终端。因为子进程继承了父进程的关系，属于父进程所在的进程组，和父进程同属于一个作业，还隶属于控制终端所关联的登录会话（login session）。关于进程组、作业、登录会话等概念，请参考《高级Unix环境编程》(Advanced Programming of Unix Environment)，及Google。<br />
　　若想脱离这些复杂的关系，操作却十分简单，只须在子进程一开始，调用函数setsid()即可。setsid做了以下工作：脱离了原来的进程组和登录会话，创建新的进程组和会话，并担当其进程组的Group Leader和会话的Session Leader.<br />
　　这时候，该进程已经真正脱离了其控制终端，即是说，该进程在其原控制终端退出登录后仍可以在系统中运行。</p>
<h5>关闭继承打开的文件描述符</h5>
<p>　　控制终端，准确说是shell默认打开了三个文件，0代表标准输入，1代表标准输出，2代表标准错误输出。由该shell执行的进程也会继承打开这三个文件，所以它的所有子进程默认的输入和输出也都关联到此终端。因为守护进程也可能有其他用户进程通过exec系列函数执行，守护进程同样会继承这些文件描述符。因此在守护进程中需要关闭继承而来的所有描述符，APUE中stevens的代码：</p>

<div class="wp_codebox"><table><tr id="p241545"><td class="line_numbers"><pre>1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
</pre></td><td class="code" id="p2415code45"><pre class="c" style="font-family:monospace;"><span style="color: #993333;">int</span> close_all_fd<span style="color: #009900;">&#40;</span><span style="color: #993333;">void</span><span style="color: #009900;">&#41;</span>
<span style="color: #009900;">&#123;</span>
        <span style="color: #993333;">struct</span> rlimit lim<span style="color: #339933;">;</span>
        <span style="color: #993333;">unsigned</span> <span style="color: #993333;">int</span> i<span style="color: #339933;">;</span>
&nbsp;
        <span style="color: #b1b100;">if</span> <span style="color: #009900;">&#40;</span>getrlimit<span style="color: #009900;">&#40;</span>RLIMIT_NOFILE<span style="color: #339933;">,</span> <span style="color: #339933;">&amp;</span>lim<span style="color: #009900;">&#41;</span> <span style="color: #339933;">&lt;</span> <span style="color: #0000dd;">0</span><span style="color: #009900;">&#41;</span>
                <span style="color: #b1b100;">return</span> <span style="color: #339933;">-</span><span style="color: #0000dd;">1</span><span style="color: #339933;">;</span>
        <span style="color: #b1b100;">if</span> <span style="color: #009900;">&#40;</span>lim.<span style="color: #202020;">rlim_cur</span> <span style="color: #339933;">==</span> RLIM_INFINITY<span style="color: #009900;">&#41;</span>
                lim.<span style="color: #202020;">rlim_cur</span> <span style="color: #339933;">=</span> <span style="color: #0000dd;">1024</span><span style="color: #339933;">;</span>
        <span style="color: #b1b100;">for</span> <span style="color: #009900;">&#40;</span>i <span style="color: #339933;">=</span> <span style="color: #0000dd;">0</span><span style="color: #339933;">;</span> i <span style="color: #339933;">&lt;</span> lim.<span style="color: #202020;">rlim_cur</span><span style="color: #339933;">;</span> i <span style="color: #339933;">++</span><span style="color: #009900;">&#41;</span> <span style="color: #009900;">&#123;</span>
<span style="color: #339933;">#ifdef MYPERF</span>
                <span style="color: #b1b100;">if</span> <span style="color: #009900;">&#40;</span>i <span style="color: #339933;">==</span> <span style="color: #0000dd;">1</span><span style="color: #009900;">&#41;</span>
                        <span style="color: #b1b100;">continue</span><span style="color: #339933;">;</span>
<span style="color: #339933;">#endif</span>
                <span style="color: #b1b100;">if</span> <span style="color: #009900;">&#40;</span>close<span style="color: #009900;">&#40;</span>i<span style="color: #009900;">&#41;</span> <span style="color: #339933;">&lt;</span> <span style="color: #0000dd;">0</span> <span style="color: #339933;">&amp;&amp;</span> errno <span style="color: #339933;">!=</span> EBADF<span style="color: #009900;">&#41;</span>
                        <span style="color: #b1b100;">return</span> <span style="color: #339933;">-</span><span style="color: #0000dd;">1</span><span style="color: #339933;">;</span>
        <span style="color: #009900;">&#125;</span>
        <span style="color: #b1b100;">return</span> <span style="color: #0000dd;">0</span><span style="color: #339933;">;</span>
<span style="color: #009900;">&#125;</span></pre></td></tr></table></div>

<h5>改变当前工作目录</h5>
<p>　　每个进程都有自己的当前工作目录，进程创建时默认继承父进程的工作目录。守护进程需要将当前工作目录改变，否则其所在目录所挂载的文件系统将无法卸载（可能是你不想要的），通常将其改变之根目录，方法是chdir(&#8220;/&#8221;);</p>
<h5>重设文件创建掩码</h5>
<p>　　为了能够自主控制文件创建权限位，常将文件创建掩码重设为0000，即umask(0);</p>
<h5>忽略SIGCHLD信号</h5>
<p>　　由于守护进程运行周期长，为了避免因为等待子进程而产生僵尸进程，通常需要忽略SIGCHLD信号：signal(SIGCHLD, SIG_IGN);</p>
<h4>总结</h4>
<p>　　方便起见，通常把创建守护进程的一系列操作包装为一个函数，在需要的地方调用即可：</p>

<div class="wp_codebox"><table><tr id="p241546"><td class="line_numbers"><pre>1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
</pre></td><td class="code" id="p2415code46"><pre class="cpp" style="font-family:monospace;"><span style="color: #0000ff;">void</span> daemonize<span style="color: #008000;">&#40;</span><span style="color: #008000;">&#41;</span><span style="color: #008080;">;</span>
<span style="color: #0000ff;">int</span>
main<span style="color: #008000;">&#40;</span><span style="color: #008000;">&#41;</span>
<span style="color: #008000;">&#123;</span>
    daemonize<span style="color: #008000;">&#40;</span><span style="color: #008000;">&#41;</span><span style="color: #008080;">;</span>
    <span style="color: #666666;">//~ other operations here.</span>
    <span style="color: #0000ff;">return</span> <span style="color: #0000dd;">0</span><span style="color: #008080;">;</span>
<span style="color: #008000;">&#125;</span>
<span style="color: #0000ff;">void</span>
daemonize<span style="color: #008000;">&#40;</span><span style="color: #008000;">&#41;</span>
<span style="color: #008000;">&#123;</span>
    <span style="color: #0000ff;">if</span><span style="color: #008000;">&#40;</span> fork<span style="color: #008000;">&#40;</span><span style="color: #008000;">&#41;</span> <span style="color: #000080;">&gt;</span> <span style="color: #0000dd;">0</span><span style="color: #008000;">&#41;</span>
        <span style="color: #0000dd;">exit</span><span style="color: #008000;">&#40;</span><span style="color: #0000dd;">0</span><span style="color: #008000;">&#41;</span><span style="color: #008080;">;</span>
    setsid<span style="color: #008000;">&#40;</span><span style="color: #008000;">&#41;</span><span style="color: #008080;">;</span>
    close<span style="color: #008000;">&#40;</span><span style="color: #0000dd;">0</span><span style="color: #008000;">&#41;</span><span style="color: #008080;">;</span> <span style="color: #666666;">//~ im so lazy a guy.</span>
    close<span style="color: #008000;">&#40;</span><span style="color: #0000dd;">1</span><span style="color: #008000;">&#41;</span><span style="color: #008080;">;</span>
    close<span style="color: #008000;">&#40;</span><span style="color: #0000dd;">2</span><span style="color: #008000;">&#41;</span><span style="color: #008080;">;</span>
    <span style="color: #666666;">//~ you can use I/O functions, but to/from the black hole...</span>
    <span style="color: #0000ff;">int</span> fd <span style="color: #000080;">=</span> open<span style="color: #008000;">&#40;</span><span style="color: #FF0000;">&quot;/dev/null&quot;</span>, O_RDWR<span style="color: #008000;">&#41;</span><span style="color: #008080;">;</span>
    dup2<span style="color: #008000;">&#40;</span>fd, <span style="color: #0000dd;">1</span><span style="color: #008000;">&#41;</span><span style="color: #008080;">;</span>
    dup2<span style="color: #008000;">&#40;</span>fd, <span style="color: #0000dd;">2</span><span style="color: #008000;">&#41;</span><span style="color: #008080;">;</span>
    chdir<span style="color: #008000;">&#40;</span><span style="color: #FF0000;">&quot;/&quot;</span><span style="color: #008000;">&#41;</span><span style="color: #008080;">;</span>
    umask<span style="color: #008000;">&#40;</span><span style="color: #0000dd;">0</span><span style="color: #008000;">&#41;</span><span style="color: #008080;">;</span>
    <span style="color: #0000ff;">signal</span><span style="color: #008000;">&#40;</span>SIGCHLD, <span style="color: #0000ff;">SIG_IGN</span><span style="color: #008000;">&#41;</span><span style="color: #008080;">;</span>
<span style="color: #008000;">&#125;</span></pre></td></tr></table></div>

]]></content:encoded>
			<wfw:commentRss>http://www.dutor.net/index.php/2010/09/daemon-process/feed/</wfw:commentRss>
		<slash:comments>2</slash:comments>
		</item>
		<item>
		<title>[命令技巧]chmod &amp; Set-User-ID &amp; Set-Group-ID</title>
		<link>http://www.dutor.net/index.php/2010/08/cmd-chmod-set-user-id-set-group-id/</link>
		<comments>http://www.dutor.net/index.php/2010/08/cmd-chmod-set-user-id-set-group-id/#comments</comments>
		<pubDate>Sun, 08 Aug 2010 07:39:03 +0000</pubDate>
		<dc:creator>dutor</dc:creator>
				<category><![CDATA[Unix/Linux]]></category>
		<category><![CDATA[chmod]]></category>
		<category><![CDATA[OS基础]]></category>
		<category><![CDATA[命令]]></category>

		<guid isPermaLink="false">http://www.dutor.net/?p=2379</guid>
		<description><![CDATA[<h4>chmod命令介绍</h4>
　　下面介绍如何使用chmod命令来设定和修改文件的权限位。
　　首先，chmod命令本身的执行也有限制，普通用户只能修改自己的文件的权限位，超级用户可以使用chmod修改任意用户任意文件的权限。使用chmod的方法为chmod [option] mode file. 常用的选项就是-R，用来对整个目录及其子目录中的文件进行模式（权限）修改。mode可以由两种方式指定，一种是由字母表达式表示的相对修改方式，一种是以4位8进制表示的绝对方式。
　　第一种方式：chmod [ugoa][+-=][rwxst] file. u指代user，g指代group，o指代other，a指代all。+-=分别执行指代增加、减少、设定相应权限（由后面的参数指定）。rwxst分别指代读、写、执行、set-user-id/set-group-id、sticky-bit粘滞位。整体上理解，就是对哪类用户（ugoa，为a时可省略）执行哪些权限（rwxst）的什么修改（+-=）。示例：
<pre lang="bash" line="1">
$ chmod u-x a.out 
$ ll a.out
-rw-r-xr-x 1 dutor dutor 7.1K 2010-08-08 13:33 a.out
$ chmod +t a.out 
$ ll a.out
-rw-r-xr-t 1 dutor dutor 7.1K 2010-08-08 13:33 a.out
$ chmod g=rs a.out 
$ ll a.out
-rw-r-Sr-t 1 dutor dutor 7.1K 2010-08-08 13:33 a.out
$ chmod a+x a.out 
$ ll a.out
-rwxr-sr-t 1 dutor dutor 7.1K 2010-08-08 13:33 a.out
</pre>]]></description>
			<content:encoded><![CDATA[<p>　　本篇文章讨论的是Linux/Unix的权限问题，包括文件的访问权限、可执行文件的权限以及修改这些权限的命令chmod。</p>
<h4>Linux权限模式介绍</h4>
<p>　　用ls -l命令列出文件的详细信息，关于ls -<a href="http://www.dutor.net/index.php/2010/06/cmd-ls/" target="_blank">l参见这里</a>。</p>

<div class="wp_codebox"><table><tr id="p237947"><td class="line_numbers"><pre>1
2
3
4
5
6
</pre></td><td class="code" id="p2379code47"><pre class="bash" style="font-family:monospace;">$ ll <span style="color: #666666; font-style: italic;"># alias ll='ls -lh'</span>
total 20K
<span style="color: #660033;">-rwxr-xr-x</span> <span style="color: #000000;">1</span> dutor dutor 7.1K <span style="color: #000000;">2010</span>-08-08 <span style="color: #000000;">12</span>:<span style="color: #000000;">45</span> a.out
<span style="color: #660033;">-rw-r--r--</span> <span style="color: #000000;">1</span> dutor dutor  <span style="color: #000000;">540</span> <span style="color: #000000;">2010</span>-08-08 <span style="color: #000000;">12</span>:<span style="color: #000000;">29</span> main.c
<span style="color: #660033;">-rw-r--r--</span> <span style="color: #000000;">1</span> dutor dutor  <span style="color: #000000;">472</span> <span style="color: #000000;">2010</span>-07-<span style="color: #000000;">17</span> <span style="color: #000000;">23</span>:<span style="color: #000000;">18</span> main.cpp
<span style="color: #660033;">-rw-r--r--</span> <span style="color: #000000;">1</span> dutor dutor   <span style="color: #000000;">53</span> <span style="color: #000000;">2010</span>-04-<span style="color: #000000;">26</span> <span style="color: #000000;">12</span>:<span style="color: #000000;">24</span> Makefile</pre></td></tr></table></div>

<p>ls -l输出内容包括七个域，其中第一个域包括10个字符。第一个字符指明了文件类型，可能是以下字符：</p>
<ul>
<li>-: 普通文件；</li>
<li>d: directory，目录文件；</li>
<li>l: link，符号链接；</li>
<li>s: socket文件；</li>
<li>b: block，块设备；</li>
<li>c: charactor，字符设备；</li>
<li>p: FIFO pipe，管道文件。</li>
</ul>
<p>　　接下来的9个字符指明了文件的访问权限：每三位指明一类用户的权限，分别是文件属主（user）、同组用户（group）、其它用户（other），权限分为读（r）、写（w）、执行（x），相应位若为-，表示此类用户不具有相应权限。<br />
　　另外，x对应的位置（执行位）还可能是其它字符。比如，user或group的执行位若为s，表示该文件的set-user-id或者set-group-id（这两种id下文会着重介绍）和执行权限x被同时置位；若为S，则表示set-user-id或set-group-id被置位，而执行权限x不被置位。other的执行为如果为t，表示该文件的粘滞位（sticky bit）和x均被置位；若为T，则表示只有粘滞位被置位。粘滞位如果被置位，而且该文件为可执行文件，则当文件被执行时，其文本段（.text段，即代码段）会被加载到swap中，程序结束时仍然保留在swap，当下次执行该文件时，将直接从swap中加载，由于swap在磁盘中为连续的block，因此加载速度会提高。另外，如果目录文件的粘滞位被置位，也具有特殊含义，此处从略 。<br />
　　<br />
　　需要特别说明的是目录的权限。Linux/Unix中，目录是一种“特殊”的文件，这个文件包括该目录下所有文件（包括子目录）的文件名和索引节点，i-node号。读一个目录是指列出该目录下所有的文件和子目录，如ls。写一个目录是指增加、删除或者重命名该目录下的文件或目录，如rm,mv等，值得一提的是，你可能无法读写和执行一个文件，但却可能删除这个文件，只要你对其所在目录具有写权限。一个目录的执行权限是指，该目录可以是一个（搜索）路径的一部分，即你必须对你要访问的文件的路径中的任何一个目录都具有执行权限，形象地你可以把目录的执行权限当作是过境的绿卡。</p>
<h4>chmod命令介绍</h4>
<p>　　下面介绍如何使用chmod命令来设定和修改文件的权限位。<br />
　　首先，chmod命令本身的执行也有限制，普通用户只能修改自己的文件的权限位，超级用户可以使用chmod修改任意用户任意文件的权限。使用chmod的方法为chmod [option] mode file. 常用的选项就是-R，用来对整个目录及其子目录中的文件进行模式（权限）修改。mode可以由两种方式指定，一种是由字母表达式表示的相对修改方式，一种是以4位8进制表示的绝对方式。<br />
　　第一种方式：chmod [ugoa][+-=][rwxst] file. u指代user，g指代group，o指代other，a指代all。+-=分别执行指代增加、减少、设定相应权限（由后面的参数指定）。rwxst分别指代读、写、执行、set-user-id/set-group-id、sticky-bit粘滞位。整体上理解，就是对哪类用户（ugoa，为a时可省略）执行哪些权限（rwxst）的什么修改（+-=）。示例：</p>

<div class="wp_codebox"><table><tr id="p237948"><td class="line_numbers"><pre>1
2
3
4
5
6
7
8
9
10
11
12
</pre></td><td class="code" id="p2379code48"><pre class="bash" style="font-family:monospace;">$ <span style="color: #c20cb9; font-weight: bold;">chmod</span> u-x a.out 
$ ll a.out
<span style="color: #660033;">-rw-r-xr-x</span> <span style="color: #000000;">1</span> dutor dutor 7.1K <span style="color: #000000;">2010</span>-08-08 <span style="color: #000000;">13</span>:<span style="color: #000000;">33</span> a.out
$ <span style="color: #c20cb9; font-weight: bold;">chmod</span> +t a.out 
$ ll a.out
<span style="color: #660033;">-rw-r-xr-t</span> <span style="color: #000000;">1</span> dutor dutor 7.1K <span style="color: #000000;">2010</span>-08-08 <span style="color: #000000;">13</span>:<span style="color: #000000;">33</span> a.out
$ <span style="color: #c20cb9; font-weight: bold;">chmod</span> <span style="color: #007800;">g</span>=rs a.out 
$ ll a.out
<span style="color: #660033;">-rw-r-Sr-t</span> <span style="color: #000000;">1</span> dutor dutor 7.1K <span style="color: #000000;">2010</span>-08-08 <span style="color: #000000;">13</span>:<span style="color: #000000;">33</span> a.out
$ <span style="color: #c20cb9; font-weight: bold;">chmod</span> a+x a.out 
$ ll a.out
<span style="color: #660033;">-rwxr-sr-t</span> <span style="color: #000000;">1</span> dutor dutor 7.1K <span style="color: #000000;">2010</span>-08-08 <span style="color: #000000;">13</span>:<span style="color: #000000;">33</span> a.out</pre></td></tr></table></div>

<p>　　第二种方式：chmod xxxx file. 其中x为一个八进制的数字，即0~7，由三个代表权限权值的数字相加或者按位或形成。各权限位的权值分别为：r:4, w:2, x:1; set-user-id:4, set-group-id:2, t:1. 其中，set-user-id, set-group-id和t组成第一个8进制数，其它三个八进制数分别代表user、group和other的权限，由rwx组成。另外，你可以指定少于4个的8进制数字，这样，前面未指定的数字就为0。示例：</p>

<div class="wp_codebox"><table><tr id="p237949"><td class="line_numbers"><pre>1
2
3
4
5
6
7
8
9
10
11
12
13
14
</pre></td><td class="code" id="p2379code49"><pre class="bash" style="font-family:monospace;">$ ll a.out 
<span style="color: #660033;">-rwxr-xr-x</span> <span style="color: #000000;">1</span> dutor dutor 7.1K <span style="color: #000000;">2010</span>-08-08 <span style="color: #000000;">13</span>:<span style="color: #000000;">54</span> a.out
$ <span style="color: #c20cb9; font-weight: bold;">chmod</span> 0755 a.out 
$ ll a.out 
<span style="color: #660033;">-rwxr-xr-x</span> <span style="color: #000000;">1</span> dutor dutor 7.1K <span style="color: #000000;">2010</span>-08-08 <span style="color: #000000;">13</span>:<span style="color: #000000;">54</span> a.out
$ <span style="color: #c20cb9; font-weight: bold;">chmod</span> 0777 a.out 
$ ll a.out 
<span style="color: #660033;">-rwxrwxrwx</span> <span style="color: #000000;">1</span> dutor dutor 7.1K <span style="color: #000000;">2010</span>-08-08 <span style="color: #000000;">13</span>:<span style="color: #000000;">54</span> a.out
$ <span style="color: #c20cb9; font-weight: bold;">chmod</span> <span style="color: #000000;">1700</span> a.out 
$ ll a.out 
<span style="color: #660033;">-rwx-----T</span> <span style="color: #000000;">1</span> dutor dutor 7.1K <span style="color: #000000;">2010</span>-08-08 <span style="color: #000000;">13</span>:<span style="color: #000000;">54</span> a.out
$ <span style="color: #c20cb9; font-weight: bold;">chmod</span> <span style="color: #000000;">6760</span> a.out 
$ ll a.out 
<span style="color: #660033;">-rwsrwS---</span> <span style="color: #000000;">1</span> dutor dutor 7.1K <span style="color: #000000;">2010</span>-08-08 <span style="color: #000000;">13</span>:<span style="color: #000000;">54</span> a.out</pre></td></tr></table></div>

<h4>user-id和group-id</h4>
<p>　　一个用户，有两个id：user-id和group-id。user-id对于一个用户唯一的，但一个用户可以隶属于多个不同的group，但默认的组只有一个，这里的默认是指这个用户创建的文件默认隶属的组。这里说的group-id即为默认组id。<br />
　　相对于下面要介绍的effective-user-id和effective-group-id，上面的user-id和group-id确切地说是real-user-id和real-group-id。这两个id被保存在/etc/passwd文件中，创建用户时被写入，每当用户登录时由登录程序来读取该文件，并设定相应用户的id，OS以用户的用户id和组来判断你是否具有相应的权限来执行特定的操作。<br />
　　effective-user-id和effective-group-id，是针对可执行文件来说的，通常一个被执行的程序（进程）的effective-user-id和effective-group-id与real-user-id和real-group-id是相同的，都等于执行该程序的用户的user-id和group-id，不管该程序文件本身属于哪个用户。但当该程序文件的set-user-id或者set-group-id被置位时，该程序进程的effective-user-id或effective-group-id就是该程序文件属主的user-id或group-id，而不是该进程的real-user-id或real-group-id。<br />
　　那么，effective-user-id和effective-group-id有什么作用呢？<br />
　　在一个进程试图去访问一种资源时，比如读、写某个文件，OS（内核）会判断此进程对该文件是否具有相应的权限，判断的依据就是上面介绍的文件的权限访问位。那么，OS是拿进程的real*id，即执行该程序的用户的id来判断呢，还是拿进程的可执行文件的属主的id来判断呢？答案是，拿进程的effective-user-id和effective-group-id来判断，而effective-user-id和effective-group-id与set-user-id和set-group-id有关。这样，问题就明了了。<br />
　　举例来说，/etc/passwd文件保存了系统中用户的基本信息（早期的Unix中，甚至直接将用户密码保存在该文件中），它的属主是root用户，普通用户对该文件只有读权限。但系统又需要允许用户修改自己的信息，这样就提供了相应的命令，例如passwd命令。这个命令的可执行文件的属主为root用户，为了普通用户也能够通过passwd命令修改密码，这个命令的set-user-id就被置位了。而普通用户的身份认证就转移到了passwd程序内部了，例如不允许普通用户修改其它用户的密码。上面所说的你可以自己验证：</p>

<div class="wp_codebox"><table><tr id="p237950"><td class="line_numbers"><pre>1
2
</pre></td><td class="code" id="p2379code50"><pre class="bash" style="font-family:monospace;">$ ll <span style="color: #000000; font-weight: bold;">`</span><span style="color: #c20cb9; font-weight: bold;">which</span> <span style="color: #c20cb9; font-weight: bold;">passwd</span><span style="color: #000000; font-weight: bold;">`</span>
<span style="color: #660033;">-rwsr-xr-x</span> <span style="color: #000000;">1</span> root root 37K <span style="color: #000000;">2010</span>-01-<span style="color: #000000;">27</span> 01:09 <span style="color: #000000; font-weight: bold;">/</span>usr<span style="color: #000000; font-weight: bold;">/</span>bin<span style="color: #000000; font-weight: bold;">/</span><span style="color: #c20cb9; font-weight: bold;">passwd</span> <span style="color: #666666; font-style: italic;"># set-user-id被置位</span></pre></td></tr></table></div>

<p>　　注意，由于现在用户密码已经不再直接保存在/etc/passwd中了，因此passwd命令可能不再修改该文件，而该文件肯定也是不允许root之外的用户（准确说是不具有超级权限的用户）修改的。事实上，真正保存密码的文件是/etc/shadow，而这个文件的权限位为0640。</p>
]]></content:encoded>
			<wfw:commentRss>http://www.dutor.net/index.php/2010/08/cmd-chmod-set-user-id-set-group-id/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>[Bash]Readline组件的菜单式补全</title>
		<link>http://www.dutor.net/index.php/2010/07/bash-readline-keybindings/</link>
		<comments>http://www.dutor.net/index.php/2010/07/bash-readline-keybindings/#comments</comments>
		<pubDate>Sun, 25 Jul 2010 05:47:10 +0000</pubDate>
		<dc:creator>dutor</dc:creator>
				<category><![CDATA[Unix/Linux]]></category>
		<category><![CDATA[readline]]></category>
		<category><![CDATA[shell]]></category>
		<category><![CDATA[配置]]></category>

		<guid isPermaLink="false">http://www.dutor.net/?p=2369</guid>
		<description><![CDATA[<h4>配置inputrc</h4>
　　我们这里需要的是一种叫做<strong>菜单式补全</strong>（menu-complete）的功能。通常，默认情况下，这个选项是没有被配置的。为了配置这项功能，并为之进行快捷键绑定，我们需要修改inputrc配置文件，这个文件中保存了Readline的一些键绑定和其它诸如编辑模式的配置选项。像许多其它配置文件一样，inputrc有系统级的配置选项/etc/inputrc和用户级的点文件~/.inputrc。建议建立自己的点文件，而不是直接编辑系统级文件，当然如果整个系统只是你一个人在用的话，你也可以在/etc/inputrc上面直接编辑。但使用点文件的另一个好处告诉你，它是属于你自己的，即使在另外一个不同的发行版上，点文件通常也是可以直接使用的。这可以减轻你在不同系统上的不适。
　　好了，打开或者建立你的.inputrc，写下，下面两行：
<pre lang="bash" line="1">
"\C-j": menu-complete
"\C-k": menu-complete-backward
</pre>]]></description>
			<content:encoded><![CDATA[<p>　　以前介绍过一些<a href="http://www.dutor.net/index.php/2010/04/shell-shortcuts/" target="_blank">使用Bash时候的一些快捷键</a>，使用这些Bash可以大大提高你输入和编辑命令行的速度，提升你的工作效率，当然也可能会把你衬托地更牛B一点。不管怎样，如果你经常使用命令行，熟练使用一些快捷键总是好的。</p>
<h4>普通的自动补全</h4>
<p>　　Tab键就是这样一个快捷键，利用它你可以不必输入命令/参数/文件/目录的的完整名称，它可以进行自动不全。比如：</p>

<div class="wp_codebox"><table><tr id="p236951"><td class="line_numbers"><pre>1
2
3
4
5
6
7
8
9
</pre></td><td class="code" id="p2369code51"><pre class="bash" style="font-family:monospace;">dutor<span style="color: #000000; font-weight: bold;">@</span>dutor-desktop:~$ <span style="color: #666666; font-style: italic;">#alias l=&quot;ls -CFh&quot;</span>
dutor<span style="color: #000000; font-weight: bold;">@</span>dutor-desktop:~$ l
Desktop<span style="color: #000000; font-weight: bold;">/</span>    Downloads<span style="color: #000000; font-weight: bold;">/</span>  Pictures<span style="color: #000000; font-weight: bold;">/</span>   Videos<span style="color: #000000; font-weight: bold;">/</span> 
Documents<span style="color: #000000; font-weight: bold;">/</span>  Music<span style="color: #000000; font-weight: bold;">/</span>      Templates<span style="color: #000000; font-weight: bold;">/</span>  Wdir<span style="color: #000000; font-weight: bold;">/</span>
dutor<span style="color: #000000; font-weight: bold;">@</span>dutor-desktop:~$ <span style="color: #666666; font-style: italic;">#cd des&lt;Tab&gt; </span>
dutor<span style="color: #000000; font-weight: bold;">@</span>dutor-desktop:~$ <span style="color: #7a0874; font-weight: bold;">cd</span> Desktop<span style="color: #000000; font-weight: bold;">/</span>
<span style="color: #000000; font-weight: bold;">/</span>home<span style="color: #000000; font-weight: bold;">/</span>dutor<span style="color: #000000; font-weight: bold;">/</span>Desktop
dutor<span style="color: #000000; font-weight: bold;">@</span>dutor-desktop:~ <span style="color: #666666; font-style: italic;">#cd d&lt;Tab&gt;&lt;Tab&gt;</span>
Desktop<span style="color: #000000; font-weight: bold;">/</span>   Documents<span style="color: #000000; font-weight: bold;">/</span> Downloads<span style="color: #000000; font-weight: bold;">/</span></pre></td></tr></table></div>

<p>　　当可选项唯一时，按下TAB键就会立即被不全。而如果有多个候选项时，按下TAB两次，所有候选项都会被列出。如上例，D开头的有三个目录，Desktop, Documents和Downloads，若想进入Destop目录，只需键入De<Tab>即可。若想进入另外两个目录中的某一个，至少需要输入该目录开头的三个字符。<br />
　　经常使用Vim的朋友（亲们？）可能会发现，Vim的命令模式（Last Line Mode）中使用帮助文档或者打开另外一个文件时，也有Tab自动不全的功能。不仅如此，当有多个候选项存在时，按下Tab或者Ctrl+n会逐次遍历这些候选项，直到找到你想要的选项。那么，Bash里面可以实现类似的功能吗？<br />
　　当然，因为默认情况下，Vim的命令行和Bash的命令行使用的是“同一个”行编辑组件：Readline。细心的朋友可能发现，在Vim的命令行中，Ctrl+a、Ctrl+e等命令也是可以使用的。</p>
<h4>配置inputrc</h4>
<p>　　我们这里需要的是一种叫做<strong>菜单式补全</strong>（menu-complete）的功能。通常，默认情况下，这个选项是没有被配置的。为了配置这项功能，并为之进行快捷键绑定，我们需要修改inputrc配置文件，这个文件中保存了Readline的一些键绑定和其它诸如编辑模式的配置选项。像许多其它配置文件一样，inputrc有系统级的配置选项/etc/inputrc和用户级的点文件~/.inputrc。建议建立自己的点文件，而不是直接编辑系统级文件，当然如果整个系统只是你一个人在用的话，你也可以在/etc/inputrc上面直接编辑。但使用点文件的另一个好处告诉你，它是属于你自己的，即使在另外一个不同的发行版上，点文件通常也是可以直接使用的。这可以减轻你在不同系统上的不适。<br />
　　好了，打开或者建立你的.inputrc，写下，下面两行：</p>

<div class="wp_codebox"><table><tr id="p236952"><td class="line_numbers"><pre>1
2
</pre></td><td class="code" id="p2369code52"><pre class="bash" style="font-family:monospace;"><span style="color: #ff0000;">&quot;\C-j&quot;</span>: menu-complete
<span style="color: #ff0000;">&quot;\C-k&quot;</span>: menu-complete-backward</pre></td></tr></table></div>

<p>　　保存，然后重启Bash或者执行下面命令，使inputrc的配置立即生效：</p>

<div class="wp_codebox"><table><tr id="p236953"><td class="line_numbers"><pre>1
</pre></td><td class="code" id="p2369code53"><pre class="bash" style="font-family:monospace;"><span style="color: #7a0874; font-weight: bold;">bind</span> <span style="color: #660033;">-f</span> ~<span style="color: #000000; font-weight: bold;">/</span>.inputrc</pre></td></tr></table></div>

<p>　　此时，通过Ctrl+j就可以把“下一个”候选项加入命令行，或者通过Ctrl+k把“上一个”候选项加入命令行。加入这项功能的另外一个好处就是，如果你要处理中文的文件或目录时，不比切换输入法（我的rxvt甚至无法使用中文输入法），选择即可。</p>
<h4>了解更多Readline</h4>
<p>　　在inputrc中还可以定义很多其它的特性，若想详细了解这些特性即配置方法，请参考这份关于<a href="http://tiswww.case.edu/php/chet/readline/rluserman.html" target="_blank">GNU Readline Library的说明文档</a>。</p>
]]></content:encoded>
			<wfw:commentRss>http://www.dutor.net/index.php/2010/07/bash-readline-keybindings/feed/</wfw:commentRss>
		<slash:comments>7</slash:comments>
		</item>
		<item>
		<title>Unix/Linux环境下创建和使用静/动态库</title>
		<link>http://www.dutor.net/index.php/2010/07/dynamic-static-library/</link>
		<comments>http://www.dutor.net/index.php/2010/07/dynamic-static-library/#comments</comments>
		<pubDate>Sun, 04 Jul 2010 14:23:55 +0000</pubDate>
		<dc:creator>dutor</dc:creator>
				<category><![CDATA[Unix/Linux]]></category>
		<category><![CDATA[边走编程]]></category>
		<category><![CDATA[OS基础]]></category>
		<category><![CDATA[动态链接]]></category>

		<guid isPermaLink="false">http://www.dutor.net/?p=2340</guid>
		<description><![CDATA[<h4>动态链接库</h4>
　　动态库和静态库相似，也是各个目标文件的集合。但相比静态链接的程序，动态链接可执行程序要小得多：这类程序运行时需要外部共享 函数库的支持，因此好像并不完整。除了程序体小之外，动态链接允许程序包指定必须的库，而不必将库装入程序包内。动态链接技术还允许多个运行中的程序共享一个库，这样就不会出现同一代码的多份拷贝共占内存的情况了。由于这些原因，当前多数程序采用动态链接技术。
　　在Linux中的扩展名通常为.so。但在链接时，并不会被链接到可执行文件中，而是在执行时（需要时）由操作系统的动态加载模块动态地加载到内存，并链接到可执行文件地址空间的相应位置。
　　动态链接库的创建也分为编译和"归档"两个阶段，但不同的是在这两个阶段需要使用一些不同的命令选项。首先，需要将源文件编译成一种成为位置无关码（PIC: Position Independent Code）的目标文件，这种代码可以被加入到内存的任何位置却不需要加载器对其进行重定位，关于这种格式可以参考《链接器与加载器》和《程序员的自我修养--链接装载与库》中较为详尽的描述。接下来需要将这些位置无关码“归档”为.so文件。整个过程只需一个工具即可，即gcc。还是上面的源文件，执行以下命令：
<pre lang="bash" line="1">
$ cc -c -fpic plus.c sub.c
$ cc -shared -o libmath.so *.o
</pre>]]></description>
			<content:encoded><![CDATA[<h4>库的作用</h4>
<p>　　大体上库的存在，有两方面的原因，一是代码的复用，二是声明和实现的分离。将功能相近的使用模块封装成库，使代码的复用、管理和分发变得简单了许多，例如著名的开源图形库ncurses，你可以自行编译，更可以直接使用已经编译好的现成的库文件。另外，由于库是二进制文件，某种意义上讲，将功能的实现部分隐藏了起来，这就为商业代码的保护提供了一种方式。<br />
　　库文件按照链接方式和时机，可以分为动态库和静态库，下面分别介绍它们在Linux环境中的创建和使用方法。</p>
<h4>静态链接库</h4>
<p>　　静态库是指在程序的链接阶段，其中被用到的代码会被直接链接到可执行文件中的库。静态链接的可执行程序包含了其所需的全部库函数：所有库函数都连接到程序中。 这类程序是完整的，其运行不需要外部库的支持。 静态链接程序的优点之一是其安装之前不需要做环境准备工作 。<br />
　　Linux中，静态库的扩展名通常为.a，它仅仅是一些目标文件（.o）的归档（archive）或者说打包，另外，为了链接时能够快速地定位其中的符号（函数、变量名等），静态库还会包含一个对其中符号的索引。<br />
　　创建静态库的过程十分简单，除编译所必须的工具之外，要用到的命令只有两个ar和ranlib。ar可以将各个目标文件进行归档，ranlib对ar生成的归档文件（即静态库文件）进行索引。假设现在有这样几个源文件：plus.c, sub.c及相应的头文件，另外还有一个用来调用库文件中函数的主文件main.c，它们的内容分别是：<br />
plus.c,</p>

<div class="wp_codebox"><table><tr id="p234054"><td class="line_numbers"><pre>1
2
3
4
5
6
</pre></td><td class="code" id="p2340code54"><pre class="cpp" style="font-family:monospace;"><span style="color: #339900;">#include &quot;plus.h&quot;</span>
<span style="color: #0000ff;">int</span>
plus<span style="color: #008000;">&#40;</span><span style="color: #0000ff;">int</span> a, <span style="color: #0000ff;">int</span> b<span style="color: #008000;">&#41;</span>
<span style="color: #008000;">&#123;</span>
    <span style="color: #0000ff;">return</span> a <span style="color: #000040;">+</span> b<span style="color: #008080;">;</span>
<span style="color: #008000;">&#125;</span></pre></td></tr></table></div>

<p>sub.c,</p>

<div class="wp_codebox"><table><tr id="p234055"><td class="line_numbers"><pre>1
2
3
4
5
6
</pre></td><td class="code" id="p2340code55"><pre class="cpp" style="font-family:monospace;"><span style="color: #339900;">#include &quot;sub.h&quot;</span>
<span style="color: #0000ff;">int</span>
sub<span style="color: #008000;">&#40;</span><span style="color: #0000ff;">int</span> a, <span style="color: #0000ff;">int</span> b<span style="color: #008000;">&#41;</span>
<span style="color: #008000;">&#123;</span>
    <span style="color: #0000ff;">return</span> a <span style="color: #000040;">-</span> b<span style="color: #008080;">;</span>
<span style="color: #008000;">&#125;</span></pre></td></tr></table></div>

<p>main.c,</p>

<div class="wp_codebox"><table><tr id="p234056"><td class="line_numbers"><pre>1
2
3
4
5
6
7
8
9
10
11
</pre></td><td class="code" id="p2340code56"><pre class="cpp" style="font-family:monospace;"><span style="color: #339900;">#include &lt;stdio.h&gt;</span>
<span style="color: #339900;">#include &lt;stdlib.h&gt;</span>
<span style="color: #339900;">#include &lt;unistd.h&gt;</span>
<span style="color: #339900;">#include &quot;plus.h&quot;</span>
<span style="color: #0000ff;">int</span>
main<span style="color: #008000;">&#40;</span><span style="color: #0000ff;">int</span> argc, <span style="color: #0000ff;">char</span> <span style="color: #000040;">**</span>argv<span style="color: #008000;">&#41;</span>
<span style="color: #008000;">&#123;</span>
    <span style="color: #0000ff;">int</span> a <span style="color: #000080;">=</span> plus<span style="color: #008000;">&#40;</span><span style="color: #0000dd;">1</span>, <span style="color: #0000dd;">2</span><span style="color: #008000;">&#41;</span><span style="color: #008080;">;</span>
    <span style="color: #0000dd;">printf</span><span style="color: #008000;">&#40;</span><span style="color: #FF0000;">&quot;%d<span style="color: #000099; font-weight: bold;">\n</span>&quot;</span>, a<span style="color: #008000;">&#41;</span><span style="color: #008080;">;</span>
    <span style="color: #0000ff;">return</span> <span style="color: #0000dd;">0</span><span style="color: #008080;">;</span>
<span style="color: #008000;">&#125;</span></pre></td></tr></table></div>

<p>　　下面将plus.c和sub.c编译，制作成静态库libmath.a，依次执行：</p>

<div class="wp_codebox"><table><tr id="p234057"><td class="line_numbers"><pre>1
2
3
</pre></td><td class="code" id="p2340code57"><pre class="bash" style="font-family:monospace;">$ <span style="color: #c20cb9; font-weight: bold;">cc</span> <span style="color: #660033;">-c</span> plus.c sub.c
$ <span style="color: #c20cb9; font-weight: bold;">ar</span> rc libmath.a plus.o sub.o
$ ranlib libmath.a</pre></td></tr></table></div>

<p>　　现在我们的libmath.a静态库已经制作完成，其中使用了ar命令的两个选项，c表示若库文件不存在则创建之，r表示库文件中若已经存在某个目标文件，且较旧，则执行替换。使用这个静态库更加简单：</p>

<div class="wp_codebox"><table><tr id="p234058"><td class="line_numbers"><pre>1
2
3
</pre></td><td class="code" id="p2340code58"><pre class="bash" style="font-family:monospace;">$ <span style="color: #c20cb9; font-weight: bold;">cc</span> main.c -L. <span style="color: #660033;">-lmath</span> <span style="color: #660033;">-o</span> main
$ .<span style="color: #000000; font-weight: bold;">/</span>main
<span style="color: #000000;">3</span></pre></td></tr></table></div>

<h4>动态链接库</h4>
<p>　　动态库和静态库相似，也是各个目标文件的集合。但相比静态链接的程序，动态链接可执行程序要小得多：这类程序运行时需要外部共享 函数库的支持，因此好像并不完整。除了程序体小之外，动态链接允许程序包指定必须的库，而不必将库装入程序包内。动态链接技术还允许多个运行中的程序共享一个库，这样就不会出现同一代码的多份拷贝共占内存的情况了。由于这些原因，当前多数程序采用动态链接技术。<br />
　　在Linux中的扩展名通常为.so。但在链接时，并不会被链接到可执行文件中，而是在执行时（需要时）由操作系统的动态加载模块动态地加载到内存，并链接到可执行文件地址空间的相应位置。<br />
　　动态链接库的创建也分为编译和&#8221;归档&#8221;两个阶段，但不同的是在这两个阶段需要使用一些不同的命令选项。首先，需要将源文件编译成一种成为位置无关码（PIC: Position Independent Code）的目标文件，这种代码可以被加入到内存的任何位置却不需要加载器对其进行重定位，关于这种格式可以参考《链接器与加载器》和《程序员的自我修养&#8211;链接装载与库》中较为详尽的描述。接下来需要将这些位置无关码“归档”为.so文件。整个过程只需一个工具即可，即gcc。还是上面的源文件，执行以下命令：</p>

<div class="wp_codebox"><table><tr id="p234059"><td class="line_numbers"><pre>1
2
</pre></td><td class="code" id="p2340code59"><pre class="bash" style="font-family:monospace;">$ <span style="color: #c20cb9; font-weight: bold;">cc</span> <span style="color: #660033;">-c</span> <span style="color: #660033;">-fpic</span> plus.c sub.c
$ <span style="color: #c20cb9; font-weight: bold;">cc</span> <span style="color: #660033;">-shared</span> <span style="color: #660033;">-o</span> libmath.so <span style="color: #000000; font-weight: bold;">*</span>.o</pre></td></tr></table></div>

<p>　　这样，包含plus.o和sub.o的动态库文件libmath.so就创建完成了。其中cc（gcc的符号链接）命令的-fpic或-fPIC选项使之创建位置无关的目标文件，使用-shared选项可以创建最终的动态库文件。<br />
　　使用动态库文件有两种方法，一种是让操作系统的动态加载模块（如ld-linux.so.2）在执行时加载动态库。另一种是在代码中使用dl库动态加载库文件。<br />
　　先介绍下第一种方法。使用这种方法需要在编译可执行文件时指明库名及其路径（对于自己的编写的动态库而言）：</p>

<div class="wp_codebox"><table><tr id="p234060"><td class="line_numbers"><pre>1
</pre></td><td class="code" id="p2340code60"><pre class="bash" style="font-family:monospace;">$ <span style="color: #c20cb9; font-weight: bold;">cc</span> main.c -L. <span style="color: #660033;">-lmath</span> <span style="color: #660033;">-o</span> main</pre></td></tr></table></div>

<p>　　这时可执行文件main就被创建了，上面的命令并没有将libmath.so中相应的目标代码链接到main中（你可以对比一下这里的main和静态链接的main的大小），只是在库中查找和确认main.c中用到的符号而已。但通常这个main现在还无法正常执行，这涉及到系统查找动态库的路径问题，系统通常只在某些指定的目录（标准路径）下查找所需的库文件，若在标准路径中无法找到所需的库，则会到环境变量LD_LIBRARY_PATH（如果存在的话）指定的目录下查找，若仍无法找到就会报错。因为libmath.so在main的当前目录中，而当前目录通常并不在标准路径之列。为了使libmath.so能够被找到和加载，你可以把它放到标准路径中，但更好的方法是将其所在目录加入到LD_LIBRARY_PATH变量中。执行下面的命令：</p>

<div class="wp_codebox"><table><tr id="p234061"><td class="line_numbers"><pre>1
2
3
4
</pre></td><td class="code" id="p2340code61"><pre class="bash" style="font-family:monospace;">$ <span style="color: #007800;">LD_LIBRARY_PATH</span>=<span style="color: #007800;">$LD_LIBRARY_PATH</span>:. <span style="color: #666666; font-style: italic;"># 添加当前目录</span>
$ <span style="color: #7a0874; font-weight: bold;">export</span> LD_LIBRARY_PATH <span style="color: #666666; font-style: italic;"># 将环境变量导出，使其在子shell中可用</span>
$ .<span style="color: #000000; font-weight: bold;">/</span>main
<span style="color: #000000;">3</span></pre></td></tr></table></div>

<p>　　<br />
　　下面介绍使用dl库加载动态库，dl库中函数很少很简练，看main.c代码:</p>

<div class="wp_codebox"><table><tr id="p234062"><td class="line_numbers"><pre>1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
</pre></td><td class="code" id="p2340code62"><pre class="cpp" style="font-family:monospace;"><span style="color: #339900;">#include &lt;stdio.h&gt;</span>
<span style="color: #339900;">#include &lt;stdlib.h&gt;</span>
<span style="color: #339900;">#include &lt;unistd.h&gt;</span>
<span style="color: #339900;">#include &lt;dlfcn.h&gt;</span>
<span style="color: #339900;">#include &quot;plus.h&quot;</span>
<span style="color: #0000ff;">int</span>
main<span style="color: #008000;">&#40;</span><span style="color: #0000ff;">int</span> argc, <span style="color: #0000ff;">char</span> <span style="color: #000040;">**</span>argv<span style="color: #008000;">&#41;</span>
<span style="color: #008000;">&#123;</span>
    <span style="color: #0000ff;">void</span> <span style="color: #000040;">*</span> lib_handle <span style="color: #000080;">=</span> dlopen<span style="color: #008000;">&#40;</span><span style="color: #FF0000;">&quot;./libmath.so&quot;</span>, RTLD_LAZY<span style="color: #008000;">&#41;</span><span style="color: #008080;">;</span>
    <span style="color: #0000ff;">if</span><span style="color: #008000;">&#40;</span>lib_handle<span style="color: #008000;">&#41;</span>
    <span style="color: #008000;">&#123;</span>
        <span style="color: #0000ff;">int</span> <span style="color: #008000;">&#40;</span><span style="color: #000040;">*</span>plus_ptr<span style="color: #008000;">&#41;</span><span style="color: #008000;">&#40;</span><span style="color: #0000ff;">int</span>, <span style="color: #0000ff;">int</span><span style="color: #008000;">&#41;</span> <span style="color: #000080;">=</span> dlsym<span style="color: #008000;">&#40;</span>lib_handle, <span style="color: #FF0000;">&quot;plus&quot;</span><span style="color: #008000;">&#41;</span><span style="color: #008080;">;</span>
        <span style="color: #0000ff;">if</span><span style="color: #008000;">&#40;</span>plus_ptr<span style="color: #008000;">&#41;</span>
        <span style="color: #008000;">&#123;</span>
            <span style="color: #0000ff;">int</span> a <span style="color: #000080;">=</span> plus_ptr<span style="color: #008000;">&#40;</span><span style="color: #0000dd;">1</span>, <span style="color: #0000dd;">2</span><span style="color: #008000;">&#41;</span><span style="color: #008080;">;</span>
            <span style="color: #0000dd;">printf</span><span style="color: #008000;">&#40;</span><span style="color: #FF0000;">&quot;%d<span style="color: #000099; font-weight: bold;">\n</span>&quot;</span>, a<span style="color: #008000;">&#41;</span><span style="color: #008080;">;</span>
        <span style="color: #008000;">&#125;</span>
        dlclose<span style="color: #008000;">&#40;</span>lib_handle<span style="color: #008000;">&#41;</span><span style="color: #008080;">;</span>
    <span style="color: #008000;">&#125;</span>
    <span style="color: #0000ff;">return</span> <span style="color: #0000dd;">0</span><span style="color: #008080;">;</span>
<span style="color: #008000;">&#125;</span></pre></td></tr></table></div>

<p>　　main.c中，首先使用dlopen打开需要的动态库，其中参数RTLD_LAZY指明仅当需要调用该库时才进行加载。dlopen返回一个句柄，dlsym使用该句柄和符号来取得相应函数的地址，这里使用int (*)(int, int)函数指针来接收plus函数的地址。接下来使用得到的函数指针调用相应的函数，最后通过dlclose函数来关闭句柄。编译这个程序需要使用dl动态链接库，因此需要使用gcc的-ldl选项：</p>

<div class="wp_codebox"><table><tr id="p234063"><td class="line_numbers"><pre>1
2
3
</pre></td><td class="code" id="p2340code63"><pre class="bash" style="font-family:monospace;">$ <span style="color: #c20cb9; font-weight: bold;">cc</span> main.c <span style="color: #660033;">-ldl</span> <span style="color: #660033;">-o</span> main
$ .<span style="color: #000000; font-weight: bold;">/</span>main
<span style="color: #000000;">3</span></pre></td></tr></table></div>

<h4>.so与.a文件的对比</h4>
<p>　　最后附上libmath.a和libmath.so文件的内容，使用objdump的-d选项查看的：<br />
libmath.a,</p>
<pre>
In archive libmath.a:

plus.o:     file format elf32-i386
Disassembly of section .text:
00000000 &lt;plus>:
   0:	55                   	push   %ebp
   1:	89 e5                	mov    %esp,%ebp
   3:	8b 45 0c             	mov    0xc(%ebp),%eax
   6:	8b 55 08             	mov    0x8(%ebp),%edx
   9:	8d 04 02             	lea    (%edx,%eax,1),%eax
   c:	5d                   	pop    %ebp
   d:	c3                   	ret    

sub.o:     file format elf32-i386
Disassembly of section .text:
00000000 &lt;sub>:
   0:	55                   	push   %ebp
   1:	89 e5                	mov    %esp,%ebp
   3:	8b 45 0c             	mov    0xc(%ebp),%eax
   6:	8b 55 08             	mov    0x8(%ebp),%edx
   9:	89 d1                	mov    %edx,%ecx
   b:	29 c1                	sub    %eax,%ecx
   d:	89 c8                	mov    %ecx,%eax
   f:	5d                   	pop    %ebp
  10:	c3                   	ret
</pre>
<p>libmath.so:</p>
<pre>
libmath.so:     file format elf32-i386
Disassembly of section .init:
00000324 &lt;_init>:
 324:	55                   	push   %ebp
 325:	89 e5                	mov    %esp,%ebp
 327:	53                   	push   %ebx
 328:	83 ec 04             	sub    $0x4,%esp
......
0000044c &lt;plus>:
 44c:	55                   	push   %ebp
 44d:	89 e5                	mov    %esp,%ebp
 44f:	8b 45 0c             	mov    0xc(%ebp),%eax
 452:	8b 55 08             	mov    0x8(%ebp),%edx
 455:	8d 04 02             	lea    (%edx,%eax,1),%eax
 458:	5d                   	pop    %ebp
 459:	c3                   	ret
 45a:	90                   	nop
 45b:	90                   	nop

0000045c &lt;sub>:
 45c:	55                   	push   %ebp
 45d:	89 e5                	mov    %esp,%ebp
 45f:	8b 45 0c             	mov    0xc(%ebp),%eax
 462:	8b 55 08             	mov    0x8(%ebp),%edx
 465:	89 d1                	mov    %edx,%ecx
 467:	29 c1                	sub    %eax,%ecx
 469:	89 c8                	mov    %ecx,%eax
 46b:	5d                   	pop    %ebp
 46c:	c3                   	ret
 46d:	90                   	nop
 46e:	90                   	nop
 46f:	90                   	nop
......

Disassembly of section .fini:

000004a8 &lt;_fini>:
 4a8:	55                   	push   %ebp
 4a9:	89 e5                	mov    %esp,%ebp
 4ab:	53                   	push   %ebx
 4ac:	83 ec 04             	sub    $0x4,%esp
 4af:	e8 00 00 00 00       	call   4b4 &lt;_fini+0xc>
 4b4:	5b                   	pop    %ebx
 4b5:	81 c3 40 1b 00 00    	add    $0x1b40,%ebx
 4bb:	e8 d0 fe ff ff       	call   390 &lt;__do_global_dtors_aux>
 4c0:	59                   	pop    %ecx
 4c1:	5b                   	pop    %ebx
 4c2:	c9                   	leave
 4c3:	c3                   	ret
</pre>
<p>　　可见，相对.a，.so有很多额外的代码段，其中比较重要的是<_init>段和<_fini>段。它们分别进行一些前期和后期处理工作，例如<_init>通常在dlopen返回之前执行一些.so库中的一些初始化工作（C++中就可能是全局构造或者静态对象的构造函数）。</p>
]]></content:encoded>
			<wfw:commentRss>http://www.dutor.net/index.php/2010/07/dynamic-static-library/feed/</wfw:commentRss>
		<slash:comments>6</slash:comments>
		</item>
		<item>
		<title>[命令技巧]使用find查找文件</title>
		<link>http://www.dutor.net/index.php/2010/07/cmd-find/</link>
		<comments>http://www.dutor.net/index.php/2010/07/cmd-find/#comments</comments>
		<pubDate>Sun, 04 Jul 2010 06:54:59 +0000</pubDate>
		<dc:creator>dutor</dc:creator>
				<category><![CDATA[Unix/Linux]]></category>
		<category><![CDATA[find]]></category>
		<category><![CDATA[命令]]></category>

		<guid isPermaLink="false">http://www.dutor.net/?p=2336</guid>
		<description><![CDATA[　　find命令可以按照指定的规则对硬盘上的文件进行查找，且可以跨越不同的文件系统。find命令的使用方法：
<pre lang="bash" line="1">find fold [option]</pre>
　　下面按照不同的选项介绍find命令。
<h4>find -name</h4>
　　-name是最常用的选项，它指定了需要查找的文件名的模式，模式中可以使用通配符和简单的正则表达式。下面的命令查找Wdir目录下的.cpp文件：
<pre lang="bash" line="1">dutor@dutor-desktop:~$ find Wdir -name "*.cpp"
Wdir/Cpp/Pthread/main.cpp
Wdir/Cpp/STL/sort_list.cpp
Wdir/Cpp/STL/Heap.cpp
Wdir/Cpp/STL/operator.cpp
Wdir/Cpp/STL/bind2nd/main.cpp
Wdir/Cpp/STL/Kth-Max.cpp
Wdir/Cpp/STL/priority_queue.cpp
Wdir/Cpp/ACM/Huffman/main.cpp
Wdir/Cpp/ACM/Bellman-Ford/main.cpp
......</pre>
　　需要注意的是，如果搜索目录以相对路径形式指定，则搜索结果也以相对路径形式给出；否则，搜索结果以绝对路径形式给出。]]></description>
			<content:encoded><![CDATA[<p>　　find命令可以按照指定的规则对硬盘上的文件进行查找，且可以跨越不同的文件系统。find命令的使用方法：</p>

<div class="wp_codebox"><table><tr id="p233664"><td class="line_numbers"><pre>1
</pre></td><td class="code" id="p2336code64"><pre class="bash" style="font-family:monospace;"><span style="color: #c20cb9; font-weight: bold;">find</span> fold <span style="color: #7a0874; font-weight: bold;">&#91;</span>option<span style="color: #7a0874; font-weight: bold;">&#93;</span></pre></td></tr></table></div>

<p>　　下面按照不同的选项介绍find命令。</p>
<h4>find -name</h4>
<p>　　-name是最常用的选项，它指定了需要查找的文件名的模式，模式中可以使用通配符和简单的正则表达式。下面的命令查找Wdir目录下的.cpp文件：</p>

<div class="wp_codebox"><table><tr id="p233665"><td class="line_numbers"><pre>1
2
3
4
5
6
7
8
9
10
11
</pre></td><td class="code" id="p2336code65"><pre class="bash" style="font-family:monospace;">dutor<span style="color: #000000; font-weight: bold;">@</span>dutor-desktop:~$ <span style="color: #c20cb9; font-weight: bold;">find</span> Wdir <span style="color: #660033;">-name</span> <span style="color: #ff0000;">&quot;*.cpp&quot;</span>
Wdir<span style="color: #000000; font-weight: bold;">/</span>Cpp<span style="color: #000000; font-weight: bold;">/</span>Pthread<span style="color: #000000; font-weight: bold;">/</span>main.cpp
Wdir<span style="color: #000000; font-weight: bold;">/</span>Cpp<span style="color: #000000; font-weight: bold;">/</span>STL<span style="color: #000000; font-weight: bold;">/</span>sort_list.cpp
Wdir<span style="color: #000000; font-weight: bold;">/</span>Cpp<span style="color: #000000; font-weight: bold;">/</span>STL<span style="color: #000000; font-weight: bold;">/</span>Heap.cpp
Wdir<span style="color: #000000; font-weight: bold;">/</span>Cpp<span style="color: #000000; font-weight: bold;">/</span>STL<span style="color: #000000; font-weight: bold;">/</span>operator.cpp
Wdir<span style="color: #000000; font-weight: bold;">/</span>Cpp<span style="color: #000000; font-weight: bold;">/</span>STL<span style="color: #000000; font-weight: bold;">/</span>bind2nd<span style="color: #000000; font-weight: bold;">/</span>main.cpp
Wdir<span style="color: #000000; font-weight: bold;">/</span>Cpp<span style="color: #000000; font-weight: bold;">/</span>STL<span style="color: #000000; font-weight: bold;">/</span>Kth-Max.cpp
Wdir<span style="color: #000000; font-weight: bold;">/</span>Cpp<span style="color: #000000; font-weight: bold;">/</span>STL<span style="color: #000000; font-weight: bold;">/</span>priority_queue.cpp
Wdir<span style="color: #000000; font-weight: bold;">/</span>Cpp<span style="color: #000000; font-weight: bold;">/</span>ACM<span style="color: #000000; font-weight: bold;">/</span>Huffman<span style="color: #000000; font-weight: bold;">/</span>main.cpp
Wdir<span style="color: #000000; font-weight: bold;">/</span>Cpp<span style="color: #000000; font-weight: bold;">/</span>ACM<span style="color: #000000; font-weight: bold;">/</span>Bellman-Ford<span style="color: #000000; font-weight: bold;">/</span>main.cpp
......</pre></td></tr></table></div>

<p>　　需要注意的是，如果搜索目录以相对路径形式指定，则搜索结果也以相对路径形式给出；否则，搜索结果以绝对路径形式给出。</p>
<h4>find -user</h4>
<p>　　-user选项指定需要搜索的文件的属主/用户。相似地，-group指定需要搜索的用户组。</p>
<h4>find -type</h4>
<p>　　-type选项指定文件的类型，该选项可以使用的参数如下：</p>
<table>
<tr>
<th>文件类型字符</th>
<th>含义</th>
</tr>
<tr>
<td>f</td>
<td>普通文件</td>
</tr>
<tr>
<td>d</td>
<td>目录</td>
</tr>
<tr>
<td>l</td>
<td>符号链接</td>
</tr>
<tr>
<td>b</td>
<td>块文件</td>
</tr>
<tr>
<td>c</td>
<td>字符文件</td>
</tr>
<tr>
<td>p</td>
<td>FIFO管道文件</td>
</tr>
<tr>
<td>s</td>
<td>套接字</td>
</tr>
</table>
<h4>find ! -option</h4>
<p>　　!可以对特定选项进行反义，下面命令搜索不属于dutor用户的.cpp文件：</p>

<div class="wp_codebox"><table><tr id="p233666"><td class="line_numbers"><pre>1
</pre></td><td class="code" id="p2336code66"><pre class="bash" style="font-family:monospace;"><span style="color: #c20cb9; font-weight: bold;">find</span> . <span style="color: #660033;">-name</span> <span style="color: #ff0000;">&quot;*.cpp&quot;</span> <span style="color: #000000; font-weight: bold;">!</span> <span style="color: #660033;">-user</span> dutor</pre></td></tr></table></div>

<p>　　注意!与-之间的空格。</p>
<h4>find -size</h4>
<p>　　使用-size选项可以根据文件的大小进行查找。下面命令查找大小为10M(近似)的文件：</p>

<div class="wp_codebox"><table><tr id="p233667"><td class="line_numbers"><pre>1
</pre></td><td class="code" id="p2336code67"><pre class="bash" style="font-family:monospace;"><span style="color: #c20cb9; font-weight: bold;">find</span> . <span style="color: #660033;">-size</span> 10M</pre></td></tr></table></div>

<p>　　-size选项的参数的单位可以是</p>
<table>
<tr>
<th>单位字符</th>
<th>含义</th>
</tr>
<tr>
<td>b</td>
<td>block，默认512字节</td>
</tr>
<tr>
<td>c</td>
<td>字节</td>
</tr>
<tr>
<td>k</td>
<td>1024字节</td>
</tr>
<tr>
<td>M</td>
<td>1024k</td>
</tr>
<tr>
<td>G</td>
<td>1024M</td>
</tr>
</table>
<p>　　另外，-size参数前还可以使用+和-，分别表示大于和小于指定大小的文件。例如下面命令查找大于10M的文件：</p>

<div class="wp_codebox"><table><tr id="p233668"><td class="line_numbers"><pre>1
</pre></td><td class="code" id="p2336code68"><pre class="bash" style="font-family:monospace;"><span style="color: #c20cb9; font-weight: bold;">find</span> . <span style="color: #660033;">-size</span> +10M</pre></td></tr></table></div>

<h4>find -a</h4>
<p>　　find命令的各选项可以利用-a, -o, -n进行逻辑组合。-a表示AND，-o表示OR，-n表示NOT。另外还可以使用转义的括号\(\)对逻辑表达式进行分组。例如下面命令查找大于或等于10M的普通文件：</p>

<div class="wp_codebox"><table><tr id="p233669"><td class="line_numbers"><pre>1
</pre></td><td class="code" id="p2336code69"><pre class="bash" style="font-family:monospace;"><span style="color: #c20cb9; font-weight: bold;">find</span> . \<span style="color: #7a0874; font-weight: bold;">&#40;</span> <span style="color: #660033;">-size</span> +10M <span style="color: #660033;">-o</span> <span style="color: #660033;">-size</span> 10M \<span style="color: #7a0874; font-weight: bold;">&#41;</span> <span style="color: #660033;">-a</span> <span style="color: #660033;">-type</span> f</pre></td></tr></table></div>

<h4>find -exec</h4>
<p>　　-exec是一个非常有用的选项，它允许对find的查找结果文件执行某个命令。例如，想把当前目录下所有的扩展名为.JPG的图片扩展名改为.jpg，可以执行如下命令：</p>

<div class="wp_codebox"><table><tr id="p233670"><td class="line_numbers"><pre>1
</pre></td><td class="code" id="p2336code70"><pre class="bash" style="font-family:monospace;"><span style="color: #c20cb9; font-weight: bold;">find</span> . <span style="color: #660033;">-name</span> <span style="color: #ff0000;">&quot;*.JPG&quot;</span> <span style="color: #660033;">-exec</span> rename <span style="color: #ff0000;">'s/JPG/jpg/g'</span> <span style="color: #7a0874; font-weight: bold;">&#123;</span><span style="color: #7a0874; font-weight: bold;">&#125;</span> \;</pre></td></tr></table></div>

<p>　　其中{}表示find查找结果文件中的一个的文件名，转义的分号\;作为exec选项的结束，另外\;之前需要一个空格。</p>
]]></content:encoded>
			<wfw:commentRss>http://www.dutor.net/index.php/2010/07/cmd-find/feed/</wfw:commentRss>
		<slash:comments>2</slash:comments>
		</item>
		<item>
		<title>软链接与硬链接</title>
		<link>http://www.dutor.net/index.php/2010/07/symbol-hard-links/</link>
		<comments>http://www.dutor.net/index.php/2010/07/symbol-hard-links/#comments</comments>
		<pubDate>Thu, 01 Jul 2010 13:15:54 +0000</pubDate>
		<dc:creator>dutor</dc:creator>
				<category><![CDATA[Unix/Linux]]></category>
		<category><![CDATA[OS基础]]></category>
		<category><![CDATA[命令]]></category>

		<guid isPermaLink="false">http://www.dutor.net/?p=2326</guid>
		<description><![CDATA[　　Linux/Unix中有两种链接，硬链接和软链接，均由ln命令来创建。
<h4>软链接</h4>
　　软链接使用ln命令的-s选项创建：
<pre lang="bash" line="1">ln -s source target #创建source文件的软链接target</pre>
　　软链接类似于Windows中的快捷方式，内部保存的是源文件的路径，路径可以是相对路径，也可以是绝对路径：
<pre lang="bash" line="1">
dutor@dutor-desktop:~$ ln -s gvim.tgz gvim
dutor@dutor-desktop:~$ ln -s /home/dutor/gvim.tgz gvim2
dutor@dutor-desktop:~$ ll gvim* # alias ll='ls -l'
lrwxrwxrwx 1 dutor dutor    8 2010-07-01 20:32 gvim -> gvim.tgz
lrwxrwxrwx 1 dutor dutor   20 2010-07-01 20:33 gvim2 -> /home/dutor/gvim.tgz
-rw-r--r-- 1 dutor dutor 8.5M 2010-06-29 23:06 gvim.tgz
</pre>
　　软链接应用十分广泛。]]></description>
			<content:encoded><![CDATA[<p>　　Linux/Unix中有两种链接，硬链接和软链接，均由ln命令来创建。</p>
<h4>软链接</h4>
<p>　　软链接使用ln命令的-s选项创建：</p>

<div class="wp_codebox"><table><tr id="p232671"><td class="line_numbers"><pre>1
</pre></td><td class="code" id="p2326code71"><pre class="bash" style="font-family:monospace;"><span style="color: #c20cb9; font-weight: bold;">ln</span> <span style="color: #660033;">-s</span> <span style="color: #7a0874; font-weight: bold;">source</span> target <span style="color: #666666; font-style: italic;">#创建source文件的软链接target</span></pre></td></tr></table></div>

<p>　　软链接类似于Windows中的快捷方式，内部保存的是源文件的路径，路径可以是相对路径，也可以是绝对路径：</p>

<div class="wp_codebox"><table><tr id="p232672"><td class="line_numbers"><pre>1
2
3
4
5
6
</pre></td><td class="code" id="p2326code72"><pre class="bash" style="font-family:monospace;">dutor<span style="color: #000000; font-weight: bold;">@</span>dutor-desktop:~$ <span style="color: #c20cb9; font-weight: bold;">ln</span> <span style="color: #660033;">-s</span> gvim.tgz gvim
dutor<span style="color: #000000; font-weight: bold;">@</span>dutor-desktop:~$ <span style="color: #c20cb9; font-weight: bold;">ln</span> <span style="color: #660033;">-s</span> <span style="color: #000000; font-weight: bold;">/</span>home<span style="color: #000000; font-weight: bold;">/</span>dutor<span style="color: #000000; font-weight: bold;">/</span>gvim.tgz gvim2
dutor<span style="color: #000000; font-weight: bold;">@</span>dutor-desktop:~$ ll gvim<span style="color: #000000; font-weight: bold;">*</span> <span style="color: #666666; font-style: italic;"># alias ll='ls -l'</span>
lrwxrwxrwx <span style="color: #000000;">1</span> dutor dutor    <span style="color: #000000;">8</span> <span style="color: #000000;">2010</span>-07-01 <span style="color: #000000;">20</span>:<span style="color: #000000;">32</span> gvim -<span style="color: #000000; font-weight: bold;">&gt;</span> gvim.tgz
lrwxrwxrwx <span style="color: #000000;">1</span> dutor dutor   <span style="color: #000000;">20</span> <span style="color: #000000;">2010</span>-07-01 <span style="color: #000000;">20</span>:<span style="color: #000000;">33</span> gvim2 -<span style="color: #000000; font-weight: bold;">&gt;</span> <span style="color: #000000; font-weight: bold;">/</span>home<span style="color: #000000; font-weight: bold;">/</span>dutor<span style="color: #000000; font-weight: bold;">/</span>gvim.tgz
<span style="color: #660033;">-rw-r--r--</span> <span style="color: #000000;">1</span> dutor dutor 8.5M <span style="color: #000000;">2010</span>-06-<span style="color: #000000;">29</span> <span style="color: #000000;">23</span>:06 gvim.tgz</pre></td></tr></table></div>

<p>　　软链接应用十分广泛。<br />
　　在文件系统中多处共享同一个较大文件时，使用软链接就可以避免创建多个副本。<br />
　　维护动态库文件的版本时，使用软链接，在升级库文件后，只需修改软链接的源文件，而使用该库的程序则不需要修改。</p>
<h4>硬链接</h4>
<p>　　不带有任何选项的ln命令即可创建硬链接：</p>

<div class="wp_codebox"><table><tr id="p232673"><td class="line_numbers"><pre>1
</pre></td><td class="code" id="p2326code73"><pre class="bash" style="font-family:monospace;"><span style="color: #c20cb9; font-weight: bold;">ln</span> <span style="color: #7a0874; font-weight: bold;">source</span> target <span style="color: #666666; font-style: italic;">#创建source文件的硬链接target</span></pre></td></tr></table></div>

<p>　　硬链接创建后，链接文件与源文件没有主次之分，文件系统中它们都和同一个inode相关联，即具有相同的inode号：</p>

<div class="wp_codebox"><table><tr id="p232674"><td class="line_numbers"><pre>1
2
3
4
</pre></td><td class="code" id="p2326code74"><pre class="bash" style="font-family:monospace;">dutor<span style="color: #000000; font-weight: bold;">@</span>dutor-desktop:~$ <span style="color: #c20cb9; font-weight: bold;">ln</span> gvim.tgz gvim
dutor<span style="color: #000000; font-weight: bold;">@</span>dutor-desktop:~$ ll <span style="color: #660033;">-i</span> gvim<span style="color: #000000; font-weight: bold;">*</span>
<span style="color: #000000;">1048032</span> <span style="color: #660033;">-rw-r--r--</span> <span style="color: #000000;">2</span> dutor dutor 8.5M <span style="color: #000000;">2010</span>-06-<span style="color: #000000;">29</span> <span style="color: #000000;">23</span>:06 gvim <span style="color: #666666; font-style: italic;"># 第3个域代表该文件的链接数</span>
<span style="color: #000000;">1048032</span> <span style="color: #660033;">-rw-r--r--</span> <span style="color: #000000;">2</span> dutor dutor 8.5M <span style="color: #000000;">2010</span>-06-<span style="color: #000000;">29</span> <span style="color: #000000;">23</span>:06 gvim.tgz</pre></td></tr></table></div>

<p>　　因此，系统不允许用户为目录创建硬件链接，否则，目录树就不再是有向无环的了。只许州官放火，不许百姓点灯，系统却可以为目录“创建”硬链接（系统知道自己在做什么，却不知用户会做什么），那就是.和..分别指向当前目录和上级目录。因此每个目录的链接数至少是2.</p>
<p>　　另外，由于硬链接的实现依赖于特定的文件系统，因此不可以跨文件系统。而软链接是基于路径的，所以只要是挂载在系统目录树中的文件或目录，都可以创建软链接。</p>
]]></content:encoded>
			<wfw:commentRss>http://www.dutor.net/index.php/2010/07/symbol-hard-links/feed/</wfw:commentRss>
		<slash:comments>2</slash:comments>
		</item>
		<item>
		<title>[命令技巧]ls</title>
		<link>http://www.dutor.net/index.php/2010/06/cmd-ls/</link>
		<comments>http://www.dutor.net/index.php/2010/06/cmd-ls/#comments</comments>
		<pubDate>Sun, 06 Jun 2010 14:37:12 +0000</pubDate>
		<dc:creator>dutor</dc:creator>
				<category><![CDATA[Unix/Linux]]></category>
		<category><![CDATA[命令]]></category>

		<guid isPermaLink="false">http://www.dutor.net/?p=2313</guid>
		<description><![CDATA[　　ls == list，根据不同的选项，列举指定目录或文件的相关信息，是Unix/Linux下最常用的命令之一，cd到某一目录下后执行的第一个命令。
<h4>ls</h4>
　　不带参数的ls列举当前目录下有哪些文件和目录，ls Folder列举Folder目录中的文件和子目录，ls File显示File文件的信息（默认为文件名）。
<pre lang="bash" line="1">
dutor@dutor-desktop:~$ cd Wdir/
/home/dutor/Wdir
dutor@dutor-desktop:~/Wdir$ ls
APUE  ASM  Cpp  LaTeX  PHP  Python  QT  Shell
dutor@dutor-desktop:~/Wdir$ ls Cpp/
ACM     main    main.cpp  Makefile    Pthread  symtab         tags    test.s
Curses  main.c  main.s    Playaround  STL      SystemProgram  test.c  TutManual
dutor@dutor-desktop:~/Wdir$ ls Cpp/Makefile
Cpp/Makefile
</pre>]]></description>
			<content:encoded><![CDATA[<p>　　ls == list，根据不同的选项，列举指定目录或文件的相关信息，是Unix/Linux下最常用的命令之一，cd到某一目录下后执行的第一个命令。</p>
<h4>ls</h4>
<p>　　不带参数的ls列举当前目录下有哪些文件和目录，ls Folder列举Folder目录中的文件和子目录，ls File显示File文件的信息（默认为文件名）。</p>

<div class="wp_codebox"><table><tr id="p231375"><td class="line_numbers"><pre>1
2
3
4
5
6
7
8
9
</pre></td><td class="code" id="p2313code75"><pre class="bash" style="font-family:monospace;">dutor<span style="color: #000000; font-weight: bold;">@</span>dutor-desktop:~$ <span style="color: #7a0874; font-weight: bold;">cd</span> Wdir<span style="color: #000000; font-weight: bold;">/</span>
<span style="color: #000000; font-weight: bold;">/</span>home<span style="color: #000000; font-weight: bold;">/</span>dutor<span style="color: #000000; font-weight: bold;">/</span>Wdir
dutor<span style="color: #000000; font-weight: bold;">@</span>dutor-desktop:~<span style="color: #000000; font-weight: bold;">/</span>Wdir$ <span style="color: #c20cb9; font-weight: bold;">ls</span>
APUE  ASM  Cpp  LaTeX  PHP  Python  QT  Shell
dutor<span style="color: #000000; font-weight: bold;">@</span>dutor-desktop:~<span style="color: #000000; font-weight: bold;">/</span>Wdir$ <span style="color: #c20cb9; font-weight: bold;">ls</span> Cpp<span style="color: #000000; font-weight: bold;">/</span>
ACM     main    main.cpp  Makefile    Pthread  symtab         tags    test.s
Curses  main.c  main.s    Playaround  STL      SystemProgram  test.c  TutManual
dutor<span style="color: #000000; font-weight: bold;">@</span>dutor-desktop:~<span style="color: #000000; font-weight: bold;">/</span>Wdir$ <span style="color: #c20cb9; font-weight: bold;">ls</span> Cpp<span style="color: #000000; font-weight: bold;">/</span>Makefile
Cpp<span style="color: #000000; font-weight: bold;">/</span>Makefile</pre></td></tr></table></div>

<h4>ls -a</h4>
<p>　　-a选项同ls，但会列举当前目录或者指定目录下的所有文件，包括dot文件（.开头的文件）和.目录和..目录。</p>

<div class="wp_codebox"><table><tr id="p231376"><td class="line_numbers"><pre>1
2
</pre></td><td class="code" id="p2313code76"><pre class="bash" style="font-family:monospace;">dutor<span style="color: #000000; font-weight: bold;">@</span>dutor-desktop:~<span style="color: #000000; font-weight: bold;">/</span>Wdir$ <span style="color: #c20cb9; font-weight: bold;">ls</span> <span style="color: #660033;">-a</span>
.  ..  APUE  ASM  Cpp  .I2C.c.swp  LaTeX  PHP  Python  QT  Shell</pre></td></tr></table></div>

<h4>ls -A</h4>
<p>　　-A选项同ls，但会列举当前目录或者指定目录下的所有文件，包括dot文件（.开头的文件），但不包括.目录和..目录。</p>

<div class="wp_codebox"><table><tr id="p231377"><td class="line_numbers"><pre>1
2
</pre></td><td class="code" id="p2313code77"><pre class="bash" style="font-family:monospace;">dutor<span style="color: #000000; font-weight: bold;">@</span>dutor-desktop:~<span style="color: #000000; font-weight: bold;">/</span>Wdir$ <span style="color: #c20cb9; font-weight: bold;">ls</span> <span style="color: #660033;">-A</span>
APUE  ASM  Cpp  .I2C.c.swp  LaTeX  PHP  Python  QT  Shell</pre></td></tr></table></div>

<h4>ls -l</h4>
<p>　　-l选项的ls命令将列举当前目录或指定目录中文件或者子目录的详析信息。</p>

<div class="wp_codebox"><table><tr id="p231378"><td class="line_numbers"><pre>1
2
3
4
5
6
7
8
9
10
</pre></td><td class="code" id="p2313code78"><pre class="bash" style="font-family:monospace;">dutor<span style="color: #000000; font-weight: bold;">@</span>dutor-desktop:~<span style="color: #000000; font-weight: bold;">/</span>Wdir<span style="color: #000000; font-weight: bold;">/</span>Cpp<span style="color: #000000; font-weight: bold;">/</span>STL$ <span style="color: #c20cb9; font-weight: bold;">ls</span> <span style="color: #660033;">-l</span>
total <span style="color: #000000;">32</span>
drwxr-xr-x <span style="color: #000000;">2</span> dutor dutor <span style="color: #000000;">4096</span> <span style="color: #000000;">2010</span>-04-<span style="color: #000000;">19</span> <span style="color: #000000;">19</span>:<span style="color: #000000;">25</span> bind2nd
<span style="color: #660033;">-rw-r--r--</span> <span style="color: #000000;">1</span> dutor dutor <span style="color: #000000;">1296</span> <span style="color: #000000;">2010</span>-03-<span style="color: #000000;">27</span> <span style="color: #000000;">18</span>:<span style="color: #000000;">39</span> Heap.cpp
<span style="color: #660033;">-rw-r--r--</span> <span style="color: #000000;">1</span> dutor dutor  <span style="color: #000000;">980</span> <span style="color: #000000;">2010</span>-03-<span style="color: #000000;">27</span> <span style="color: #000000;">18</span>:03 Kth-Max.cpp
<span style="color: #660033;">-rw-r--r--</span> <span style="color: #000000;">1</span> dutor dutor <span style="color: #000000;">1168</span> <span style="color: #000000;">2010</span>-04-<span style="color: #000000;">29</span> <span style="color: #000000;">20</span>:<span style="color: #000000;">24</span> main.cpp
<span style="color: #660033;">-rw-r--r--</span> <span style="color: #000000;">1</span> dutor dutor  <span style="color: #000000;">709</span> <span style="color: #000000;">2010</span>-04-<span style="color: #000000;">20</span> <span style="color: #000000;">17</span>:<span style="color: #000000;">58</span> operator.cpp
<span style="color: #660033;">-rw-r--r--</span> <span style="color: #000000;">1</span> dutor dutor  <span style="color: #000000;">654</span> <span style="color: #000000;">2010</span>-03-<span style="color: #000000;">27</span> <span style="color: #000000;">17</span>:<span style="color: #000000;">40</span> priority_queue.cpp
<span style="color: #660033;">-rw-r--r--</span> <span style="color: #000000;">1</span> dutor dutor  <span style="color: #000000;">461</span> <span style="color: #000000;">2010</span>-04-<span style="color: #000000;">10</span> <span style="color: #000000;">22</span>:<span style="color: #000000;">41</span> sort_list.cpp
<span style="color: #660033;">-rw-r--r--</span> <span style="color: #000000;">1</span> dutor dutor  <span style="color: #000000;">655</span> <span style="color: #000000;">2010</span>-04-<span style="color: #000000;">29</span> <span style="color: #000000;">21</span>:<span style="color: #000000;">18</span> test.cpp</pre></td></tr></table></div>

<p>ls -l列举的信息包含7个以Tab的域：</p>
<ul>
<li>第一个域：第一个字符指明了文件类型
<ul>
<li>-: 普通文件；</li>
<li>d: 目录文件；</li>
<li>l: 符号链接；</li>
<li>s: socket文件；</li>
<li>b: 块设备；</li>
<li>c: 字符设备；</li>
<li>p: 管道文件。</li>
</ul>
<p>后面的9个字符指明了文件的访问权限：每三位指明一类用户的权限，分别是文件属主、同组用户、其它用户，权限分为读（r）、写（w）、执行（x）。
        </li>
<li>第二个域：链接数。普通文件至少为1，目录至少为2（.和..）；</li>
<li>第三域：文件属主；</li>
<li>第四域：用户组；</li>
<li>第五域：文件大小，其中目录大小通常为块大小的整数倍；</li>
<li>第六域：文件的最近修改日期和时间，修改文件意味着对其内文件或子目录的增添和修改；</li>
<li>第七域：文件名</li>
</ul>
<h4>ls -t</h4>
<p>　　按文件的修改时间列举文件，最近修改的在前。</p>

<div class="wp_codebox"><table><tr id="p231379"><td class="line_numbers"><pre>1
2
3
4
</pre></td><td class="code" id="p2313code79"><pre class="bash" style="font-family:monospace;">dutor<span style="color: #000000; font-weight: bold;">@</span>dutor-desktop:~<span style="color: #000000; font-weight: bold;">/</span>Wdir$ <span style="color: #c20cb9; font-weight: bold;">ls</span>
APUE  ASM  Cpp  LaTeX  PHP  Python  QT  Shell
dutor<span style="color: #000000; font-weight: bold;">@</span>dutor-desktop:~<span style="color: #000000; font-weight: bold;">/</span>Wdir$ <span style="color: #c20cb9; font-weight: bold;">ls</span> <span style="color: #660033;">-t</span>
Cpp  QT  Shell  PHP  ASM  LaTeX  APUE  Python</pre></td></tr></table></div>

<h4>ls -r</h4>
<p>　　以相反顺序列举文件。</p>

<div class="wp_codebox"><table><tr id="p231380"><td class="line_numbers"><pre>1
2
3
4
5
6
</pre></td><td class="code" id="p2313code80"><pre class="bash" style="font-family:monospace;">dutor<span style="color: #000000; font-weight: bold;">@</span>dutor-desktop:~<span style="color: #000000; font-weight: bold;">/</span>Wdir$ <span style="color: #c20cb9; font-weight: bold;">ls</span>
APUE  ASM  Cpp  LaTeX  PHP  Python  QT  Shell
dutor<span style="color: #000000; font-weight: bold;">@</span>dutor-desktop:~<span style="color: #000000; font-weight: bold;">/</span>Wdir$ <span style="color: #c20cb9; font-weight: bold;">ls</span> <span style="color: #660033;">-t</span>
Cpp  QT  Shell  PHP  ASM  LaTeX  APUE  Python
dutor<span style="color: #000000; font-weight: bold;">@</span>dutor-desktop:~<span style="color: #000000; font-weight: bold;">/</span>Wdir$ <span style="color: #c20cb9; font-weight: bold;">ls</span> <span style="color: #660033;">-tr</span>
Python  APUE  LaTeX  ASM  PHP  Shell  QT  Cpp</pre></td></tr></table></div>

<h4>ls -1</h4>
<p>　　单独行列举文件。</p>
<h4>ls -F</h4>
<p>　　可视化显示文件类型。</p>

<div class="wp_codebox"><table><tr id="p231381"><td class="line_numbers"><pre>1
2
</pre></td><td class="code" id="p2313code81"><pre class="bash" style="font-family:monospace;">$ <span style="color: #c20cb9; font-weight: bold;">ls</span> <span style="color: #660033;">-F</span>
Desktop<span style="color: #000000; font-weight: bold;">/</span>  Documents<span style="color: #000000; font-weight: bold;">/</span>  Ubuntu-App<span style="color: #000000; font-weight: bold;">@</span>  firstfile  Music<span style="color: #000000; font-weight: bold;">/</span>  Public<span style="color: #000000; font-weight: bold;">/</span>  Templates<span style="color: #000000; font-weight: bold;">/</span></pre></td></tr></table></div>

<ul>
<li>/ ： 目录</li>
<li>nothing ： 普通文件.</li>
<li>@ ：符号链接文件</li>
<li>* ：可执行文件</li>
</ul>
<h4>ls -latr</h4>
<p>　　即是说，各个选项可以结合使用，除了互相排斥的选项，例如-a和-A。</p>
<h4>使用alias</h4>
<p>使用alias会更加方便，我定义的alias有：</p>

<div class="wp_codebox"><table><tr id="p231382"><td class="line_numbers"><pre>1
2
3
</pre></td><td class="code" id="p2313code82"><pre class="bash" style="font-family:monospace;"><span style="color: #7a0874; font-weight: bold;">alias</span> <span style="color: #007800;">ll</span>=<span style="color: #ff0000;">'ls -lh'</span>
<span style="color: #7a0874; font-weight: bold;">alias</span> <span style="color: #007800;">la</span>=<span style="color: #ff0000;">'ls -A'</span>
<span style="color: #7a0874; font-weight: bold;">alias</span> <span style="color: #007800;">l</span>=<span style="color: #ff0000;">'ls -CF'</span></pre></td></tr></table></div>

]]></content:encoded>
			<wfw:commentRss>http://www.dutor.net/index.php/2010/06/cmd-ls/feed/</wfw:commentRss>
		<slash:comments>1</slash:comments>
		</item>
		<item>
		<title>[命令技巧]mkdir -p</title>
		<link>http://www.dutor.net/index.php/2010/06/cmd-mkdir-p/</link>
		<comments>http://www.dutor.net/index.php/2010/06/cmd-mkdir-p/#comments</comments>
		<pubDate>Sun, 06 Jun 2010 07:43:17 +0000</pubDate>
		<dc:creator>dutor</dc:creator>
				<category><![CDATA[Unix/Linux]]></category>
		<category><![CDATA[命令]]></category>

		<guid isPermaLink="false">http://www.dutor.net/?p=2311</guid>
		<description><![CDATA[　　上一篇<a href="http://www.dutor.net/index.php/2010/05/cmd-mkcd/" target="_blank">[命令技巧]mkcd</a>中，mkcd函数里面使用到了mkdir的-p选项。mkdir的-p选项允许你一次性创建多层次的目录，而不是一次只创建单独的目录。例如，我们要在当前目录创建目录Projects/a/src，使用命令
<pre lang="bash" line="1">mkdir -p Project/a/src</pre>
而不是
<pre lang="bash" line="1">
mkdir Project
cd Project
mkdir a
cd a
mkdir src
</pre>]]></description>
			<content:encoded><![CDATA[<p>　　上一篇<a href="http://www.dutor.net/index.php/2010/05/cmd-mkcd/" target="_blank">[命令技巧]mkcd</a>中，mkcd函数里面使用到了mkdir的-p选项。mkdir的-p选项允许你一次性创建多层次的目录，而不是一次只创建单独的目录。例如，我们要在当前目录创建目录Projects/a/src，使用命令</p>

<div class="wp_codebox"><table><tr id="p231183"><td class="line_numbers"><pre>1
</pre></td><td class="code" id="p2311code83"><pre class="bash" style="font-family:monospace;"><span style="color: #c20cb9; font-weight: bold;">mkdir</span> <span style="color: #660033;">-p</span> Project<span style="color: #000000; font-weight: bold;">/</span>a<span style="color: #000000; font-weight: bold;">/</span>src</pre></td></tr></table></div>

<p>而不是</p>

<div class="wp_codebox"><table><tr id="p231184"><td class="line_numbers"><pre>1
2
3
4
5
</pre></td><td class="code" id="p2311code84"><pre class="bash" style="font-family:monospace;"><span style="color: #c20cb9; font-weight: bold;">mkdir</span> Project
<span style="color: #7a0874; font-weight: bold;">cd</span> Project
<span style="color: #c20cb9; font-weight: bold;">mkdir</span> a
<span style="color: #7a0874; font-weight: bold;">cd</span> a
<span style="color: #c20cb9; font-weight: bold;">mkdir</span> src</pre></td></tr></table></div>

<p>　　当然，如果你有mkcd，就可以直接</p>

<div class="wp_codebox"><table><tr id="p231185"><td class="line_numbers"><pre>1
</pre></td><td class="code" id="p2311code85"><pre class="bash" style="font-family:monospace;">mkcd Project<span style="color: #000000; font-weight: bold;">/</span>a<span style="color: #000000; font-weight: bold;">/</span>src</pre></td></tr></table></div>

<p>　　此外，如果我们想创建多层次、多维度的目录树，mkcd也显得比较苍白了。例如我们想要建立目录Project，其中含有4个文件夹a, b, c, d，且这4个文件都含有一个src文件夹。或许，我们可以逐个创建，但我更倾向于使用单个命令来搞定，而mkdir       的-p选项和shell的参数扩展允许我这么做，例如下面的一个命令就可以完成任务。</p>

<div class="wp_codebox"><table><tr id="p231186"><td class="line_numbers"><pre>1
</pre></td><td class="code" id="p2311code86"><pre class="bash" style="font-family:monospace;"><span style="color: #c20cb9; font-weight: bold;">mkdir</span> <span style="color: #660033;">-p</span> Project<span style="color: #000000; font-weight: bold;">/</span><span style="color: #7a0874; font-weight: bold;">&#123;</span>a,b,c,d<span style="color: #7a0874; font-weight: bold;">&#125;</span><span style="color: #000000; font-weight: bold;">/</span>src</pre></td></tr></table></div>

<p>　　嗯，mkdir -p到此over~</p>
]]></content:encoded>
			<wfw:commentRss>http://www.dutor.net/index.php/2010/06/cmd-mkdir-p/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>[命令技巧]mkcd</title>
		<link>http://www.dutor.net/index.php/2010/05/cmd-mkcd/</link>
		<comments>http://www.dutor.net/index.php/2010/05/cmd-mkcd/#comments</comments>
		<pubDate>Sun, 30 May 2010 12:06:28 +0000</pubDate>
		<dc:creator>dutor</dc:creator>
				<category><![CDATA[Unix/Linux]]></category>
		<category><![CDATA[shell]]></category>
		<category><![CDATA[命令]]></category>

		<guid isPermaLink="false">http://www.dutor.net/?p=2304</guid>
		<description><![CDATA[　　介绍一个新命令，保准你从未听说过，但它实现的操作你应该一直都在使用，这个命令就是mkcd。其实它不是一个命令，而是一个shell函数：
<pre lang="bash" line="1">
# mkcd: mkdir, then cd
mkcd()
{
    if [ $# = "1" ]
    then
        mkdir -p "$1"
        cd "$1"
    else
        echo "Usage: mkcd folder"
    fi
}
</pre>
　　很简单，相信你一看就知道它能做什么了。]]></description>
			<content:encoded><![CDATA[<p>　　介绍一个新命令，保准你从未听说过，但它实现的操作你应该一直都在使用，这个命令就是mkcd。其实它不是一个命令，而是一个shell函数：</p>

<div class="wp_codebox"><table><tr id="p230487"><td class="line_numbers"><pre>1
2
3
4
5
6
7
8
9
10
11
</pre></td><td class="code" id="p2304code87"><pre class="bash" style="font-family:monospace;"><span style="color: #666666; font-style: italic;"># mkcd: mkdir, then cd</span>
mkcd<span style="color: #7a0874; font-weight: bold;">&#40;</span><span style="color: #7a0874; font-weight: bold;">&#41;</span>
<span style="color: #7a0874; font-weight: bold;">&#123;</span>
    <span style="color: #000000; font-weight: bold;">if</span> <span style="color: #7a0874; font-weight: bold;">&#91;</span> <span style="color: #007800;">$#</span> = <span style="color: #ff0000;">&quot;1&quot;</span> <span style="color: #7a0874; font-weight: bold;">&#93;</span>
    <span style="color: #000000; font-weight: bold;">then</span>
        <span style="color: #c20cb9; font-weight: bold;">mkdir</span> <span style="color: #660033;">-p</span> <span style="color: #ff0000;">&quot;$1&quot;</span>
        <span style="color: #7a0874; font-weight: bold;">cd</span> <span style="color: #ff0000;">&quot;$1&quot;</span>
    <span style="color: #000000; font-weight: bold;">else</span>
        <span style="color: #7a0874; font-weight: bold;">echo</span> <span style="color: #ff0000;">&quot;Usage: mkcd folder&quot;</span>
    <span style="color: #000000; font-weight: bold;">fi</span>
<span style="color: #7a0874; font-weight: bold;">&#125;</span></pre></td></tr></table></div>

<p>　　很简单，相信你一看就知道它能做什么了。<br />
　　你需要做的就是把这个函数丢进你的.bashrc，然后</p>

<div class="wp_codebox"><table><tr id="p230488"><td class="line_numbers"><pre>1
</pre></td><td class="code" id="p2304code88"><pre class="bash" style="font-family:monospace;"><span style="color: #7a0874; font-weight: bold;">source</span> ~<span style="color: #000000; font-weight: bold;">/</span>.bashrc <span style="color: #666666; font-style: italic;"># 重新加载，使.bashrc立即生效</span></pre></td></tr></table></div>

]]></content:encoded>
			<wfw:commentRss>http://www.dutor.net/index.php/2010/05/cmd-mkcd/feed/</wfw:commentRss>
		<slash:comments>6</slash:comments>
		</item>
		<item>
		<title>sed单行命令快速参考</title>
		<link>http://www.dutor.net/index.php/2010/05/sed-samples/</link>
		<comments>http://www.dutor.net/index.php/2010/05/sed-samples/#comments</comments>
		<pubDate>Fri, 14 May 2010 14:14:03 +0000</pubDate>
		<dc:creator>dutor</dc:creator>
				<category><![CDATA[Unix/Linux]]></category>
		<category><![CDATA[命令]]></category>

		<guid isPermaLink="false">http://www.dutor.net/?p=2274</guid>
		<description><![CDATA[<h4>简述</h4>
　　sed是Linux环境下的一个文本流、行编辑器，十分强大，这里贴一些常用的单行脚本，脚本最初<a href="http://sed.sourceforge.net/sed1line_zh-CN.html" target="_blank">来源于此</a>，基本未做改动。另外一个强大的文本处理工具就是awk，对于这两个工具，个人觉得，根据个人选择其一就够用了，我自己就喜欢sed多一点。Bones在<a href="http://li2z.cn/2009/12/07/sed_awk/" target="_blank">这里</a>用awk对下面的各个sed命令行做了相应的替代。
　　推荐一本关于sed和awk的书《sed &#038; awk》，作者Dale Dougberty, Arnold Robbins。中文版在网上已经买不到了，china-pub倒是有，不过是原版的一般人承受不起那个价位。幸好这本书的作者提供免费的电子版，在网上应该可以搜的到。
<h4>sed单行命令快速参考</h4>
<h5>文本间隔</h5>
<pre lang="bash" line="1">
# 在每一行后面增加一空行
 sed G
 
 # 将原来的所有空行删除并在每一行后面增加一空行。
 # 这样在输出的文本中每一行后面将有且只有一空行。
 sed '/^$/d;G'
 
 # 在每一行后面增加两行空行
 sed 'G;G'
 
 # 将第一个脚本所产生的所有空行删除（即删除所有偶数行）
 sed 'n;d'
 
 # 在匹配式样“regex”的行之前插入一空行
 sed '/regex/{x;p;x;}'
 
 # 在匹配式样“regex”的行之后插入一空行
 sed '/regex/G'
 
 # 在匹配式样“regex”的行之前和之后各插入一空行
 sed '/regex/{x;p;x;G;}'
</pre>]]></description>
			<content:encoded><![CDATA[<h4>简述</h4>
<p>　　sed是Linux环境下的一个文本流、行编辑器，十分强大，这里贴一些常用的单行脚本，脚本最初<a href="http://sed.sourceforge.net/sed1line_zh-CN.html" target="_blank">来源于此</a>，基本未做改动。另外一个强大的文本处理工具就是awk，对于这两个工具，个人觉得，根据个人选择其一就够用了，我自己就喜欢sed多一点。Bones在<a href="http://li2z.cn/2009/12/07/sed_awk/" target="_blank">这里</a>用awk对下面的各个sed命令行做了相应的替代。<br />
　　推荐一本关于sed和awk的书《sed &#038; awk》，作者Dale Dougberty, Arnold Robbins。中文版在网上已经买不到了，china-pub倒是有，不过是原版的一般人承受不起那个价位。幸好这本书的作者提供免费的电子版，在网上应该可以搜的到。</p>
<h4>sed单行命令快速参考</h4>
<h5>文本间隔</h5>

<div class="wp_codebox"><table><tr id="p227489"><td class="line_numbers"><pre>1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
</pre></td><td class="code" id="p2274code89"><pre class="bash" style="font-family:monospace;"><span style="color: #666666; font-style: italic;"># 在每一行后面增加一空行</span>
 <span style="color: #c20cb9; font-weight: bold;">sed</span> G
&nbsp;
 <span style="color: #666666; font-style: italic;"># 将原来的所有空行删除并在每一行后面增加一空行。</span>
 <span style="color: #666666; font-style: italic;"># 这样在输出的文本中每一行后面将有且只有一空行。</span>
 <span style="color: #c20cb9; font-weight: bold;">sed</span> <span style="color: #ff0000;">'/^$/d;G'</span>
&nbsp;
 <span style="color: #666666; font-style: italic;"># 在每一行后面增加两行空行</span>
 <span style="color: #c20cb9; font-weight: bold;">sed</span> <span style="color: #ff0000;">'G;G'</span>
&nbsp;
 <span style="color: #666666; font-style: italic;"># 将第一个脚本所产生的所有空行删除（即删除所有偶数行）</span>
 <span style="color: #c20cb9; font-weight: bold;">sed</span> <span style="color: #ff0000;">'n;d'</span>
&nbsp;
 <span style="color: #666666; font-style: italic;"># 在匹配式样“regex”的行之前插入一空行</span>
 <span style="color: #c20cb9; font-weight: bold;">sed</span> <span style="color: #ff0000;">'/regex/{x;p;x;}'</span>
&nbsp;
 <span style="color: #666666; font-style: italic;"># 在匹配式样“regex”的行之后插入一空行</span>
 <span style="color: #c20cb9; font-weight: bold;">sed</span> <span style="color: #ff0000;">'/regex/G'</span>
&nbsp;
 <span style="color: #666666; font-style: italic;"># 在匹配式样“regex”的行之前和之后各插入一空行</span>
 <span style="color: #c20cb9; font-weight: bold;">sed</span> <span style="color: #ff0000;">'/regex/{x;p;x;G;}'</span></pre></td></tr></table></div>

<h5>编号</h5>

<div class="wp_codebox"><table><tr id="p227490"><td class="line_numbers"><pre>1
2
3
4
5
6
7
8
9
10
11
12
</pre></td><td class="code" id="p2274code90"><pre class="bash" style="font-family:monospace;"><span style="color: #666666; font-style: italic;"># 为文件中的每一行进行编号（简单的左对齐方式）。这里使用了“制表符”</span>
 <span style="color: #666666; font-style: italic;"># （tab，见本文末尾关于'\t'的用法的描述）而不是空格来对齐边缘。</span>
 <span style="color: #c20cb9; font-weight: bold;">sed</span> = filename <span style="color: #000000; font-weight: bold;">|</span> <span style="color: #c20cb9; font-weight: bold;">sed</span> <span style="color: #ff0000;">'N;s/\n/\t/'</span>
&nbsp;
 <span style="color: #666666; font-style: italic;"># 对文件中的所有行编号（行号在左，文字右端对齐）。</span>
 <span style="color: #c20cb9; font-weight: bold;">sed</span> = filename <span style="color: #000000; font-weight: bold;">|</span> <span style="color: #c20cb9; font-weight: bold;">sed</span> <span style="color: #ff0000;">'N; s/^/     /; s/ *\(.\{6,\}\)\n/\1  /'</span>
&nbsp;
 <span style="color: #666666; font-style: italic;"># 对文件中的所有行编号，但只显示非空白行的行号。</span>
 <span style="color: #c20cb9; font-weight: bold;">sed</span> <span style="color: #ff0000;">'/./='</span> filename <span style="color: #000000; font-weight: bold;">|</span> <span style="color: #c20cb9; font-weight: bold;">sed</span> <span style="color: #ff0000;">'/./N; s/\n/ /'</span>
&nbsp;
 <span style="color: #666666; font-style: italic;"># 计算行数 （模拟 &quot;wc -l&quot;）</span>
 <span style="color: #c20cb9; font-weight: bold;">sed</span> <span style="color: #660033;">-n</span> <span style="color: #ff0000;">'$='</span></pre></td></tr></table></div>

<h5>文本转换和替代(这是我最常用到的功能了)</h5>

<div class="wp_codebox"><table><tr id="p227491"><td class="line_numbers"><pre>1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
</pre></td><td class="code" id="p2274code91"><pre class="bash" style="font-family:monospace;"><span style="color: #666666; font-style: italic;"># Unix环境：转换DOS的新行符（CR/LF）为Unix格式。</span>
 <span style="color: #c20cb9; font-weight: bold;">sed</span> <span style="color: #ff0000;">'s/.$//'</span>                     <span style="color: #666666; font-style: italic;"># 假设所有行以CR/LF结束</span>
 <span style="color: #c20cb9; font-weight: bold;">sed</span> <span style="color: #ff0000;">'s/^M$//'</span>                    <span style="color: #666666; font-style: italic;"># 在bash/tcsh中，将按Ctrl-M改为按Ctrl-V</span>
 <span style="color: #c20cb9; font-weight: bold;">sed</span> <span style="color: #ff0000;">'s/\x0D$//'</span>                  <span style="color: #666666; font-style: italic;"># ssed、gsed 3.02.80，及更高版本</span>
&nbsp;
 <span style="color: #666666; font-style: italic;"># Unix环境：转换Unix的新行符（LF）为DOS格式。</span>
 <span style="color: #c20cb9; font-weight: bold;">sed</span> <span style="color: #ff0000;">&quot;s/$/<span style="color: #780078;">`echo -e \\\r`</span>/&quot;</span>        <span style="color: #666666; font-style: italic;"># 在ksh下所使用的命令</span>
 <span style="color: #c20cb9; font-weight: bold;">sed</span> <span style="color: #ff0000;">'s/$'</span><span style="color: #ff0000;">&quot;/<span style="color: #780078;">`echo \\\r`</span>/&quot;</span>         <span style="color: #666666; font-style: italic;"># 在bash下所使用的命令</span>
 <span style="color: #c20cb9; font-weight: bold;">sed</span> <span style="color: #ff0000;">&quot;s/$/<span style="color: #780078;">`echo \\\r`</span>/&quot;</span>           <span style="color: #666666; font-style: italic;"># 在zsh下所使用的命令</span>
 <span style="color: #c20cb9; font-weight: bold;">sed</span> <span style="color: #ff0000;">'s/$/\r/'</span>                    <span style="color: #666666; font-style: italic;"># gsed 3.02.80 及更高版本</span>
&nbsp;
 <span style="color: #666666; font-style: italic;"># DOS环境：转换Unix新行符（LF）为DOS格式。</span>
 <span style="color: #c20cb9; font-weight: bold;">sed</span> <span style="color: #ff0000;">&quot;s/$//&quot;</span>                      <span style="color: #666666; font-style: italic;"># 方法 1</span>
 <span style="color: #c20cb9; font-weight: bold;">sed</span> <span style="color: #660033;">-n</span> p                         <span style="color: #666666; font-style: italic;"># 方法 2</span>
&nbsp;
 <span style="color: #666666; font-style: italic;"># DOS环境：转换DOS新行符（CR/LF）为Unix格式。</span>
 <span style="color: #666666; font-style: italic;"># 下面的脚本只对UnxUtils sed 4.0.7 及更高版本有效。要识别UnxUtils版本的</span>
 <span style="color: #666666; font-style: italic;">#  sed可以通过其特有的“--text”选项。你可以使用帮助选项（“--help”）看</span>
 <span style="color: #666666; font-style: italic;"># 其中有无一个“--text”项以此来判断所使用的是否是UnxUtils版本。其它DOS</span>
 <span style="color: #666666; font-style: italic;"># 版本的的sed则无法进行这一转换。但可以用“tr”来实现这一转换。</span>
 <span style="color: #c20cb9; font-weight: bold;">sed</span> <span style="color: #ff0000;">&quot;s/<span style="color: #000099; font-weight: bold;">\r</span>//&quot;</span> infile <span style="color: #000000; font-weight: bold;">&gt;</span>outfile     <span style="color: #666666; font-style: italic;"># UnxUtils sed v4.0.7 或更高版本</span>
 <span style="color: #c20cb9; font-weight: bold;">tr</span> <span style="color: #660033;">-d</span> \r <span style="color: #000000; font-weight: bold;">&lt;</span>infile <span style="color: #000000; font-weight: bold;">&gt;</span>outfile        <span style="color: #666666; font-style: italic;"># GNU tr 1.22 或更高版本</span>
&nbsp;
 <span style="color: #666666; font-style: italic;"># 将每一行前导的“空白字符”（空格，制表符）删除</span>
 <span style="color: #666666; font-style: italic;"># 使之左对齐</span>
 <span style="color: #c20cb9; font-weight: bold;">sed</span> <span style="color: #ff0000;">'s/^[ \t]*//'</span>                <span style="color: #666666; font-style: italic;"># 见本文末尾关于'\t'用法的描述</span>
&nbsp;
 <span style="color: #666666; font-style: italic;"># 将每一行拖尾的“空白字符”（空格，制表符）删除</span>
 <span style="color: #c20cb9; font-weight: bold;">sed</span> <span style="color: #ff0000;">'s/[ \t]*$//'</span>                <span style="color: #666666; font-style: italic;"># 见本文末尾关于'\t'用法的描述</span>
&nbsp;
 <span style="color: #666666; font-style: italic;"># 将每一行中的前导和拖尾的空白字符删除</span>
 <span style="color: #c20cb9; font-weight: bold;">sed</span> <span style="color: #ff0000;">'s/^[ \t]*//;s/[ \t]*$//'</span>
&nbsp;
 <span style="color: #666666; font-style: italic;"># 在每一行开头处插入5个空格（使全文向右移动5个字符的位置）</span>
 <span style="color: #c20cb9; font-weight: bold;">sed</span> <span style="color: #ff0000;">'s/^/     /'</span>
&nbsp;
 <span style="color: #666666; font-style: italic;"># 以79个字符为宽度，将所有文本右对齐</span>
 <span style="color: #c20cb9; font-weight: bold;">sed</span> <span style="color: #660033;">-e</span> :a <span style="color: #660033;">-e</span> <span style="color: #ff0000;">'s/^.\{1,78\}$/ &amp;/;ta'</span>  <span style="color: #666666; font-style: italic;"># 78个字符外加最后的一个空格</span>
&nbsp;
 <span style="color: #666666; font-style: italic;"># 以79个字符为宽度，使所有文本居中。在方法1中，为了让文本居中每一行的前</span>
 <span style="color: #666666; font-style: italic;"># 头和后头都填充了空格。 在方法2中，在居中文本的过程中只在文本的前面填充</span>
 <span style="color: #666666; font-style: italic;"># 空格，并且最终这些空格将有一半会被删除。此外每一行的后头并未填充空格。</span>
 <span style="color: #c20cb9; font-weight: bold;">sed</span>  <span style="color: #660033;">-e</span> :a <span style="color: #660033;">-e</span> <span style="color: #ff0000;">'s/^.\{1,77\}$/ &amp; /;ta'</span>                     <span style="color: #666666; font-style: italic;"># 方法1</span>
 <span style="color: #c20cb9; font-weight: bold;">sed</span>  <span style="color: #660033;">-e</span> :a <span style="color: #660033;">-e</span> <span style="color: #ff0000;">'s/^.\{1,77\}$/ &amp;/;ta'</span> <span style="color: #660033;">-e</span> <span style="color: #ff0000;">'s/\( *\)\1/\1/'</span>  <span style="color: #666666; font-style: italic;"># 方法2</span>
&nbsp;
 <span style="color: #666666; font-style: italic;"># 在每一行中查找字串“foo”，并将找到的“foo”替换为“bar”</span>
 <span style="color: #c20cb9; font-weight: bold;">sed</span> <span style="color: #ff0000;">'s/foo/bar/'</span>                 <span style="color: #666666; font-style: italic;"># 只替换每一行中的第一个“foo”字串</span>
 <span style="color: #c20cb9; font-weight: bold;">sed</span> <span style="color: #ff0000;">'s/foo/bar/4'</span>                <span style="color: #666666; font-style: italic;"># 只替换每一行中的第四个“foo”字串</span>
 <span style="color: #c20cb9; font-weight: bold;">sed</span> <span style="color: #ff0000;">'s/foo/bar/g'</span>                <span style="color: #666666; font-style: italic;"># 将每一行中的所有“foo”都换成“bar”</span>
 <span style="color: #c20cb9; font-weight: bold;">sed</span> <span style="color: #ff0000;">'s/\(.*\)foo\(.*foo\)/\1bar\2/'</span> <span style="color: #666666; font-style: italic;"># 替换倒数第二个“foo”</span>
 <span style="color: #c20cb9; font-weight: bold;">sed</span> <span style="color: #ff0000;">'s/\(.*\)foo/\1bar/'</span>            <span style="color: #666666; font-style: italic;"># 替换最后一个“foo”</span>
&nbsp;
 <span style="color: #666666; font-style: italic;"># 只在行中出现字串“baz”的情况下将“foo”替换成“bar”</span>
 <span style="color: #c20cb9; font-weight: bold;">sed</span> <span style="color: #ff0000;">'/baz/s/foo/bar/g'</span>
&nbsp;
 <span style="color: #666666; font-style: italic;"># 将“foo”替换成“bar”，并且只在行中未出现字串“baz”的情况下替换</span>
 <span style="color: #c20cb9; font-weight: bold;">sed</span> <span style="color: #ff0000;">'/baz/!s/foo/bar/g'</span>
&nbsp;
 <span style="color: #666666; font-style: italic;"># 不管是“scarlet”“ruby”还是“puce”，一律换成“red”</span>
 <span style="color: #c20cb9; font-weight: bold;">sed</span> <span style="color: #ff0000;">'s/scarlet/red/g;s/ruby/red/g;s/puce/red/g'</span>  <span style="color: #666666; font-style: italic;">#对多数的sed都有效</span>
 gsed <span style="color: #ff0000;">'s/scarlet\|ruby\|puce/red/g'</span>               <span style="color: #666666; font-style: italic;"># 只对GNU sed有效</span>
&nbsp;
 <span style="color: #666666; font-style: italic;"># 倒置所有行，第一行成为最后一行，依次类推（模拟“tac”）。</span>
 <span style="color: #666666; font-style: italic;"># 由于某些原因，使用下面命令时HHsed v1.5会将文件中的空行删除</span>
 <span style="color: #c20cb9; font-weight: bold;">sed</span> <span style="color: #ff0000;">'1!G;h;$!d'</span>               <span style="color: #666666; font-style: italic;"># 方法1</span>
 <span style="color: #c20cb9; font-weight: bold;">sed</span> <span style="color: #660033;">-n</span> <span style="color: #ff0000;">'1!G;h;$p'</span>             <span style="color: #666666; font-style: italic;"># 方法2</span>
&nbsp;
 <span style="color: #666666; font-style: italic;"># 将行中的字符逆序排列，第一个字成为最后一字，……（模拟“rev”）</span>
 <span style="color: #c20cb9; font-weight: bold;">sed</span> <span style="color: #ff0000;">'/\n/!G;s/\(.\)\(.*\n\)/&amp;\2\1/;//D;s/.//'</span>
&nbsp;
 <span style="color: #666666; font-style: italic;"># 将每两行连接成一行（类似“paste”）</span>
 <span style="color: #c20cb9; font-weight: bold;">sed</span> <span style="color: #ff0000;">'$!N;s/\n/ /'</span>
&nbsp;
 <span style="color: #666666; font-style: italic;"># 如果当前行以反斜杠“\”结束，则将下一行并到当前行末尾</span>
 <span style="color: #666666; font-style: italic;"># 并去掉原来行尾的反斜杠</span>
 <span style="color: #c20cb9; font-weight: bold;">sed</span> <span style="color: #660033;">-e</span> :a <span style="color: #660033;">-e</span> <span style="color: #ff0000;">'/\\$/N; s/\\\n//; ta'</span>
&nbsp;
 <span style="color: #666666; font-style: italic;"># 如果当前行以等号开头，将当前行并到上一行末尾</span>
 <span style="color: #666666; font-style: italic;"># 并以单个空格代替原来行头的“=”</span>
 <span style="color: #c20cb9; font-weight: bold;">sed</span> <span style="color: #660033;">-e</span> :a <span style="color: #660033;">-e</span> <span style="color: #ff0000;">'$!N;s/\n=/ /;ta'</span> <span style="color: #660033;">-e</span> <span style="color: #ff0000;">'P;D'</span>
&nbsp;
 <span style="color: #666666; font-style: italic;"># 为数字字串增加逗号分隔符号，将“1234567”改为“1,234,567”</span>
 gsed <span style="color: #ff0000;">':a;s/\B[0-9]\{3\}\&gt;/,&amp;/;ta'</span>                     <span style="color: #666666; font-style: italic;"># GNU sed</span>
 <span style="color: #c20cb9; font-weight: bold;">sed</span> <span style="color: #660033;">-e</span> :a <span style="color: #660033;">-e</span> <span style="color: #ff0000;">'s/\(.*[0-9]\)\([0-9]\{3\}\)/\1,\2/;ta'</span>  <span style="color: #666666; font-style: italic;"># 其他sed</span>
&nbsp;
 <span style="color: #666666; font-style: italic;"># 为带有小数点和负号的数值增加逗号分隔符（GNU sed）</span>
 gsed <span style="color: #660033;">-r</span> <span style="color: #ff0000;">':a;s/(^|[^0-9.])([0-9]+)([0-9]{3})/\1\2,\3/g;ta'</span>
&nbsp;
 <span style="color: #666666; font-style: italic;"># 在每5行后增加一空白行 （在第5，10，15，20，等行后增加一空白行）</span>
 gsed <span style="color: #ff0000;">'0~5G'</span>                      <span style="color: #666666; font-style: italic;"># 只对GNU sed有效</span>
 <span style="color: #c20cb9; font-weight: bold;">sed</span> <span style="color: #ff0000;">'n;n;n;n;G;'</span></pre></td></tr></table></div>

<h5>选择性地显示特定行</h5>

<div class="wp_codebox"><table><tr id="p227492"><td class="line_numbers"><pre>1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
</pre></td><td class="code" id="p2274code92"><pre class="bash" style="font-family:monospace;"><span style="color: #666666; font-style: italic;"># 显示文件中的前10行 （模拟“head”的行为）</span>
 <span style="color: #c20cb9; font-weight: bold;">sed</span> 10q
&nbsp;
 <span style="color: #666666; font-style: italic;"># 显示文件中的第一行 （模拟“head -1”命令）</span>
 <span style="color: #c20cb9; font-weight: bold;">sed</span> q
&nbsp;
 <span style="color: #666666; font-style: italic;"># 显示文件中的最后10行 （模拟“tail”）</span>
 <span style="color: #c20cb9; font-weight: bold;">sed</span> <span style="color: #660033;">-e</span> :a <span style="color: #660033;">-e</span> <span style="color: #ff0000;">'$q;N;11,$D;ba'</span>
&nbsp;
 <span style="color: #666666; font-style: italic;"># 显示文件中的最后2行（模拟“tail -2”命令）</span>
 <span style="color: #c20cb9; font-weight: bold;">sed</span> <span style="color: #ff0000;">'$!N;$!D'</span>
&nbsp;
 <span style="color: #666666; font-style: italic;"># 显示文件中的最后一行（模拟“tail -1”）</span>
 <span style="color: #c20cb9; font-weight: bold;">sed</span> <span style="color: #ff0000;">'$!d'</span>                        <span style="color: #666666; font-style: italic;"># 方法1</span>
 <span style="color: #c20cb9; font-weight: bold;">sed</span> <span style="color: #660033;">-n</span> <span style="color: #ff0000;">'$p'</span>                      <span style="color: #666666; font-style: italic;"># 方法2</span>
&nbsp;
 <span style="color: #666666; font-style: italic;"># 显示文件中的倒数第二行</span>
 <span style="color: #c20cb9; font-weight: bold;">sed</span> <span style="color: #660033;">-e</span> <span style="color: #ff0000;">'$!{h;d;}'</span> <span style="color: #660033;">-e</span> x              <span style="color: #666666; font-style: italic;"># 当文件中只有一行时，输入空行</span>
 <span style="color: #c20cb9; font-weight: bold;">sed</span> <span style="color: #660033;">-e</span> <span style="color: #ff0000;">'1{$q;}'</span> <span style="color: #660033;">-e</span> <span style="color: #ff0000;">'$!{h;d;}'</span> <span style="color: #660033;">-e</span> x  <span style="color: #666666; font-style: italic;"># 当文件中只有一行时，显示该行</span>
 <span style="color: #c20cb9; font-weight: bold;">sed</span> <span style="color: #660033;">-e</span> <span style="color: #ff0000;">'1{$d;}'</span> <span style="color: #660033;">-e</span> <span style="color: #ff0000;">'$!{h;d;}'</span> <span style="color: #660033;">-e</span> x  <span style="color: #666666; font-style: italic;"># 当文件中只有一行时，不输出</span>
&nbsp;
 <span style="color: #666666; font-style: italic;"># 只显示匹配正则表达式的行（模拟“grep”）</span>
 <span style="color: #c20cb9; font-weight: bold;">sed</span> <span style="color: #660033;">-n</span> <span style="color: #ff0000;">'/regexp/p'</span>               <span style="color: #666666; font-style: italic;"># 方法1</span>
 <span style="color: #c20cb9; font-weight: bold;">sed</span> <span style="color: #ff0000;">'/regexp/!d'</span>                 <span style="color: #666666; font-style: italic;"># 方法2</span>
&nbsp;
 <span style="color: #666666; font-style: italic;"># 只显示“不”匹配正则表达式的行（模拟“grep -v”）</span>
 <span style="color: #c20cb9; font-weight: bold;">sed</span> <span style="color: #660033;">-n</span> <span style="color: #ff0000;">'/regexp/!p'</span>              <span style="color: #666666; font-style: italic;"># 方法1，与前面的命令相对应</span>
 <span style="color: #c20cb9; font-weight: bold;">sed</span> <span style="color: #ff0000;">'/regexp/d'</span>                  <span style="color: #666666; font-style: italic;"># 方法2，类似的语法</span>
&nbsp;
 <span style="color: #666666; font-style: italic;"># 查找“regexp”并将匹配行的上一行显示出来，但并不显示匹配行</span>
 <span style="color: #c20cb9; font-weight: bold;">sed</span> <span style="color: #660033;">-n</span> <span style="color: #ff0000;">'/regexp/{g;1!p;};h'</span>
&nbsp;
 <span style="color: #666666; font-style: italic;"># 查找“regexp”并将匹配行的下一行显示出来，但并不显示匹配行</span>
 <span style="color: #c20cb9; font-weight: bold;">sed</span> <span style="color: #660033;">-n</span> <span style="color: #ff0000;">'/regexp/{n;p;}'</span>
&nbsp;
 <span style="color: #666666; font-style: italic;"># 显示包含“regexp”的行及其前后行，并在第一行之前加上“regexp”所</span>
 <span style="color: #666666; font-style: italic;"># 在行的行号 （类似“grep -A1 -B1”）</span>
 <span style="color: #c20cb9; font-weight: bold;">sed</span> <span style="color: #660033;">-n</span> <span style="color: #660033;">-e</span> <span style="color: #ff0000;">'/regexp/{=;x;1!p;g;$!N;p;D;}'</span> <span style="color: #660033;">-e</span> h
&nbsp;
 <span style="color: #666666; font-style: italic;"># 显示包含“AAA”、“BBB”或“CCC”的行（任意次序）</span>
 <span style="color: #c20cb9; font-weight: bold;">sed</span> <span style="color: #ff0000;">'/AAA/!d; /BBB/!d; /CCC/!d'</span>  <span style="color: #666666; font-style: italic;"># 字串的次序不影响结果</span>
&nbsp;
 <span style="color: #666666; font-style: italic;"># 显示包含“AAA”、“BBB”和“CCC”的行（固定次序）</span>
 <span style="color: #c20cb9; font-weight: bold;">sed</span> <span style="color: #ff0000;">'/AAA.*BBB.*CCC/!d'</span>
&nbsp;
 <span style="color: #666666; font-style: italic;"># 显示包含“AAA”“BBB”或“CCC”的行 （模拟“egrep”）</span>
 <span style="color: #c20cb9; font-weight: bold;">sed</span> <span style="color: #660033;">-e</span> <span style="color: #ff0000;">'/AAA/b'</span> <span style="color: #660033;">-e</span> <span style="color: #ff0000;">'/BBB/b'</span> <span style="color: #660033;">-e</span> <span style="color: #ff0000;">'/CCC/b'</span> <span style="color: #660033;">-e</span> d    <span style="color: #666666; font-style: italic;"># 多数sed</span>
 gsed <span style="color: #ff0000;">'/AAA\|BBB\|CCC/!d'</span>                        <span style="color: #666666; font-style: italic;"># 对GNU sed有效</span>
&nbsp;
 <span style="color: #666666; font-style: italic;"># 显示包含“AAA”的段落 （段落间以空行分隔）</span>
 <span style="color: #666666; font-style: italic;"># HHsed v1.5 必须在“x;”后加入“G;”，接下来的3个脚本都是这样</span>
 <span style="color: #c20cb9; font-weight: bold;">sed</span> <span style="color: #660033;">-e</span> <span style="color: #ff0000;">'/./{H;$!d;}'</span> <span style="color: #660033;">-e</span> <span style="color: #ff0000;">'x;/AAA/!d;'</span>
&nbsp;
 <span style="color: #666666; font-style: italic;"># 显示包含“AAA”“BBB”和“CCC”三个字串的段落 （任意次序）</span>
 <span style="color: #c20cb9; font-weight: bold;">sed</span> <span style="color: #660033;">-e</span> <span style="color: #ff0000;">'/./{H;$!d;}'</span> <span style="color: #660033;">-e</span> <span style="color: #ff0000;">'x;/AAA/!d;/BBB/!d;/CCC/!d'</span>
&nbsp;
 <span style="color: #666666; font-style: italic;"># 显示包含“AAA”、“BBB”、“CCC”三者中任一字串的段落 （任意次序）</span>
 <span style="color: #c20cb9; font-weight: bold;">sed</span> <span style="color: #660033;">-e</span> <span style="color: #ff0000;">'/./{H;$!d;}'</span> <span style="color: #660033;">-e</span> <span style="color: #ff0000;">'x;/AAA/b'</span> <span style="color: #660033;">-e</span> <span style="color: #ff0000;">'/BBB/b'</span> <span style="color: #660033;">-e</span> <span style="color: #ff0000;">'/CCC/b'</span> <span style="color: #660033;">-e</span> d
 gsed <span style="color: #ff0000;">'/./{H;$!d;};x;/AAA\|BBB\|CCC/b;d'</span>         <span style="color: #666666; font-style: italic;"># 只对GNU sed有效</span>
&nbsp;
 <span style="color: #666666; font-style: italic;"># 显示包含65个或以上字符的行</span>
 <span style="color: #c20cb9; font-weight: bold;">sed</span> <span style="color: #660033;">-n</span> <span style="color: #ff0000;">'/^.\{65\}/p'</span>
&nbsp;
 <span style="color: #666666; font-style: italic;"># 显示包含65个以下字符的行</span>
 <span style="color: #c20cb9; font-weight: bold;">sed</span> <span style="color: #660033;">-n</span> <span style="color: #ff0000;">'/^.\{65\}/!p'</span>            <span style="color: #666666; font-style: italic;"># 方法1，与上面的脚本相对应</span>
 <span style="color: #c20cb9; font-weight: bold;">sed</span> <span style="color: #ff0000;">'/^.\{65\}/d'</span>                <span style="color: #666666; font-style: italic;"># 方法2，更简便一点的方法</span>
&nbsp;
 <span style="color: #666666; font-style: italic;"># 显示部分文本——从包含正则表达式的行开始到最后一行结束</span>
 <span style="color: #c20cb9; font-weight: bold;">sed</span> <span style="color: #660033;">-n</span> <span style="color: #ff0000;">'/regexp/,$p'</span>
&nbsp;
 <span style="color: #666666; font-style: italic;"># 显示部分文本——指定行号范围（从第8至第12行，含8和12行）</span>
 <span style="color: #c20cb9; font-weight: bold;">sed</span> <span style="color: #660033;">-n</span> <span style="color: #ff0000;">'8,12p'</span>                   <span style="color: #666666; font-style: italic;"># 方法1</span>
 <span style="color: #c20cb9; font-weight: bold;">sed</span> <span style="color: #ff0000;">'8,12!d'</span>                     <span style="color: #666666; font-style: italic;"># 方法2</span>
&nbsp;
 <span style="color: #666666; font-style: italic;"># 显示第52行</span>
 <span style="color: #c20cb9; font-weight: bold;">sed</span> <span style="color: #660033;">-n</span> <span style="color: #ff0000;">'52p'</span>                     <span style="color: #666666; font-style: italic;"># 方法1</span>
 <span style="color: #c20cb9; font-weight: bold;">sed</span> <span style="color: #ff0000;">'52!d'</span>                       <span style="color: #666666; font-style: italic;"># 方法2</span>
 <span style="color: #c20cb9; font-weight: bold;">sed</span> <span style="color: #ff0000;">'52q;d'</span>                      <span style="color: #666666; font-style: italic;"># 方法3, 处理大文件时更有效率</span>
&nbsp;
 <span style="color: #666666; font-style: italic;"># 从第3行开始，每7行显示一次    </span>
 gsed <span style="color: #660033;">-n</span> <span style="color: #ff0000;">'3~7p'</span>                   <span style="color: #666666; font-style: italic;"># 只对GNU sed有效</span>
 <span style="color: #c20cb9; font-weight: bold;">sed</span> <span style="color: #660033;">-n</span> <span style="color: #ff0000;">'3,${p;n;n;n;n;n;n;}'</span>     <span style="color: #666666; font-style: italic;"># 其他sed</span>
&nbsp;
 <span style="color: #666666; font-style: italic;"># 显示两个正则表达式之间的文本（包含）</span>
 <span style="color: #c20cb9; font-weight: bold;">sed</span> <span style="color: #660033;">-n</span> <span style="color: #ff0000;">'/Iowa/,/Montana/p'</span>       <span style="color: #666666; font-style: italic;"># 区分大小写方式</span></pre></td></tr></table></div>

<h5>选择性地删除特定行</h5>

<div class="wp_codebox"><table><tr id="p227493"><td class="line_numbers"><pre>1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
</pre></td><td class="code" id="p2274code93"><pre class="bash" style="font-family:monospace;"><span style="color: #666666; font-style: italic;"># 显示通篇文档，除了两个正则表达式之间的内容</span>
 <span style="color: #c20cb9; font-weight: bold;">sed</span> <span style="color: #ff0000;">'/Iowa/,/Montana/d'</span>
&nbsp;
 <span style="color: #666666; font-style: italic;"># 删除文件中相邻的重复行（模拟“uniq”）</span>
 <span style="color: #666666; font-style: italic;"># 只保留重复行中的第一行，其他行删除</span>
 <span style="color: #c20cb9; font-weight: bold;">sed</span> <span style="color: #ff0000;">'$!N; /^\(.*\)\n\1$/!P; D'</span>
&nbsp;
 <span style="color: #666666; font-style: italic;"># 删除文件中的重复行，不管有无相邻。注意hold space所能支持的缓存</span>
 <span style="color: #666666; font-style: italic;"># 大小，或者使用GNU sed。</span>
 <span style="color: #c20cb9; font-weight: bold;">sed</span> <span style="color: #660033;">-n</span> <span style="color: #ff0000;">'G; s/\n/&amp;&amp;/; /^\([ -~]*\n\).*\n\1/d; s/\n//; h; P'</span>
&nbsp;
 <span style="color: #666666; font-style: italic;"># 删除除重复行外的所有行（模拟“uniq -d”）</span>
 <span style="color: #c20cb9; font-weight: bold;">sed</span> <span style="color: #ff0000;">'$!N; s/^\(.*\)\n\1$/\1/; t; D'</span>
&nbsp;
 <span style="color: #666666; font-style: italic;"># 删除文件中开头的10行</span>
 <span style="color: #c20cb9; font-weight: bold;">sed</span> <span style="color: #ff0000;">'1,10d'</span>
&nbsp;
 <span style="color: #666666; font-style: italic;"># 删除文件中的最后一行</span>
 <span style="color: #c20cb9; font-weight: bold;">sed</span> <span style="color: #ff0000;">'$d'</span>
&nbsp;
 <span style="color: #666666; font-style: italic;"># 删除文件中的最后两行</span>
 <span style="color: #c20cb9; font-weight: bold;">sed</span> <span style="color: #ff0000;">'N;$!P;$!D;$d'</span>
&nbsp;
 <span style="color: #666666; font-style: italic;"># 删除文件中的最后10行</span>
 <span style="color: #c20cb9; font-weight: bold;">sed</span> <span style="color: #660033;">-e</span> :a <span style="color: #660033;">-e</span> <span style="color: #ff0000;">'$d;N;2,10ba'</span> <span style="color: #660033;">-e</span> <span style="color: #ff0000;">'P;D'</span>   <span style="color: #666666; font-style: italic;"># 方法1</span>
 <span style="color: #c20cb9; font-weight: bold;">sed</span> <span style="color: #660033;">-n</span> <span style="color: #660033;">-e</span> :a <span style="color: #660033;">-e</span> <span style="color: #ff0000;">'1,10!{P;N;D;};N;ba'</span>  <span style="color: #666666; font-style: italic;"># 方法2</span>
&nbsp;
 <span style="color: #666666; font-style: italic;"># 删除8的倍数行</span>
 gsed <span style="color: #ff0000;">'0~8d'</span>                           <span style="color: #666666; font-style: italic;"># 只对GNU sed有效</span>
 <span style="color: #c20cb9; font-weight: bold;">sed</span> <span style="color: #ff0000;">'n;n;n;n;n;n;n;d;'</span>                <span style="color: #666666; font-style: italic;"># 其他sed</span>
&nbsp;
 <span style="color: #666666; font-style: italic;"># 删除匹配式样的行</span>
 <span style="color: #c20cb9; font-weight: bold;">sed</span> <span style="color: #ff0000;">'/pattern/d'</span>                      <span style="color: #666666; font-style: italic;"># 删除含pattern的行。当然pattern</span>
                                       <span style="color: #666666; font-style: italic;"># 可以换成任何有效的正则表达式</span>
&nbsp;
 <span style="color: #666666; font-style: italic;"># 删除文件中的所有空行（与“grep '.' ”效果相同）</span>
 <span style="color: #c20cb9; font-weight: bold;">sed</span> <span style="color: #ff0000;">'/^$/d'</span>                           <span style="color: #666666; font-style: italic;"># 方法1</span>
 <span style="color: #c20cb9; font-weight: bold;">sed</span> <span style="color: #ff0000;">'/./!d'</span>                           <span style="color: #666666; font-style: italic;"># 方法2</span>
&nbsp;
 <span style="color: #666666; font-style: italic;"># 只保留多个相邻空行的第一行。并且删除文件顶部和尾部的空行。</span>
 <span style="color: #666666; font-style: italic;"># （模拟“cat -s”）</span>
 <span style="color: #c20cb9; font-weight: bold;">sed</span> <span style="color: #ff0000;">'/./,/^$/!d'</span>        <span style="color: #666666; font-style: italic;">#方法1，删除文件顶部的空行，允许尾部保留一空行</span>
 <span style="color: #c20cb9; font-weight: bold;">sed</span> <span style="color: #ff0000;">'/^$/N;/\n$/D'</span>      <span style="color: #666666; font-style: italic;">#方法2，允许顶部保留一空行，尾部不留空行</span>
&nbsp;
 <span style="color: #666666; font-style: italic;"># 只保留多个相邻空行的前两行。</span>
 <span style="color: #c20cb9; font-weight: bold;">sed</span> <span style="color: #ff0000;">'/^$/N;/\n$/N;//D'</span>
&nbsp;
 <span style="color: #666666; font-style: italic;"># 删除文件顶部的所有空行</span>
 <span style="color: #c20cb9; font-weight: bold;">sed</span> <span style="color: #ff0000;">'/./,$!d'</span>
&nbsp;
 <span style="color: #666666; font-style: italic;"># 删除文件尾部的所有空行</span>
 <span style="color: #c20cb9; font-weight: bold;">sed</span> <span style="color: #660033;">-e</span> :a <span style="color: #660033;">-e</span> <span style="color: #ff0000;">'/^\n*$/{$d;N;ba'</span> <span style="color: #660033;">-e</span> <span style="color: #ff0000;">'}'</span>  <span style="color: #666666; font-style: italic;"># 对所有sed有效</span>
 <span style="color: #c20cb9; font-weight: bold;">sed</span> <span style="color: #660033;">-e</span> :a <span style="color: #660033;">-e</span> <span style="color: #ff0000;">'/^\n*$/N;/\n$/ba'</span>        <span style="color: #666666; font-style: italic;"># 同上，但只对 gsed 3.02.*有效</span>
&nbsp;
 <span style="color: #666666; font-style: italic;"># 删除每个段落的最后一行</span>
 <span style="color: #c20cb9; font-weight: bold;">sed</span> <span style="color: #660033;">-n</span> <span style="color: #ff0000;">'/^$/{p;h;};/./{x;/./p;}'</span></pre></td></tr></table></div>

<h5>其他特殊应用</h5>

<div class="wp_codebox"><table><tr id="p227494"><td class="line_numbers"><pre>1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
</pre></td><td class="code" id="p2274code94"><pre class="bash" style="font-family:monospace;"><span style="color: #666666; font-style: italic;"># 移除手册页（man page）中的nroff标记。在Unix System V或bash shell下使</span>
 <span style="color: #666666; font-style: italic;"># 用'echo'命令时可能需要加上 -e 选项。</span>
 <span style="color: #c20cb9; font-weight: bold;">sed</span> <span style="color: #ff0000;">&quot;s/.<span style="color: #780078;">`echo \\\b`</span>//g&quot;</span>    <span style="color: #666666; font-style: italic;"># 外层的双括号是必须的（Unix环境）</span>
 <span style="color: #c20cb9; font-weight: bold;">sed</span> <span style="color: #ff0000;">'s/.^H//g'</span>             <span style="color: #666666; font-style: italic;"># 在bash或tcsh中, 按 Ctrl-V 再按 Ctrl-H</span>
 <span style="color: #c20cb9; font-weight: bold;">sed</span> <span style="color: #ff0000;">'s/.\x08//g'</span>           <span style="color: #666666; font-style: italic;"># sed 1.5，GNU sed，ssed所使用的十六进制的表示方法</span>
&nbsp;
 <span style="color: #666666; font-style: italic;"># 提取新闻组或 e-mail 的邮件头</span>
 <span style="color: #c20cb9; font-weight: bold;">sed</span> <span style="color: #ff0000;">'/^$/q'</span>                <span style="color: #666666; font-style: italic;"># 删除第一行空行后的所有内容</span>
&nbsp;
 <span style="color: #666666; font-style: italic;"># 提取新闻组或 e-mail 的正文部分</span>
 <span style="color: #c20cb9; font-weight: bold;">sed</span> <span style="color: #ff0000;">'1,/^$/d'</span>              <span style="color: #666666; font-style: italic;"># 删除第一行空行之前的所有内容</span>
&nbsp;
 <span style="color: #666666; font-style: italic;"># 从邮件头提取“Subject”（标题栏字段），并移除开头的“Subject:”字样</span>
 <span style="color: #c20cb9; font-weight: bold;">sed</span> <span style="color: #ff0000;">'/^Subject: */!d; s///;q'</span>
&nbsp;
 <span style="color: #666666; font-style: italic;"># 从邮件头获得回复地址</span>
 <span style="color: #c20cb9; font-weight: bold;">sed</span> <span style="color: #ff0000;">'/^Reply-To:/q; /^From:/h; /./d;g;q'</span>
&nbsp;
 <span style="color: #666666; font-style: italic;"># 获取邮件地址。在上一个脚本所产生的那一行邮件头的基础上进一步的将非电邮</span>
 <span style="color: #666666; font-style: italic;"># 地址的部分剃除。（见上一脚本）</span>
 <span style="color: #c20cb9; font-weight: bold;">sed</span> <span style="color: #ff0000;">'s/ *(.*)//; s/&gt;.*//; s/.*[:&lt;] *//'</span>
&nbsp;
 <span style="color: #666666; font-style: italic;"># 在每一行开头加上一个尖括号和空格（引用信息）</span>
 <span style="color: #c20cb9; font-weight: bold;">sed</span> <span style="color: #ff0000;">'s/^/&gt; /'</span>
&nbsp;
 <span style="color: #666666; font-style: italic;"># 将每一行开头处的尖括号和空格删除（解除引用）</span>
 <span style="color: #c20cb9; font-weight: bold;">sed</span> <span style="color: #ff0000;">'s/^&gt; //'</span>
&nbsp;
 <span style="color: #666666; font-style: italic;"># 移除大部分的HTML标签（包括跨行标签）</span>
 <span style="color: #c20cb9; font-weight: bold;">sed</span> <span style="color: #660033;">-e</span> :a <span style="color: #660033;">-e</span> <span style="color: #ff0000;">'s/&lt;[^&gt;]*&gt;//g;/&lt;/N;//ba'</span>
&nbsp;
 <span style="color: #666666; font-style: italic;"># 将分成多卷的uuencode文件解码。移除文件头信息，只保留uuencode编码部分。</span>
 <span style="color: #666666; font-style: italic;"># 文件必须以特定顺序传给sed。下面第一种版本的脚本可以直接在命令行下输入；</span>
 <span style="color: #666666; font-style: italic;"># 第二种版本则可以放入一个带执行权限的shell脚本中。（由Rahul Dhesi的一</span>
 <span style="color: #666666; font-style: italic;"># 个脚本修改而来。）</span>
 <span style="color: #c20cb9; font-weight: bold;">sed</span> <span style="color: #ff0000;">'/^end/,/^begin/d'</span> file1 file2 ... fileX <span style="color: #000000; font-weight: bold;">|</span> uudecode   <span style="color: #666666; font-style: italic;"># vers. 1</span>
 <span style="color: #c20cb9; font-weight: bold;">sed</span> <span style="color: #ff0000;">'/^end/,/^begin/d'</span> <span style="color: #ff0000;">&quot;$@&quot;</span> <span style="color: #000000; font-weight: bold;">|</span> uudecode                    <span style="color: #666666; font-style: italic;"># vers. 2</span>
&nbsp;
 <span style="color: #666666; font-style: italic;"># 将文件中的段落以字母顺序排序。段落间以（一行或多行）空行分隔。GNU sed使用</span>
 <span style="color: #666666; font-style: italic;"># 字元“\v”来表示垂直制表符，这里用它来作为换行符的占位符——当然你也可以</span>
 <span style="color: #666666; font-style: italic;"># 用其他未在文件中使用的字符来代替它。</span>
 <span style="color: #c20cb9; font-weight: bold;">sed</span> <span style="color: #ff0000;">'/./{H;d;};x;s/\n/={NL}=/g'</span> <span style="color: #c20cb9; font-weight: bold;">file</span> <span style="color: #000000; font-weight: bold;">|</span> <span style="color: #c20cb9; font-weight: bold;">sort</span> <span style="color: #000000; font-weight: bold;">|</span> <span style="color: #c20cb9; font-weight: bold;">sed</span> <span style="color: #ff0000;">'1s/={NL}=//;s/={NL}=/\n/g'</span>
 gsed <span style="color: #ff0000;">'/./{H;d};x;y/\n/\v/'</span> <span style="color: #c20cb9; font-weight: bold;">file</span> <span style="color: #000000; font-weight: bold;">|</span> <span style="color: #c20cb9; font-weight: bold;">sort</span> <span style="color: #000000; font-weight: bold;">|</span> <span style="color: #c20cb9; font-weight: bold;">sed</span> <span style="color: #ff0000;">'1s/\v//;y/\v/\n/'</span>
&nbsp;
 <span style="color: #666666; font-style: italic;"># 分别压缩每个.TXT文件，压缩后删除原来的文件并将压缩后的.ZIP文件</span>
 <span style="color: #666666; font-style: italic;"># 命名为与原来相同的名字（只是扩展名不同）。（DOS环境：“dir /b”</span>
 <span style="color: #666666; font-style: italic;"># 显示不带路径的文件名）。</span>
 <span style="color: #7a0874; font-weight: bold;">echo</span> <span style="color: #000000; font-weight: bold;">@</span><span style="color: #7a0874; font-weight: bold;">echo</span> off <span style="color: #000000; font-weight: bold;">&gt;</span>zipup.bat
 <span style="color: #c20cb9; font-weight: bold;">dir</span> <span style="color: #000000; font-weight: bold;">/</span>b <span style="color: #000000; font-weight: bold;">*</span>.txt <span style="color: #000000; font-weight: bold;">|</span> <span style="color: #c20cb9; font-weight: bold;">sed</span> <span style="color: #ff0000;">&quot;s/^\(.*\)\.TXT/pkzip -mo \1 \1.TXT/&quot;</span> <span style="color: #000000; font-weight: bold;">&gt;&gt;</span>zipup.bat</pre></td></tr></table></div>

]]></content:encoded>
			<wfw:commentRss>http://www.dutor.net/index.php/2010/05/sed-samples/feed/</wfw:commentRss>
		<slash:comments>1</slash:comments>
		</item>
		<item>
		<title>[Shell]环境变量 &amp; 参数扩展 &amp; 模式匹配</title>
		<link>http://www.dutor.net/index.php/2010/05/shell-argument-extension/</link>
		<comments>http://www.dutor.net/index.php/2010/05/shell-argument-extension/#comments</comments>
		<pubDate>Tue, 11 May 2010 12:29:56 +0000</pubDate>
		<dc:creator>dutor</dc:creator>
				<category><![CDATA[Unix/Linux]]></category>
		<category><![CDATA[shell]]></category>

		<guid isPermaLink="false">http://www.dutor.net/?p=2272</guid>
		<description><![CDATA[　　俺学习和使用Shell过程中积累的一些东西，希望对某些看官有用。另，本人使用bash环境。
<h4>Shell预设环境变量</h4>
<table > 
	<tr > 
		<th >环境变量</th><th >说明</th> 
	</tr> 
	<tr > 
		<td >$HOME</td><td >当前用户主目录</td> 
	</tr> 
	<tr > 
		<td >$PATH</td><td >冒号分割的用来搜索命令的目录的几何</td> 
	</tr> 
	<tr > 
		<td >$PS1</td><td >命令提示符，例如[\u@\h/\W$]给出了user@host/folder $这样的提示符</td> 
	</tr> 
	<tr > 
		<td >$PS2</td><td >二级提示符，通常仅仅包含一个&#62;</td> 
	</tr> 
	<tr > 
		<td >$IFS</td><td >输入分割域，通常为空白符，即空格、制表符、回车</td> 
	</tr> 
	<tr > 
		<td > </td><td > </td> 
	</tr> 
	<tr > 
		<td >$0</td><td >shell脚本的文件名</td> 
	</tr> 
	<tr > 
		<td >$#</td><td >调用本脚本时提供的参数个数</td> 
	</tr> 
	<tr > 
		<td >$$</td><td >shell脚本的进程号</td> 
	</tr> 
	<tr > 
		<td > $! </td><td > 后台进程的进程号 </td> 
	</tr> 
	<tr > 
		<td > $? </td><td > 上一个进程的退出状态 </td> 
	</tr> 
	<tr > 
		<td >$1, $2, ……, $n</td><td >脚本的参数，n超过9时需要用${n}</td> 
	</tr> 
	<tr > 
		<td >$*</td><td >包含了所有的参数，各参数以$IFS分割</td> 
	</tr> 
	<tr > 
		<td >$@</td><td >类似$*，但当$IFS为空时，各参数不会<strong>粘</strong>到一块儿，”$*”和”$@“的扩展不同</td> 
	</tr> 
</table> ]]></description>
			<content:encoded><![CDATA[<p>　　俺学习和使用Shell过程中积累的一些东西，希望对某些看官有用。另，本人使用bash环境。</p>
<h4>Shell预设环境变量</h4>
<table >
<tr >
<th >环境变量</th>
<th >说明</th>
</tr>
<tr >
<td >$HOME</td>
<td >当前用户主目录</td>
</tr>
<tr >
<td >$PATH</td>
<td >冒号分割的用来搜索命令的目录的几何</td>
</tr>
<tr >
<td >$PS1</td>
<td >命令提示符，例如[\u@\h/\W$]给出了user@host/folder $这样的提示符</td>
</tr>
<tr >
<td >$PS2</td>
<td >二级提示符，通常仅仅包含一个&gt;</td>
</tr>
<tr >
<td >$IFS</td>
<td >输入分割域，通常为空白符，即空格、制表符、回车</td>
</tr>
<tr >
<td > </td>
<td > </td>
</tr>
<tr >
<td >$0</td>
<td >shell脚本的文件名</td>
</tr>
<tr >
<td >$#</td>
<td >调用本脚本时提供的参数个数</td>
</tr>
<tr >
<td >$$</td>
<td >shell脚本的进程号</td>
</tr>
<tr >
<td > $! </td>
<td > 后台进程的进程号 </td>
</tr>
<tr >
<td > $? </td>
<td > 上一个进程的退出状态 </td>
</tr>
<tr >
<td >$1, $2, ……, $n</td>
<td >脚本的参数，n超过9时需要用${n}</td>
</tr>
<tr >
<td >$*</td>
<td >包含了所有的参数，各参数以$IFS分割</td>
</tr>
<tr >
<td >$@</td>
<td >类似$*，但当$IFS为空时，各参数不会<strong>粘</strong>到一块儿，”$*”和”$@“的扩展不同</td>
</tr>
</table>
<h4>参数扩展与模式匹配</h4>
<table >
<tr >
<th >  参数形式  </th>
<th >  扩展后  </th>
</tr>
<tr >
<td > x{y,z}  </td>
<td >xy xz  </td>
</tr>
<tr >
<td > ${x}{y, z}  </td>
<td > ${x}y ${x}z  </td>
</tr>
<tr >
<td > ${x}{y, $z}  </td>
<td > ${x}y ${x}${z}  </td>
</tr>
<tr >
<td > ${param#pattern} </td>
<td > 从param前面最小删除pattern的匹配 </td>
</tr>
<tr >
<td > ${param##pattern} </td>
<td > 从param前面最大删除pattern的匹配 </td>
</tr>
<tr >
<td > ${param%pattern} </td>
<td > 从param后面最小删除pattern的匹配 </td>
</tr>
<tr >
<td > ${param%%pattern} </td>
<td > 从param后面最大删除pattern的匹配 </td>
</tr>
<tr >
<td > ${param/pattern/string} </td>
<td > 从param中用string替换pattern的第一次匹配，string可为空 </td>
</tr>
<tr >
<td > ${param//pattern/string} </td>
<td > 从param中用string替换pattern的所有匹配，string可为空 </td>
</tr>
<tr >
<td > ${param:3:2} </td>
<td > 截取$param中索引3开始的2个字符 </td>
</tr>
<tr >
<td > ${param:3} </td>
<td > 截取$param中索引3至末尾的字符 </td>
</tr>
<tr >
<td > ${@:3:2} </td>
<td > 截取参数列表$@中第3个开始的2个参数 </td>
</tr>
<tr >
<td > ${param:-word} </td>
<td > 若$param为空或为设置，则参数式返回word，$param不变 </td>
</tr>
<tr >
<td > ${param:+word} </td>
<td > 若$param为非空，则参数式返回word，$param不变 </td>
</tr>
<tr >
<td > ${param:=word} </td>
<td > 若$param为空或为设置，则参数式返回word，同时$param设置为word </td>
</tr>
<tr >
<td > ${param:?message} </td>
<td > 若$param为空或为设置，则输出错误信息message，若包含空白符，则需引号 </td>
</tr>
</table>
]]></content:encoded>
			<wfw:commentRss>http://www.dutor.net/index.php/2010/05/shell-argument-extension/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>[命令技巧]使用dd</title>
		<link>http://www.dutor.net/index.php/2010/04/use-cmd-dd/</link>
		<comments>http://www.dutor.net/index.php/2010/04/use-cmd-dd/#comments</comments>
		<pubDate>Wed, 28 Apr 2010 12:18:30 +0000</pubDate>
		<dc:creator>dutor</dc:creator>
				<category><![CDATA[Unix/Linux]]></category>
		<category><![CDATA[命令]]></category>

		<guid isPermaLink="false">http://www.dutor.net/?p=2198</guid>
		<description><![CDATA[<h4>dd简介</h4>
　　dd是一个比较古老的命令，早在Unix诞生之时就来到人间，成为每一个Hacker的必备工具。它是干什么的？对此，man大叔有话说。dd是一个拷贝文件的命令，同时它会根据特定选项对文件进行转换和格式化。主要的选项有：
<ul>
  	<li><strong>ibs=BYTES</strong>，一次从输入文件中拷贝的字节数（BLOCKS）</li>
  	<li><strong>if=FILE </strong>，指定输入文件，缺省为stdin</li>
  	<li><strong>obs=BYTES</strong>， 一次从输出文件中拷贝的字节数</li>
 	<li><strong>of=FILE</strong>，指定输出文件，不会截断文件，缺省为stdout</li>
	<li><strong>bs=BYTES</strong>，同时指定ibs=BYTES, obs=BYTES</li>
 	<li><strong>cbs=BYTES </strong>，每次转换的字节数</li>
  	<li><strong>conv=KEYWORDS[,KEYWORDS]</strong>，根据KEYWORDS指定的规则（多个规则以逗号,分隔）对文件进行转换</li>
  	<li><strong>count=BLOCKS</strong>，指定从输入文件中要拷贝的BLOCKS数</li>
  	<li><strong>seek=BLOCKS</strong>，从输出文件开头处跳过指定的BLOCKS数</li>
  	<li><strong>skip=BLOCKS</strong> ，从输出文件开头处跳过指定的BLOCKS数</li>
</ul>]]></description>
			<content:encoded><![CDATA[<p>　　原计划每周介绍一个Unix/Linux命令的，可由于时间和精力的原因，目前只写了一篇<a href="http://www.dutor.net/index.php/2010/04/cmd-cd/" target="_blank">关于cd</a>(Change Directory)的。尽力吧，今天介绍一下dd，let&#8217;s go. <img src="http://www.dutor.net/wp-content/cache/e07bfd5e23027b462ed96336a470335d.png" align="absmiddle" class="tex" alt="\color{red}\sqrt{\heartsuit}" /></p>
<hr />
<h4>dd简介</h4>
<p>　　dd是一个比较古老的命令，早在Unix诞生之时就来到人间，成为每一个Hacker的必备工具。它是干什么的？对此，man大叔有话说。dd是一个拷贝文件的命令，同时它会根据特定选项对文件进行转换和格式化。主要的选项有：</p>
<ul>
<li><strong>ibs=BYTES</strong>，一次从输入文件中拷贝的字节数（BLOCKS）</li>
<li><strong>if=FILE </strong>，指定输入文件，缺省为stdin</li>
<li><strong>obs=BYTES</strong>， 一次从输出文件中拷贝的字节数</li>
<li><strong>of=FILE</strong>，指定输出文件，不会截断文件，缺省为stdout</li>
<li><strong>bs=BYTES</strong>，同时指定ibs=BYTES, obs=BYTES</li>
<li><strong>cbs=BYTES </strong>，每次转换的字节数</li>
<li><strong>conv=KEYWORDS[,KEYWORDS]</strong>，根据KEYWORDS指定的规则（多个规则以逗号,分隔）对文件进行转换</li>
<li><strong>count=BLOCKS</strong>，指定从输入文件中要拷贝的BLOCKS数</li>
<li><strong>seek=BLOCKS</strong>，从输出文件开头处跳过指定的BLOCKS数</li>
<li><strong>skip=BLOCKS</strong> ，从输出文件开头处跳过指定的BLOCKS数</li>
</ul>
<p>　　指定BYTES时默认为BYTES个字节，如512为512字节。数字后面可以加单位修饰，如512b同512, 512w等于512*2, 512K等于512*1024, 512M等于512*1024*1024。<br />
　　可供选择的KEYWORDS有：</p>
<ul>
<li><strong>ascii </strong>，将<a href="http://natural-innovations.com/computing/asciiebcdic.html">EBCDIC</a>编码转换为ASCII编码</li>
<li><strong>ebcdic</strong>，将ASCII编码转换为EBCDIC编码</li>
<li><strong>block</strong>，将\n结束变长记录转换到cbs指定的长度，不足部分以空格填充</li>
<li><strong>unblock</strong>，将每个cbs尾部填充的空格剔除</li>
<li><strong>lcase</strong>，将字母转换为小写</li>
<li><strong>ucase</strong>，将字母转换为大写</li>
<li><strong>swab</strong>，交换每对相邻的字符的位置，例如&#8217;echo abcd|dd conv=swab&#8217;输出badc</li>
<li><strong>noerror</strong>，忽略读文件产生的错误</li>
<li><strong>sync</strong>，将每一个输入块用0填充至ibs指定的大小</li>
</ul>
<h4>dd用例</h4>
<h5>文件/设备备份</h5>

<div class="wp_codebox"><table><tr id="p219895"><td class="code" id="p2198code95"><pre class="bash" style="font-family:monospace;"><span style="color: #c20cb9; font-weight: bold;">dd</span> <span style="color: #007800;">if</span>=<span style="color: #000000; font-weight: bold;">/</span>dev<span style="color: #000000; font-weight: bold;">/</span>hda <span style="color: #007800;">of</span>=<span style="color: #000000; font-weight: bold;">/</span>path<span style="color: #000000; font-weight: bold;">/</span>to<span style="color: #000000; font-weight: bold;">/</span>image</pre></td></tr></table></div>

<p>将整个磁盘hda镜像到image文件。</p>

<div class="wp_codebox"><table><tr id="p219896"><td class="code" id="p2198code96"><pre class="bash" style="font-family:monospace;"><span style="color: #c20cb9; font-weight: bold;">dd</span> <span style="color: #007800;">if</span>=<span style="color: #000000; font-weight: bold;">/</span>dev<span style="color: #000000; font-weight: bold;">/</span>hda <span style="color: #000000; font-weight: bold;">|</span> <span style="color: #c20cb9; font-weight: bold;">gzip</span> <span style="color: #000000; font-weight: bold;">&gt;/</span>path<span style="color: #000000; font-weight: bold;">/</span>to<span style="color: #000000; font-weight: bold;">/</span>image.gz</pre></td></tr></table></div>

<p>备份/dev/hda全盘数据，并利用gzip工具进行压缩，保存到指定路径</p>

<div class="wp_codebox"><table><tr id="p219897"><td class="code" id="p2198code97"><pre class="bash" style="font-family:monospace;"><span style="color: #c20cb9; font-weight: bold;">gzip</span> <span style="color: #660033;">-dc</span> <span style="color: #000000; font-weight: bold;">/</span>path<span style="color: #000000; font-weight: bold;">/</span>to<span style="color: #000000; font-weight: bold;">/</span>image.gz <span style="color: #000000; font-weight: bold;">|</span> <span style="color: #c20cb9; font-weight: bold;">dd</span> <span style="color: #007800;">of</span>=<span style="color: #000000; font-weight: bold;">/</span>dev<span style="color: #000000; font-weight: bold;">/</span>hda</pre></td></tr></table></div>

<p>将压缩的备份文件恢复到指定盘</p>

<div class="wp_codebox"><table><tr id="p219898"><td class="code" id="p2198code98"><pre class="bash" style="font-family:monospace;"><span style="color: #c20cb9; font-weight: bold;">dd</span> <span style="color: #007800;">if</span>=<span style="color: #000000; font-weight: bold;">/</span>dev<span style="color: #000000; font-weight: bold;">/</span>fd0 <span style="color: #007800;">of</span>=disk.img <span style="color: #007800;">count</span>=<span style="color: #000000;">1</span> <span style="color: #007800;">bs</span>=1440k</pre></td></tr></table></div>

<p>将软驱数据备份到当前目录的disk.img文件</p>

<div class="wp_codebox"><table><tr id="p219899"><td class="code" id="p2198code99"><pre class="bash" style="font-family:monospace;"><span style="color: #c20cb9; font-weight: bold;">dd</span> <span style="color: #007800;">if</span>=<span style="color: #000000; font-weight: bold;">/</span>dev<span style="color: #000000; font-weight: bold;">/</span>hda <span style="color: #007800;">of</span>=<span style="color: #000000; font-weight: bold;">/</span>path<span style="color: #000000; font-weight: bold;">/</span>to<span style="color: #000000; font-weight: bold;">/</span>mbr <span style="color: #007800;">count</span>=<span style="color: #000000;">1</span> <span style="color: #007800;">bs</span>=<span style="color: #000000;">512</span></pre></td></tr></table></div>

<p>备份磁盘开始的512Byte大小的MBR信息到指定文件</p>

<div class="wp_codebox"><table><tr id="p2198100"><td class="code" id="p2198code100"><pre class="bash" style="font-family:monospace;"><span style="color: #c20cb9; font-weight: bold;">dd</span> <span style="color: #007800;">if</span>=<span style="color: #000000; font-weight: bold;">/</span>path<span style="color: #000000; font-weight: bold;">/</span>to<span style="color: #000000; font-weight: bold;">/</span>mbr <span style="color: #007800;">of</span>=<span style="color: #000000; font-weight: bold;">/</span>dev<span style="color: #000000; font-weight: bold;">/</span>hda</pre></td></tr></table></div>

<p>将备份的MBR信息写到磁盘开始部分</p>

<div class="wp_codebox"><table><tr id="p2198101"><td class="code" id="p2198code101"><pre class="bash" style="font-family:monospace;"><span style="color: #c20cb9; font-weight: bold;">dd</span> <span style="color: #007800;">if</span>=<span style="color: #000000; font-weight: bold;">/</span>dev<span style="color: #000000; font-weight: bold;">/</span>mem <span style="color: #007800;">of</span>=<span style="color: #000000; font-weight: bold;">/</span>root<span style="color: #000000; font-weight: bold;">/</span>mem.bin <span style="color: #007800;">bs</span>=<span style="color: #000000;">1024</span></pre></td></tr></table></div>

<p>将内存里的数据拷贝到root目录下的mem.bin文件</p>

<div class="wp_codebox"><table><tr id="p2198102"><td class="code" id="p2198code102"><pre class="bash" style="font-family:monospace;"><span style="color: #c20cb9; font-weight: bold;">dd</span> <span style="color: #007800;">if</span>=<span style="color: #000000; font-weight: bold;">/</span>dev<span style="color: #000000; font-weight: bold;">/</span>cdrom <span style="color: #007800;">of</span>=cd.iso</pre></td></tr></table></div>

<p>拷贝光盘数据，保存为cd.iso文件</p>
<h5>改变交换分区的大小</h5>

<div class="wp_codebox"><table><tr id="p2198103"><td class="code" id="p2198code103"><pre class="bash" style="font-family:monospace;"><span style="color: #c20cb9; font-weight: bold;">dd</span> <span style="color: #007800;">if</span>=<span style="color: #000000; font-weight: bold;">/</span>dev<span style="color: #000000; font-weight: bold;">/</span>zero <span style="color: #007800;">of</span>=<span style="color: #000000; font-weight: bold;">/</span>swapfile <span style="color: #007800;">bs</span>=<span style="color: #000000;">4096</span> <span style="color: #007800;">count</span>=512K</pre></td></tr></table></div>

<p>创建一个足够大的文件（此处为2G）</p>

<div class="wp_codebox"><table><tr id="p2198104"><td class="code" id="p2198code104"><pre class="bash" style="font-family:monospace;">mkswap <span style="color: #000000; font-weight: bold;">/</span>swapfile</pre></td></tr></table></div>

<p>格式化这个文件为swap文件</p>

<div class="wp_codebox"><table><tr id="p2198105"><td class="code" id="p2198code105"><pre class="bash" style="font-family:monospace;">swapon <span style="color: #000000; font-weight: bold;">/</span>swapfile</pre></td></tr></table></div>

<p>启用这个swap文件</p>

<div class="wp_codebox"><table><tr id="p2198106"><td class="code" id="p2198code106"><pre class="bash" style="font-family:monospace;"><span style="color: #000000; font-weight: bold;">/</span>swapfile swap swap defaults <span style="color: #000000;">0</span> <span style="color: #000000;">0</span></pre></td></tr></table></div>

<p>在每次开机的时候自动加载swap文件, 需要在 /etc/fstab 文件中增加一行 </p>
<h5>测试硬盘的速度</h5>

<div class="wp_codebox"><table><tr id="p2198107"><td class="code" id="p2198code107"><pre class="bash" style="font-family:monospace;"><span style="color: #c20cb9; font-weight: bold;">dd</span> <span style="color: #007800;">if</span>=<span style="color: #000000; font-weight: bold;">/</span>dev<span style="color: #000000; font-weight: bold;">/</span>zero <span style="color: #007800;">of</span>=largefile <span style="color: #007800;">bs</span>=1M <span style="color: #007800;">count</span>=1K</pre></td></tr></table></div>

<p>产生一个大小为1G的文件</p>

<div class="wp_codebox"><table><tr id="p2198108"><td class="code" id="p2198code108"><pre class="bash" style="font-family:monospace;"><span style="color: #c20cb9; font-weight: bold;">dd</span> <span style="color: #007800;">if</span>=largefile <span style="color: #007800;">of</span>=<span style="color: #000000; font-weight: bold;">/</span>dev<span style="color: #000000; font-weight: bold;">/</span>null <span style="color: #007800;">bs</span>=1M <span style="color: #007800;">count</span>=1K</pre></td></tr></table></div>

<p>复制该文件到空设备/dev/null<br />
通过这两个命令可测试出磁盘的读写速度</p>
<h5>快速生成一定大小的文件</h5>

<div class="wp_codebox"><table><tr id="p2198109"><td class="code" id="p2198code109"><pre class="bash" style="font-family:monospace;"><span style="color: #c20cb9; font-weight: bold;">dd</span> <span style="color: #007800;">if</span>=<span style="color: #000000; font-weight: bold;">/</span>dev<span style="color: #000000; font-weight: bold;">/</span>zero <span style="color: #007800;">of</span>=largefile <span style="color: #007800;">bs</span>=1M <span style="color: #007800;">count</span>=1K</pre></td></tr></table></div>

<p>产生大小为1G的文件，由0填充</p>

<div class="wp_codebox"><table><tr id="p2198110"><td class="code" id="p2198code110"><pre class="bash" style="font-family:monospace;"><span style="color: #c20cb9; font-weight: bold;">dd</span> <span style="color: #007800;">if</span>=<span style="color: #000000; font-weight: bold;">/</span>dev<span style="color: #000000; font-weight: bold;">/</span>urandom <span style="color: #007800;">of</span>=largefile <span style="color: #007800;">bs</span>=1M <span style="color: #007800;">count</span>=1K</pre></td></tr></table></div>

<p>产生大小为1G的文件，由随机数填充</p>
<h5>Unix/Linux的一些特殊设备文件</h5>
<p>一切皆文件。</p>
<ul>
<li><strong>/dev/mem</strong>，直接存取物理内存</li>
<li><strong>/dev/null</strong>，空设备。任何写入都将被直接丢弃，任何读取都将得到EOF。</li>
<li><strong>/dev/zero</strong>，零字节源，只能读取到无限多的零字节。</li>
<li><strong>/dev/full</strong>，满设备。任何写入都将失败，并把errno设为ENOSPC以表示没有剩余空间。</li>
<li><strong>/dev/random</strong>，随机数发生器。完全由用户的输入来产生随机数。	如果用户停止所有动作，则停止产生新的随机数。</li>
<li><strong>/dev/urandom</strong>，更快，但是不够安全的随机数发生器。尽可能由用户的输入来产生随机数，如果用户停止所有动作，则把已经产生的随机数做为种子来产生新的随机数。</li>
</ul>
]]></content:encoded>
			<wfw:commentRss>http://www.dutor.net/index.php/2010/04/use-cmd-dd/feed/</wfw:commentRss>
		<slash:comments>1</slash:comments>
		</item>
		<item>
		<title>[命令技巧]使用cd</title>
		<link>http://www.dutor.net/index.php/2010/04/use-cmd-cd/</link>
		<comments>http://www.dutor.net/index.php/2010/04/use-cmd-cd/#comments</comments>
		<pubDate>Thu, 15 Apr 2010 00:46:56 +0000</pubDate>
		<dc:creator>dutor</dc:creator>
				<category><![CDATA[Unix/Linux]]></category>
		<category><![CDATA[命令]]></category>

		<guid isPermaLink="false">http://www.dutor.net/?p=2146</guid>
		<description><![CDATA[　　利用alias，可以使我们更快的输入一些常用的但比较长的命令，这当然也适用于cd命令。为了不用每次有执行alias定义别名，我们应该把这些别名放入shell的配置文件中，比如.bashrc和.bash_profile，当shell(这里假定是bash)启动时会自动执行其中的命令。下面列出我常用的一些别名，仅供参考：
<pre lang="bash" line="1">
alias ll='ls -lh'
alias la='ls -A'
alias l='ls -CF'
alias ..='cd ..'
alias ...='cd ../..'
alias ....='cd ../../..'
alias -- -='cd -' # --指示命令选项已经结束，下面全都是参数，否则=会被当作选项
alias bl='bc -l' # calculator with compute library.
bind 'set completion-ignore-case on' # 使shell的Tab自动补全忽略字母的大小写
</pre>]]></description>
			<content:encoded><![CDATA[<p>　　今天开始，我计划每周介绍一个或者与之相关的一类Linux/Unix命令，除基本使用外，更倾向于该这些命令的奇技淫巧。欢迎大家捧场，多做补充。Linux的使用是一个经验积累的过程，更是一种投资。分享是一种美德，愿大家多行善、多积德，帮助别人的同时，也为自己攒点人品。现在就开始！</p>
<hr />
　　我想，cd命令很可能是每一个<strong>Linux</strong>er的第一个命令吧，当然还有可能是ls命令。cd，即Change Directory，将当前工作目录切换至目标目录，基本使用方法是：</p>

<div class="wp_codebox"><table><tr id="p2146111"><td class="code" id="p2146code111"><pre class="bash" style="font-family:monospace;"><span style="color: #7a0874; font-weight: bold;">cd</span> wdir <span style="color: #666666; font-style: italic;"># 切换至当前目录下的wdir目录，使用相对路径</span>
<span style="color: #7a0874; font-weight: bold;">cd</span> <span style="color: #000000; font-weight: bold;">/</span>home<span style="color: #000000; font-weight: bold;">/</span>chris <span style="color: #666666; font-style: italic;"># 使用绝对路径</span></pre></td></tr></table></div>

<h4>特殊目录</h4>
<p>　　为了能够较快的切换目录，Linux下定义了一些特殊的名称或者变量，他们代表着特殊的目录。</p>

<div class="wp_codebox"><table><tr id="p2146112"><td class="line_numbers"><pre>1
2
3
4
5
6
7
8
</pre></td><td class="code" id="p2146code112"><pre class="bash" style="font-family:monospace;"><span style="color: #7a0874; font-weight: bold;">cd</span> .. <span style="color: #666666; font-style: italic;"># 至上级目录，即父目录，根目录/的父目录为其本身</span>
<span style="color: #7a0874; font-weight: bold;">cd</span> . <span style="color: #666666; font-style: italic;"># 至当前目录，即未改变目录，.在某些情况下很是有用</span>
<span style="color: #7a0874; font-weight: bold;">cd</span> ~ <span style="color: #666666; font-style: italic;"># 至当前登录用户的用户目录，如/home/ivan</span>
<span style="color: #7a0874; font-weight: bold;">cd</span> <span style="color: #666666; font-style: italic;"># 同上</span>
<span style="color: #7a0874; font-weight: bold;">cd</span> <span style="color: #007800;">$HOME</span> <span style="color: #666666; font-style: italic;"># 同上</span>
<span style="color: #7a0874; font-weight: bold;">cd</span> ~Chris <span style="color: #666666; font-style: italic;"># 至Chris同学的用户目录，即/home/Chris</span>
<span style="color: #7a0874; font-weight: bold;">cd</span> - <span style="color: #666666; font-style: italic;"># 至最近离开的目录，很常用</span>
<span style="color: #7a0874; font-weight: bold;">cd</span> <span style="color: #000000; font-weight: bold;">!</span>$ <span style="color: #666666; font-style: italic;"># !$为上一个命令中的最后一个参数</span></pre></td></tr></table></div>

<h4>使用别名alias</h4>
<p>　　alias命令可以定义别名，Shell会将以后执行的命令中alias的第一个参数替换为第二个参数然后执行：</p>

<div class="wp_codebox"><table><tr id="p2146113"><td class="line_numbers"><pre>1
2
</pre></td><td class="code" id="p2146code113"><pre class="bash" style="font-family:monospace;"><span style="color: #7a0874; font-weight: bold;">alias</span> <span style="color: #007800;">short</span>=<span style="color: #ff0000;">&quot;longlong -a long&quot;</span>
short <span style="color: #666666; font-style: italic;"># 等同于longlong -a long</span></pre></td></tr></table></div>

<p>　　利用alias，可以使我们更快的输入一些常用的但比较长的命令，这当然也适用于cd命令。为了不用每次有执行alias定义别名，我们应该把这些别名放入shell的配置文件中，比如.bashrc和.bash_profile，当shell(这里假定是bash)启动时会自动执行其中的命令。下面列出我常用的一些别名，仅供参考：</p>

<div class="wp_codebox"><table><tr id="p2146114"><td class="line_numbers"><pre>1
2
3
4
5
6
7
8
9
</pre></td><td class="code" id="p2146code114"><pre class="bash" style="font-family:monospace;"><span style="color: #7a0874; font-weight: bold;">alias</span> <span style="color: #007800;">ll</span>=<span style="color: #ff0000;">'ls -lh'</span>
<span style="color: #7a0874; font-weight: bold;">alias</span> <span style="color: #007800;">la</span>=<span style="color: #ff0000;">'ls -A'</span>
<span style="color: #7a0874; font-weight: bold;">alias</span> <span style="color: #007800;">l</span>=<span style="color: #ff0000;">'ls -CF'</span>
<span style="color: #7a0874; font-weight: bold;">alias</span> ..=<span style="color: #ff0000;">'cd ..'</span>
<span style="color: #7a0874; font-weight: bold;">alias</span> ...=<span style="color: #ff0000;">'cd ../..'</span>
<span style="color: #7a0874; font-weight: bold;">alias</span> ....=<span style="color: #ff0000;">'cd ../../..'</span>
<span style="color: #7a0874; font-weight: bold;">alias</span> <span style="color: #660033;">--</span> -=<span style="color: #ff0000;">'cd -'</span> <span style="color: #666666; font-style: italic;"># --指示命令选项已经结束，下面全都是参数，否则=会被当作选项</span>
<span style="color: #7a0874; font-weight: bold;">alias</span> <span style="color: #007800;">bl</span>=<span style="color: #ff0000;">'bc -l'</span> <span style="color: #666666; font-style: italic;"># calculator with compute library.</span>
<span style="color: #7a0874; font-weight: bold;">bind</span> <span style="color: #ff0000;">'set completion-ignore-case on'</span> <span style="color: #666666; font-style: italic;"># 使shell的Tab自动补全忽略字母的大小写</span></pre></td></tr></table></div>

<h4>使用$CDPATH</h4>
<p>　　$CDPATH是bash的标准环境变量，它保存着cd命令默认搜索的一些目录，类似于$PATH变量。它是一组由分号<strong>:</strong>分隔的目录的路径组成的。<br />
　　举例来说，我的工作目录为/home/Wdir，其下有很多不同类的目录，比如Cpp、Site、ACM、APUE、LaTeX等等。每次我都需要执行cd Wdir/ACM进入ACM目录，甚是麻烦。如果我把/home/Wdir加入到$CDPATH变量中，我就可以通过cd ACM直接进入ACM目录了。我的$CDPATH=&#8217;/:./:~/Wdir:/var:/media&#8217;，同样地，我们需要把这个设置写入到.bashrc中，把该环境变量导出(export):</p>

<div class="wp_codebox"><table><tr id="p2146115"><td class="code" id="p2146code115"><pre class="bash" style="font-family:monospace;"><span style="color: #7a0874; font-weight: bold;">export</span> <span style="color: #007800;">CDPATH</span>=<span style="color: #ff0000;">'/:./:~/Wdir:/var:/media'</span></pre></td></tr></table></div>

<h4>Update!!!(2010-05-30)</h4>
<p>　　介绍一个新命令，保准你从未听说过，但它实现的操作你应该一直都在使用，这个命令就是mkcd。其实它不是一个命令，而是一个shell函数：</p>

<div class="wp_codebox"><table><tr id="p2146116"><td class="line_numbers"><pre>1
2
3
4
5
6
7
8
9
10
11
</pre></td><td class="code" id="p2146code116"><pre class="bash" style="font-family:monospace;"><span style="color: #666666; font-style: italic;"># mkcd: mkdir, then cd</span>
mkcd<span style="color: #7a0874; font-weight: bold;">&#40;</span><span style="color: #7a0874; font-weight: bold;">&#41;</span>
<span style="color: #7a0874; font-weight: bold;">&#123;</span>
    <span style="color: #000000; font-weight: bold;">if</span> <span style="color: #7a0874; font-weight: bold;">&#91;</span> <span style="color: #007800;">$#</span> = <span style="color: #ff0000;">&quot;1&quot;</span> <span style="color: #7a0874; font-weight: bold;">&#93;</span>
    <span style="color: #000000; font-weight: bold;">then</span>
        <span style="color: #c20cb9; font-weight: bold;">mkdir</span> <span style="color: #660033;">-p</span> <span style="color: #ff0000;">&quot;$1&quot;</span>
        <span style="color: #7a0874; font-weight: bold;">cd</span> <span style="color: #ff0000;">&quot;$1&quot;</span>
    <span style="color: #000000; font-weight: bold;">else</span>
        <span style="color: #7a0874; font-weight: bold;">echo</span> <span style="color: #ff0000;">&quot;Usage: mkcd folder&quot;</span>
    <span style="color: #000000; font-weight: bold;">fi</span>
<span style="color: #7a0874; font-weight: bold;">&#125;</span></pre></td></tr></table></div>

<p>　　很简单，相信你一看就知道它能做什么了。<br />
　　你需要做的就是把这个函数丢进你的.bashrc，然后</p>

<div class="wp_codebox"><table><tr id="p2146117"><td class="line_numbers"><pre>1
</pre></td><td class="code" id="p2146code117"><pre class="bash" style="font-family:monospace;"><span style="color: #7a0874; font-weight: bold;">source</span> ~<span style="color: #000000; font-weight: bold;">/</span>.bashrc <span style="color: #666666; font-style: italic;"># 重新加载，使.bashrc立即生效</span></pre></td></tr></table></div>

<h4>注意</h4>
<p>　　任何东西都不可滥用。过度的使用alias可能会造成名字的混乱，向$CDPATH添加过多的目录有时也会让你吃尽苦头。</p>
]]></content:encoded>
			<wfw:commentRss>http://www.dutor.net/index.php/2010/04/use-cmd-cd/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>虚拟内存管理总结</title>
		<link>http://www.dutor.net/index.php/2010/04/virtual-memory/</link>
		<comments>http://www.dutor.net/index.php/2010/04/virtual-memory/#comments</comments>
		<pubDate>Sun, 11 Apr 2010 05:32:48 +0000</pubDate>
		<dc:creator>dutor</dc:creator>
				<category><![CDATA[Unix/Linux]]></category>
		<category><![CDATA[OS基础]]></category>
		<category><![CDATA[虚拟内存]]></category>

		<guid isPermaLink="false">http://www.dutor.net/index.php/2010/04/%e8%99%9a%e6%8b%9f%e5%86%85%e5%ad%98%e7%ae%a1%e7%90%86%e6%80%bb%e7%bb%93/</guid>
		<description><![CDATA[　　去年写的，后来整理文章时"丢"了，现在把它贴回来。

　　操作系统为每一个进程维护着一个虚拟的地址空间，这个地址空间的大小通常取决于系统的地址线数目，比如在32位系统中，虚拟地址空间的返回就是0×00000000~0xFFFFFFFF，大小共4G。通常操作系统会划分出一部分来专门供内核使用，而不允许用户进程直接访问。Linux内核占用4G中高地址的1G，即0XC0000000~0XFFFFFFFF，windows内核通常占用高地址的2G空间，但也可配置成1G。进程的代码、数据以及共享库等资源终究是要放在物理内存中才能被访问的，操作系统在建立用户进程时，会为其建立各自独立的虚拟地址空间，然后将各自的数据段、代码段、BSS段等映射到这个地址空间，并为其初始化堆、栈等必须的资源。另外，操作系统还将虚拟空间和物理空间都划分成大小相等的页，把进程数据所在虚拟地址空间的各个虚拟页面映射到其真正被加载的物理页面，这种映射是全相联方式的，即任何一个虚页可以被映射到任何一个实页。]]></description>
			<content:encoded><![CDATA[<p>　　去年写的，后来整理文章时&#8221;丢&#8221;了，现在把它贴回来。</p>
<hr />
　　操作系统为每一个进程维护着一个虚拟的地址空间，这个地址空间的大小通常取决于系统的地址线数目，比如在32位系统中，虚拟地址空间的返回就是0×00000000~0xFFFFFFFF，大小共4G。通常操作系统会划分出一部分来专门供内核使用，而不允许用户进程直接访问。Linux内核占用4G中高地址的1G，即0XC0000000~0XFFFFFFFF，windows内核通常占用高地址的2G空间，但也可配置成1G。进程的代码、数据以及共享库等资源终究是要放在物理内存中才能被访问的，操作系统在建立用户进程时，会为其建立各自独立的虚拟地址空间，然后将各自的数据段、代码段、BSS段等映射到这个地址空间，并为其初始化堆、栈等必须的资源。另外，操作系统还将虚拟空间和物理空间都划分成大小相等的页，把进程数据所在虚拟地址空间的各个虚拟页面映射到其真正被加载的物理页面，这种映射是全相联方式的，即任何一个虚页可以被映射到任何一个实页。</p>
<p>　　操作系统采用虚拟内存的方式管理存储器有很多好处：<br />
　　第一，<strong>虚拟内存管理可以控制物理内存的访问权限</strong>。物理内存本身是不限制访问的，任何地址都可以读写，而操作系统要求不同的页面具有不同的访问权限，这是利用CPU模式和MMU的内存保护机制实现的。例如，代码段被只读保护起来，防止被错误的指令意外改写，内核地址空间也被保护起来，防止在用户模式下执行错误的指令意外改写内核数据。这样，执行错误指令或恶意代码的破坏能力受到了限制，顶多使当前进程因段错误终止，而不会影响整个系统的稳定性。</p>
<p>　　第二，<strong>虚拟内存管理最主要的作用是让每个进程有独立的地址空间</strong>。所谓独立的地址空间是指，不同进程中的同一个VA被MMU映射到不同的PA，并且在某一个进程中访问任何地址都不可能访问到另外一个进程的数据，这样使得任何一个进程由于执行错误指令或恶意代码导致的非法内存访问都不会意外改写其它进程的数据，不会影响其它进程的运行，从而保证整个系统的稳定性。另一方面，每个进程都认为自己独占整个虚拟地址空间，这样链接器和加载器的实现会比较容易，不必考虑各进程的地址范围是否冲突。</p>
<p>　　第三，<strong>方便了共享库的实现</strong>。采用共享库的目的在于节省内存(物理内存)，一些公用模块在内存中可以只保存一份，让各进程共享，而不是各自加载一份，当然，只读的代码段可以共享，可写的数据段就必须各自保留一份了。采用虚拟内存机制后，可以将物理内存中所加载的共享库分别映射到进程各自的地址空间，由于加载地址可能不同，所以共享库必须实现为地址无关码(PIC)。</p>
<p>　　第三，<strong>VA到PA的映射会给分配和释放内存带来方便，物理地址不连续的几块内存可以映射成虚拟地址连续的一块内存</strong>。比如要用malloc分配一块很大的内存空间，虽然有足够多的空闲物理内存，却没有足够大的连续空闲内存，这时就可以分配多个不连续的物理页面而映射到连续的虚拟地址范围。</p>
<p>　　第四，<strong>“增加”了程序可以使用的内存空间</strong>。一个系统如果同时运行着很多进程，为各进程分配的内存之和可能会大于实际可用的物理内存，虚拟内存管理使得这种情况下各进程仍然能够正常运行。因为各进程分配的只不过是虚拟内存的页面，这些页面的数据可以映射到物理页面，也可以临时保存到磁盘上而不占用物理页面。当所访问的页面不在内存中时再将其加载进来，无空闲页面的时候还可能需要采取一定的置换算法将某个页面换出。这种机制的可行性得益于伟大的“局部性原理”。</p>
]]></content:encoded>
			<wfw:commentRss>http://www.dutor.net/index.php/2010/04/virtual-memory/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
	</channel>
</rss>

