<?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>Programming Life with Music &#187; Linux</title>
	<atom:link href="http://jackaldire.com/tag/linux/feed/" rel="self" type="application/rss+xml" />
	<link>http://jackaldire.com</link>
	<description>JackalDire &#039;s Blog</description>
	<lastBuildDate>Tue, 13 Jul 2010 08:29:29 +0000</lastBuildDate>
	<language>en</language>
	<sy:updatePeriod>hourly</sy:updatePeriod>
	<sy:updateFrequency>1</sy:updateFrequency>
	<generator>http://wordpress.org/?v=3.0</generator>
<atom:link rel="hub" href="http://pubsubhubbub.appspot.com"/><atom:link rel="hub" href="http://superfeedr.com/hubbub"/>		<item>
		<title>自己动手写Linux Shell（三） —— 支持IO重定向</title>
		<link>http://jackaldire.com/201001/write-your-own-shell-3-io-redirection/</link>
		<comments>http://jackaldire.com/201001/write-your-own-shell-3-io-redirection/#comments</comments>
		<pubDate>Sun, 31 Jan 2010 14:57:56 +0000</pubDate>
		<dc:creator>JackalDire</dc:creator>
				<category><![CDATA[Linux与开源]]></category>
		<category><![CDATA[编程]]></category>
		<category><![CDATA[Linux]]></category>
		<category><![CDATA[Shell]]></category>

		<guid isPermaLink="false">http://jackaldire.com/?p=86</guid>
		<description><![CDATA[1.IO重定向功能分析 IO重定向也是Shell的基本功能之一，这篇文章比较全面地介绍了Linux Shell的IO重定向功能。总结一下，IO重定向的大致格式是这样： cmd &#91;src &#124; &#38;&#93; &#40;&#62; &#124; &#60; &#124; &#62;&#62; &#41; &#40;&#38; num&#124;-&#41; &#124; dst 貌似写得有点复杂（我不是故意的）。解释一下，整个重定向语句由三部分组成： 第一部分（[src&#124;&#038;]）：src代表被重定向的文件描述符，一般是0（stdin）、1（stdout）和2（stderr），此外还可以是‘＆’，代表2和3，也就是把stdout和stderr同时重定向。这一部分通常是省略的，‘>’和‘>>’隐含了0，‘ &#124; < &#124; >>）：三种操作符。‘’将src的输出重定向到目标文件（若文件不存在则创建，否则现有文件被截断(truncation)）；‘>>’将src的输出附加到（pending）目标文件尾部（若文件不存在则创建）。 第三部分（ (&#038; num&#124;-) &#124; dst ）：第三部分有两种形式，最常见的就是一个文件名，代表重定向的目标。此外还可以是&#8217;&#038;'加一个数字，代表将src重定向到数字代表的文件描述符上。另外‘&#038;’后还可以接‘-’，代表关闭src。比如： $ cmd 2&#62;&#38;1 将标准错误重定向到标准输出 $ cmd 1&#62;&#38;- 关闭标准输出 $ cmd 0&#60;&#38;- 关闭标准输入 2.IO重定向功能实现 Linux的IO重定向实际上是通过dup函数和close函数配合实现。close关闭一个文件描述符，而dup复制一个文件描述符，并且新产生的文件描述符是当前可用文件描述符的最小值。 通过先将要重定向的fd关闭，在将重定向的目标文件的描述符dup就实现了重定向（因为012三个描述符默认都是打开的，关闭任何一个后其都将成为当前可用的最小文件描述符）。 为了支持重定向命令的分析，实现里新添加了一个结构，记录了每个重定向的必须信息，然后在子进程fork以后根据记录信息进行重定向操作。 测试的时候发现了一个有趣的问题。比如： $ ls &#62;f1 &#62;f2 $ cat &#62;f1 &#62;f2 这两条命令在bash里的结果是后面的重定向覆盖了前面的重定向，这和我的实现是一样的，也是最简单的。而在zsh里，第一条命令的结果是f1 [...]]]></description>
			<content:encoded><![CDATA[<p><embed src="http://www.blogcastone.net/audio/player.swf?soundFile=http%3A%2F%2Fstorage.live.com%2Fitems%2F9151E070FED682BB%21167%3Ffilename%3D11%2520A%2520WINTER%2520STORY.mp3&#038;playerID=10&#038;bg=0xf8f8f8&#038;leftbg=0xeeeeee&#038;lefticon=0x666666&#038;rightbg=0xcccccc&#038;rightbghover=0x999999&#038;righticon=0x666666&#038;righticonhover=0xffffff&#038;text=0x666666&#038;slider=0x666666&#038;track=0xFFFFFF&#038;border=0x666666&#038;loader=0x9FFFB8&#038;loop=no&#038;autostart=no" type="application/x-shockwave-flash" wmode="transparent" height="40" width="290"></embed></p>
<h2>1.IO重定向功能分析</h2>
<p>IO重定向也是Shell的基本功能之一，<a href="http://www.ibm.com/developerworks/cn/linux/l-iotips/">这篇文章</a>比较全面地介绍了Linux Shell的IO重定向功能。总结一下，IO重定向的大致格式是这样：</p>

<div class="wp_syntax"><div class="code"><pre class="bash" style="font-family:monospace;">cmd  <span style="color: #7a0874; font-weight: bold;">&#91;</span>src <span style="color: #000000; font-weight: bold;">|</span> <span style="color: #000000; font-weight: bold;">&amp;</span><span style="color: #7a0874; font-weight: bold;">&#93;</span>     <span style="color: #7a0874; font-weight: bold;">&#40;</span><span style="color: #000000; font-weight: bold;">&gt;</span> <span style="color: #000000; font-weight: bold;">|</span> <span style="color: #000000; font-weight: bold;">&lt;</span> <span style="color: #000000; font-weight: bold;">|</span> <span style="color: #000000; font-weight: bold;">&gt;&gt;</span> <span style="color: #7a0874; font-weight: bold;">&#41;</span>      <span style="color: #7a0874; font-weight: bold;">&#40;</span><span style="color: #000000; font-weight: bold;">&amp;</span> num<span style="color: #000000; font-weight: bold;">|</span>-<span style="color: #7a0874; font-weight: bold;">&#41;</span>  <span style="color: #000000; font-weight: bold;">|</span> dst</pre></div></div>

<p>貌似写得有点复杂（我不是故意的）。解释一下，整个重定向语句由三部分组成：</p>
<p><span id="more-86"></span></p>
<p>第一部分（[src|&#038;]）：src代表被重定向的文件描述符，一般是0（stdin）、1（stdout）和2（stderr），此外还可以是‘＆’，代表2和3，也就是把stdout和stderr同时重定向。这一部分通常是省略的，‘>’和‘>>’隐含了0，‘<’隐含了1，也就是说</p>

<div class="wp_syntax"><div class="code"><pre class="bash" style="font-family:monospace;">$ cmd <span style="color: #000000; font-weight: bold;">&lt;</span><span style="color: #c20cb9; font-weight: bold;">file</span> 等价于
$ cmd <span style="color: #000000;">0</span><span style="color: #000000; font-weight: bold;">&lt;</span><span style="color: #c20cb9; font-weight: bold;">file</span>
$ cmd <span style="color: #000000; font-weight: bold;">&gt;</span><span style="color: #c20cb9; font-weight: bold;">file</span> 等价于
$ cmd <span style="color: #000000;">1</span><span style="color: #000000; font-weight: bold;">&gt;</span><span style="color: #c20cb9; font-weight: bold;">file</span></pre></div></div>

<p>第二部分（> | < | >>）：三种操作符。‘<’将src的输入重定向到目标文件；‘>’将src的输出重定向到目标文件（若文件不存在则创建，否则现有文件被截断(truncation)）；‘>>’将src的输出附加到（pending）目标文件尾部（若文件不存在则创建）。</p>
<p>第三部分（ (&#038; num|-)  | dst ）：第三部分有两种形式，最常见的就是一个文件名，代表重定向的目标。此外还可以是&#8217;&#038;'加一个数字，代表将src重定向到数字代表的文件描述符上。另外‘&#038;’后还可以接‘-’，代表关闭src。比如：</p>

<div class="wp_syntax"><div class="code"><pre class="bash" style="font-family:monospace;">$ cmd <span style="color: #000000;">2</span><span style="color: #000000; font-weight: bold;">&gt;&amp;</span><span style="color: #000000;">1</span>     将标准错误重定向到标准输出
$ cmd <span style="color: #000000;">1</span><span style="color: #000000; font-weight: bold;">&gt;&amp;</span>-      关闭标准输出
$ cmd <span style="color: #000000;">0</span><span style="color: #000000; font-weight: bold;">&lt;&amp;</span>-      关闭标准输入</pre></div></div>

</p>
<h2>2.IO重定向功能实现</h2>
<p>Linux的IO重定向实际上是通过dup函数和close函数配合实现。close关闭一个文件描述符，而dup复制一个文件描述符，并且新产生的文件描述符是当前可用文件描述符的最小值。</p>
<p>通过先将要重定向的fd关闭，在将重定向的目标文件的描述符dup就实现了重定向（因为012三个描述符默认都是打开的，关闭任何一个后其都将成为当前可用的最小文件描述符）。</p>
<p>为了支持重定向命令的分析，实现里新添加了一个结构，记录了每个重定向的必须信息，然后在子进程fork以后根据记录信息进行重定向操作。</p>
<p>测试的时候发现了一个有趣的问题。比如：</p>

<div class="wp_syntax"><div class="code"><pre class="bash" style="font-family:monospace;">$ <span style="color: #c20cb9; font-weight: bold;">ls</span> <span style="color: #000000; font-weight: bold;">&gt;</span>f1 <span style="color: #000000; font-weight: bold;">&gt;</span>f2
$ <span style="color: #c20cb9; font-weight: bold;">cat</span> <span style="color: #000000; font-weight: bold;">&gt;</span>f1 <span style="color: #000000; font-weight: bold;">&gt;</span>f2</pre></div></div>

<p>这两条命令在bash里的结果是后面的重定向覆盖了前面的重定向，这和我的实现是一样的，也是最简单的。而在zsh里，第一条命令的结果是f1 f2文件有相同的内容，也就是标准输出同时被重定向到f1和f2两个文件里了；第二条命令的效果等同于先把f1、f2两个文件现连接起来再重定向到cat的输入。这是相当神奇的，到现在也没找到实现方法，看来得找时间研究一下zsh的代码了。</p>
<p>其实实现重定向最麻烦的地方是命令分析，也就是字符串处理。parse_command函数俨然已经100行了，两个switch-case加无数个if-else组成的大自动机，不加注释恐怕就是write-only了（感觉加了注释还是write-only）&#8230;</p>
<p>打开重定向文件那里有一点问题，一大堆flags或来或去，最傻的是忘了给创建的文件设置mode，结果只能用root权限查看&#8230;</p>
<p><strong>源代码 : <a href='http://jackaldire.com/wordpress/wp-content/uploads/2010/01/jdsh_v3.h'>jdsh_v3.h</a> <a href='http://jackaldire.com/wordpress/wp-content/uploads/2010/01/jdsh_v3.c'>jdsh_v3.c</a>（为了让乱七八糟的代码稍微可读一点，单独分了个头文件出来）</strong></p>
<p>剩下的任务就是管道了，有必要把代码好好整理一下了。</p>

	<h4>Related Post</h4>
	<ul class="st-related-posts">
	<li><a href="http://jackaldire.com/201001/write-your-own-shell-2-background-task/" title="自己动手写Linux Shell（二） —— 支持后台执行 (2010年01月31日)">自己动手写Linux Shell（二） —— 支持后台执行</a> (2)</li>
	<li><a href="http://jackaldire.com/201001/write-your-own-shell-1-a-simple-command-interpreter/" title="自己动手写Linux Shell（一） —— 简单的命令解释器 (2010年01月29日)">自己动手写Linux Shell（一） —— 简单的命令解释器</a> (2)</li>
	<li><a href="http://jackaldire.com/200905/linux-and-i/" title="我和Linux (2009年05月14日)">我和Linux</a> (0)</li>
	<li><a href="http://jackaldire.com/200906/archlinux-tor-config/" title="在Archlinux上的安装Tor (2009年06月8日)">在Archlinux上的安装Tor</a> (6)</li>
</ul>

]]></content:encoded>
			<wfw:commentRss>http://jackaldire.com/201001/write-your-own-shell-3-io-redirection/feed/</wfw:commentRss>
		<slash:comments>1</slash:comments>
		</item>
		<item>
		<title>自己动手写Linux Shell（二） —— 支持后台执行</title>
		<link>http://jackaldire.com/201001/write-your-own-shell-2-background-task/</link>
		<comments>http://jackaldire.com/201001/write-your-own-shell-2-background-task/#comments</comments>
		<pubDate>Sat, 30 Jan 2010 18:09:53 +0000</pubDate>
		<dc:creator>JackalDire</dc:creator>
				<category><![CDATA[Linux与开源]]></category>
		<category><![CDATA[编程]]></category>
		<category><![CDATA[Linux]]></category>
		<category><![CDATA[Shell]]></category>

		<guid isPermaLink="false">http://jackaldire.com/?p=82</guid>
		<description><![CDATA[在写完一个最简单的命令解释器以后，我给自己的shell起了个名字——jdsh（JackalDire Shell）。 本来以为加入后台执行不是什么难事，但是认真想了一下要处理好一个字符‘＆’不是一般的麻烦，各种问题接踵而至，于是决定先找点轻松的活干。 1.加入shell内建命令 每个shell都有自己的内建命令，最常见的有“cd”、“pwd”、“exit”等等。没有“cd“的shell是没法干活的。 其实很简单，标准的做法建个hash表把所有内建命令加进去，parse command以后先查一下表就行了，然后可以通过像Linux Syscall的实现方法一样，用一个字符串连接宏（##）找到对应的处理函数。但是由于只准备写寥寥几个命令，偷懒直接 if else if了（= =!）。 2.打印命令提示符Prompt 每个命令行shell都有命令提示符，告诉用户现在可以敲命令。大多数的linux shell的prompt是可以定制的。我采用了bash的默认格式“[username@hostname cwd]$ ”。实现prompt里的cwd（current working directory）时候发现了一个问题：基本上所有linux shell里都用了&#8217;~'代替$HOME。于是做个个字符串替换，使得home文件夹在显示的时候都显示为&#8217;~'（命令里的路径还不支持&#8217;~'） 3.处理SIGINT、SIGQUIT和SIGTSTP信号 SIGINT信号对应按下ctrl+c，shell对该信号的处理方式是（观察zsh/bash得到，没有查文档）：若shell当前没有前台任务，则输入一个空行，放弃当前正在输入的命令；若当前有前台任务，则SIGINT信号由前台程序捕捉。 SIGQUIT信号对应按下ctrl+\，shell对该信号的处理方式是（观察zsh/bash得到，没有查文档）：若shell当前没有前台任务，则忽略该信号，放弃当前正在输入的命令；若当前有前台任务，则SIGQUIT信号由前台程序捕捉。 SIGQUIT信号对应按下ctrl+z，shell对该信号的处理方式是（观察zsh/bash得到，没有查文档）：若shell当前没有前台任务，则忽略该信号，放弃当前正在输入的命令；若当前有前台任务，则SIGQUIT信号由前台程序捕捉。 PS:对这APUE里的信号表看了一遍，好像没有其他要特殊处理的信号了。 其实很好处理，用signal函数或者sigaction都可以（偷懒就用signal了）。在shell的主进程里改变SIGINT的信号处理函数、忽略SIGQUIT和SIGTSPT信号就可以。 有一个问题需要注意：必须在fork的子进程里恢复对这几个信号的默认处理方式。因为fork产生子进程和父进程有相同的信号处理函数signal handler。解决方法就是fork以后在子进程里手动恢复修改过的信号。另一种方法是不用fork，改用clone系统调用，通过clone flags里的CLONE_SIGHAND参数使得复制出来的进程不保留父进程的信号处理函数。 回到主题上&#8230;.. 4.后台运行程序 其实单纯的实现后台运行很简单，把前面程序里的wait去掉使shell主进程不等待子进程结束就OK了。问题在于，shell是通过一个&#8217;&#038;'字符决定后台执行，如何才能从命令里提取出这个代表后台执行的&#8217;&#038;'字符？ 看起来似乎一个字符串查找就能解决，其实并非如此：如果这&#8217;&#038;'是在一个路径名里呢(Linux中只有一个字符不能做文件名：&#8217;/')。看一下别的shell很快就会找到解决方法：转义字符。如果想把有特殊含义的字符当作一个普通字符处理，那么就要在前面加上转移字符&#8217;\'（比如空格、&#8217;\'、&#8217;&#038;'、&#8217;~'、&#8217;-'等等）。 要支持转移字符，我原来用strsep实现的优美的parse command函数就得全部扔掉重写。没办法，换成了fgetc和丑陋的switch case。 有了转义字符，就可以处理含有特殊字符的文件名了^ ^ 另外，我观察到bash和zsh在后台程序运行结束后都会显示一条提示信息显示pid和命令，于是我也想把这个功能加进去。思路很简单，就是改变SIGCHLD信号的handler，捕捉到SIGCHLD后输出进程信息就可以了。默认SIGCHLD信号是通过wait和waitpid函数捕捉。signal能改变SIGCHLD信号的处理函数，但是无法获得足够的信息（pid、退出代码等），而sigaction支持复杂的信号处理函数，通过向信号处理函数传递siginfo结构，提供更充足的信息（还是sigaction强大）。 差不多就这样了&#8230;代码量翻了一倍，直接贴出来有点恐怖，所以扔到附件了～（BUG很多，就不一一列举了，sign～） 源代码：jdsh_v2.c Related Post 自己动手写Linux Shell（三） —— 支持IO重定向 (1) 自己动手写Linux Shell（一） —— 简单的命令解释器 (2) 我和Linux (0) [...]]]></description>
			<content:encoded><![CDATA[<p>在写完一个最简单的命令解释器以后，我给自己的shell起了个名字——jdsh（JackalDire Shell）。</p>
<p>本来以为加入后台执行不是什么难事，但是认真想了一下要处理好一个字符‘＆’不是一般的麻烦，各种问题接踵而至，于是决定先找点轻松的活干。</p>
<h2>1.加入shell内建命令</h2>
<p><span id="more-82"></span></p>
<p>每个shell都有自己的内建命令，最常见的有“cd”、“pwd”、“exit”等等。没有“cd“的shell是没法干活的。</p>
<p>其实很简单，标准的做法建个hash表把所有内建命令加进去，parse command以后先查一下表就行了，然后可以通过像Linux Syscall的实现方法一样，用一个字符串连接宏（##）找到对应的处理函数。但是由于只准备写寥寥几个命令，偷懒直接 if else if了（= =!）。</p>
<h2>2.打印命令提示符Prompt</h2>
<p>每个命令行shell都有命令提示符，告诉用户现在可以敲命令。大多数的linux shell的prompt是可以定制的。我采用了bash的默认格式“[username@hostname cwd]$ ”。实现prompt里的cwd（current working directory）时候发现了一个问题：基本上所有linux shell里都用了&#8217;~'代替$HOME。于是做个个字符串替换，使得home文件夹在显示的时候都显示为&#8217;~'（命令里的路径还不支持&#8217;~'）</p>
<h2>3.处理SIGINT、SIGQUIT和SIGTSTP信号</h2>
<p>SIGINT信号对应按下ctrl+c，shell对该信号的处理方式是（观察zsh/bash得到，没有查文档）：若shell当前没有前台任务，则输入一个空行，放弃当前正在输入的命令；若当前有前台任务，则SIGINT信号由前台程序捕捉。</p>
<p>SIGQUIT信号对应按下ctrl+\，shell对该信号的处理方式是（观察zsh/bash得到，没有查文档）：若shell当前没有前台任务，则忽略该信号，放弃当前正在输入的命令；若当前有前台任务，则SIGQUIT信号由前台程序捕捉。</p>
<p>SIGQUIT信号对应按下ctrl+z，shell对该信号的处理方式是（观察zsh/bash得到，没有查文档）：若shell当前没有前台任务，则忽略该信号，放弃当前正在输入的命令；若当前有前台任务，则SIGQUIT信号由前台程序捕捉。<br />
PS:对这APUE里的信号表看了一遍，好像没有其他要特殊处理的信号了。</p>
<p>其实很好处理，用signal函数或者sigaction都可以（偷懒就用signal了）。在shell的主进程里改变SIGINT的信号处理函数、忽略SIGQUIT和SIGTSPT信号就可以。</p>
<p>有一个问题需要注意：必须在fork的子进程里恢复对这几个信号的默认处理方式。因为fork产生子进程和父进程有相同的信号处理函数signal handler。解决方法就是fork以后在子进程里手动恢复修改过的信号。另一种方法是不用fork，改用clone系统调用，通过clone flags里的CLONE_SIGHAND参数使得复制出来的进程不保留父进程的信号处理函数。</p>
</p>
<p>回到主题上&#8230;..</p>
<h2>4.后台运行程序</h2>
<p>其实单纯的实现后台运行很简单，把前面程序里的wait去掉使shell主进程不等待子进程结束就OK了。问题在于，shell是通过一个&#8217;&#038;'字符决定后台执行，如何才能从命令里提取出这个代表后台执行的&#8217;&#038;'字符？</p>
<p>看起来似乎一个字符串查找就能解决，其实并非如此：如果这&#8217;&#038;'是在一个路径名里呢(Linux中只有一个字符不能做文件名：&#8217;/')。看一下别的shell很快就会找到解决方法：<strong>转义字符</strong>。如果想把有特殊含义的字符当作一个普通字符处理，那么就要在前面加上转移字符&#8217;\'（比如空格、&#8217;\'、&#8217;&#038;'、&#8217;~'、&#8217;-'等等）。</p>
<p>要支持转移字符，我原来用strsep实现的优美的parse command函数就得全部扔掉重写。没办法，换成了fgetc和丑陋的switch case。</p>
<p>有了转义字符，就可以处理含有特殊字符的文件名了^ ^</p>
<p>另外，我观察到bash和zsh在后台程序运行结束后都会显示一条提示信息显示pid和命令，于是我也想把这个功能加进去。思路很简单，就是改变SIGCHLD信号的handler，捕捉到SIGCHLD后输出进程信息就可以了。默认SIGCHLD信号是通过wait和waitpid函数捕捉。signal能改变SIGCHLD信号的处理函数，但是无法获得足够的信息（pid、退出代码等），而sigaction支持复杂的信号处理函数，通过向信号处理函数传递siginfo结构，提供更充足的信息（还是sigaction强大）。</p>
<p>差不多就这样了&#8230;代码量翻了一倍，直接贴出来有点恐怖，所以扔到附件了～（BUG很多，就不一一列举了，sign～）</p>
<p>源代码：<a href='http://jackaldire.com/wordpress/wp-content/uploads/2010/01/jdsh_v21.c'>jdsh_v2.c</a></p>

	<h4>Related Post</h4>
	<ul class="st-related-posts">
	<li><a href="http://jackaldire.com/201001/write-your-own-shell-3-io-redirection/" title="自己动手写Linux Shell（三） —— 支持IO重定向 (2010年01月31日)">自己动手写Linux Shell（三） —— 支持IO重定向</a> (1)</li>
	<li><a href="http://jackaldire.com/201001/write-your-own-shell-1-a-simple-command-interpreter/" title="自己动手写Linux Shell（一） —— 简单的命令解释器 (2010年01月29日)">自己动手写Linux Shell（一） —— 简单的命令解释器</a> (2)</li>
	<li><a href="http://jackaldire.com/200905/linux-and-i/" title="我和Linux (2009年05月14日)">我和Linux</a> (0)</li>
	<li><a href="http://jackaldire.com/200906/archlinux-tor-config/" title="在Archlinux上的安装Tor (2009年06月8日)">在Archlinux上的安装Tor</a> (6)</li>
</ul>

]]></content:encoded>
			<wfw:commentRss>http://jackaldire.com/201001/write-your-own-shell-2-background-task/feed/</wfw:commentRss>
		<slash:comments>2</slash:comments>
		</item>
		<item>
		<title>自己动手写Linux Shell（一） —— 简单的命令解释器</title>
		<link>http://jackaldire.com/201001/write-your-own-shell-1-a-simple-command-interpreter/</link>
		<comments>http://jackaldire.com/201001/write-your-own-shell-1-a-simple-command-interpreter/#comments</comments>
		<pubDate>Fri, 29 Jan 2010 10:32:37 +0000</pubDate>
		<dc:creator>JackalDire</dc:creator>
				<category><![CDATA[Linux与开源]]></category>
		<category><![CDATA[编程]]></category>
		<category><![CDATA[Linux]]></category>
		<category><![CDATA[Shell]]></category>

		<guid isPermaLink="false">http://jackaldire.com/?p=80</guid>
		<description><![CDATA[Like The Wind &#8212; S.E.N.S 寒假在做Linux Kernel Project这本书上的习题，第二章的练习是写一个简单的shell，看了一下要求觉得这个练习很有价值，涉及到很多Linux C Programming的知识，所以准备认真地做一下。 最终的目标如下: 命令解释执行 支持后台执行(&#038;) 支持输入输出重定向(, >>) 支持管道IPC 内建命令cd, pwd, exit等 可见写一个shell并不是一件简单的事，从简单的一步一步做起吧，手头有APUE，一边做一边查。 一个简单的命令解释器 命令解释执行是shell最基本的功能，实现的方法很简单：从标准输入流中读入命令，然后exec一下就行了。但是还有很多琐碎的地方需要处理： 1.命令行参数传递 首先需要将输入的命令字符串按空格打断（strsep实在是太方便了），然后将打断的字符串构建成一个char*数组，通过execv的第二个参数传递给程序。 注：man exec可以得到关于exec函数族的详细说明。需要说明的是execlp和execvp会在PATH环境变量中的目录搜索可执行程序，而其他的exec函数族函数不会，如果不使用这两个函数，则需要自己编写代码搜索PATH环境变量。 2.使用fork建立子进程 直接在当前进程里exec的话，exec执行的程序结束后，整个程序也就结束了，因为exec直接将原来的进程上下文替换。所以需要fork一个新进程来执行命令，而父进程阻塞直到子进程结束后继续执行，这个可以通过wait函数实现。 3.处理命令的返回值 大多数的shell在命令程序返回非零值（异常退出）会打印出其返回值。而子进程的返回值可以在父进程里通过wait函数的第一个参数得到。然后通过一组宏可以方便地确定子进程的返回状态。这部分内容在APUE里有详细说明（8.6节），下面代码里的pr_exit函数基本上就是从APUE上抄过来的。 4.检查各个函数的返回值 Linux C Programming的一个原则就是在所有可能fail的地方加入检查代码。绝大多数C库函数和Linux系统函数都以负数返回值表示出错，并且通过C库的全局变量errno可以获得错误号，从而得到错误原因，并输出到标准错误流。由于整个过程动作固定，就用一个CHKERR宏来完成了。 下面是源代码 CODE BELOW ARE UNDER GPLV3 LISENCE 1 2 3 4 5 6 7 8 9 10 11 12 13 14 [...]]]></description>
			<content:encoded><![CDATA[<p><embed src="http://www.blogcastone.net/audio/player.swf?soundFile=http%3A%2F%2Fstorage.live.com%2Fitems%2F9151E070FED682BB%21175%3Ffilename%3D4.Like%2520the%2520Wind%2520%7E%2520Guitar%2520Version%2520.mp3&#038;playerID=10&#038;bg=0xf8f8f8&#038;leftbg=0xeeeeee&#038;lefticon=0x666666&#038;rightbg=0xcccccc&#038;rightbghover=0x999999&#038;righticon=0x666666&#038;righticonhover=0xffffff&#038;text=0x666666&#038;slider=0x666666&#038;track=0xFFFFFF&#038;border=0x666666&#038;loader=0x9FFFB8&#038;loop=no&#038;autostart=no" type="application/x-shockwave-flash" wmode="transparent" height="40" width="290"></embed></p>
<div> Like The Wind &#8212; S.E.N.S </div>
<p></p>
<p>寒假在做Linux Kernel Project这本书上的习题，第二章的练习是写一个简单的shell，看了一下要求觉得这个练习很有价值，涉及到很多Linux C Programming的知识，所以准备认真地做一下。</p>
<ol><strong>最终的目标如下:</strong></p>
<li>命令解释执行</li>
<li>支持后台执行(&#038;)</li>
<li>支持输入输出重定向(<, >, >>)</li>
<li>支持管道IPC</li>
<li>内建命令cd, pwd, exit等</li>
</ol>
<p>可见写一个shell并不是一件简单的事，从简单的一步一步做起吧，手头有APUE，一边做一边查。</p>
<p><span id="more-80"></span></p>
<h2>一个简单的命令解释器</h2>
<p>命令解释执行是shell最基本的功能，实现的方法很简单：从标准输入流中读入命令，然后exec一下就行了。但是还有很多琐碎的地方需要处理：</p>
<h3>1.命令行参数传递</h3>
<p>首先需要将输入的命令字符串按空格打断（strsep实在是太方便了），然后将打断的字符串构建成一个char*数组，通过execv的第二个参数传递给程序。</p>
<p>注：man exec可以得到关于exec函数族的详细说明。需要说明的是execlp和execvp会在PATH环境变量中的目录搜索可执行程序，而其他的exec函数族函数不会，如果不使用这两个函数，则需要自己编写代码搜索PATH环境变量。</p>
<h3>2.使用fork建立子进程</h3>
<p>直接在当前进程里exec的话，exec执行的程序结束后，整个程序也就结束了，因为exec直接将原来的进程上下文替换。所以需要fork一个新进程来执行命令，而父进程阻塞直到子进程结束后继续执行，这个可以通过wait函数实现。</p>
<h3>3.处理命令的返回值</h3>
<p>大多数的shell在命令程序返回非零值（异常退出）会打印出其返回值。而子进程的返回值可以在父进程里通过wait函数的第一个参数得到。然后通过一组宏可以方便地确定子进程的返回状态。这部分内容在APUE里有详细说明（8.6节），下面代码里的pr_exit函数基本上就是从APUE上抄过来的。</p>
<h3>4.检查各个函数的返回值</h3>
<p>Linux C Programming的一个原则就是在所有可能fail的地方加入检查代码。绝大多数C库函数和Linux系统函数都以负数返回值表示出错，并且通过C库的全局变量errno可以获得错误号，从而得到错误原因，并输出到标准错误流。由于整个过程动作固定，就用一个CHKERR宏来完成了。
<p>下面是源代码</p>
<p><strong>CODE BELOW ARE UNDER <a href="http://www.gnu.org/licenses/gpl-3.0-standalone.html">GPLV3 LISENCE</a></strong></p>

<div class="wp_syntax"><table><tr><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"><pre class="c" style="font-family:monospace;"><span style="color: #808080; font-style: italic;">/* By JackalDire, Jan 29 2010 
 * Tested on Linux Kernel 2.6.32, gcc 4.4.3 */</span>
<span style="color: #339933;">#include &lt;unistd.h&gt;</span>
<span style="color: #339933;">#include &lt;sys/wait.h&gt;</span>
&nbsp;
<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;string.h&gt;</span>
<span style="color: #339933;">#include &lt;errno.h&gt;</span>
&nbsp;
<span style="color: #339933;">#define LINE_MAX 8192</span>
<span style="color: #339933;">#define ARG_MAX 1024</span>
<span style="color: #339933;">#define ARG_NR_MAX 32</span>
&nbsp;
<span style="color: #339933;">#define CHKERR(ret, msg) if (ret &lt; 0) {\
        fprintf(stderr, &quot;ERROR : \&quot;%s\&quot;, %s\n&quot;, \
                msg, strerror(errno)); \
        exit(-1);   \
    } </span>
&nbsp;
<span style="color: #993333;">char</span> <span style="color: #339933;">*</span> args<span style="color: #009900;">&#91;</span>ARG_NR_MAX <span style="color: #339933;">+</span> <span style="color: #0000dd;">1</span><span style="color: #009900;">&#93;</span><span style="color: #339933;">;</span>
<span style="color: #000000; font-weight: bold;">extern</span> <span style="color: #993333;">char</span> <span style="color: #339933;">**</span> environ<span style="color: #339933;">;</span>
&nbsp;
<span style="color: #993333;">char</span> line<span style="color: #009900;">&#91;</span>LINE_MAX <span style="color: #339933;">+</span> <span style="color: #0000dd;">1</span><span style="color: #009900;">&#93;</span><span style="color: #339933;">;</span>
&nbsp;
<span style="color: #993333;">void</span> parse_command<span style="color: #009900;">&#40;</span><span style="color: #993333;">char</span> <span style="color: #339933;">*</span> cmd<span style="color: #009900;">&#41;</span>
<span style="color: #009900;">&#123;</span>
    <span style="color: #993333;">char</span> <span style="color: #339933;">*</span> res<span style="color: #339933;">;</span>
    size_t cnt <span style="color: #339933;">=</span> <span style="color: #0000dd;">0</span><span style="color: #339933;">;</span>
    <span style="color: #808080; font-style: italic;">/* tokenize the command string by space */</span>
    <span style="color: #b1b100;">while</span> <span style="color: #009900;">&#40;</span><span style="color: #009900;">&#40;</span>res <span style="color: #339933;">=</span> strsep<span style="color: #009900;">&#40;</span><span style="color: #339933;">&amp;</span>cmd<span style="color: #339933;">,</span> <span style="color: #ff0000;">&quot; &quot;</span><span style="color: #009900;">&#41;</span><span style="color: #009900;">&#41;</span> <span style="color: #339933;">!=</span> NULL<span style="color: #009900;">&#41;</span> <span style="color: #009900;">&#123;</span>
        <span style="color: #000066;">printf</span><span style="color: #009900;">&#40;</span><span style="color: #ff0000;">&quot;%s<span style="color: #000099; font-weight: bold;">\n</span>&quot;</span><span style="color: #339933;">,</span> res<span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
        args<span style="color: #009900;">&#91;</span>cnt<span style="color: #339933;">++</span><span style="color: #009900;">&#93;</span> <span style="color: #339933;">=</span> strdup<span style="color: #009900;">&#40;</span>res<span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
    <span style="color: #009900;">&#125;</span>
    args<span style="color: #009900;">&#91;</span>cnt<span style="color: #009900;">&#93;</span> <span style="color: #339933;">=</span> NULL<span style="color: #339933;">;</span>
<span style="color: #009900;">&#125;</span>
&nbsp;
<span style="color: #993333;">void</span> pr_exit<span style="color: #009900;">&#40;</span><span style="color: #993333;">const</span> <span style="color: #993333;">char</span> <span style="color: #339933;">*</span> name<span style="color: #339933;">,</span> <span style="color: #993333;">int</span> status<span style="color: #009900;">&#41;</span>
<span style="color: #009900;">&#123;</span>
    <span style="color: #b1b100;">if</span> <span style="color: #009900;">&#40;</span>WIFEXITED<span style="color: #009900;">&#40;</span>status<span style="color: #009900;">&#41;</span><span style="color: #009900;">&#41;</span> <span style="color: #666666; font-style: italic;">// exit normally</span>
        <span style="color: #b1b100;">return</span><span style="color: #339933;">;</span>
    <span style="color: #b1b100;">else</span> <span style="color: #b1b100;">if</span> <span style="color: #009900;">&#40;</span>WIFSIGNALED<span style="color: #009900;">&#40;</span>status<span style="color: #009900;">&#41;</span><span style="color: #009900;">&#41;</span>
        fprintf<span style="color: #009900;">&#40;</span>stderr<span style="color: #339933;">,</span> <span style="color: #ff0000;">&quot;%s exit abnormally, signal %d caught%s.<span style="color: #000099; font-weight: bold;">\n</span>&quot;</span><span style="color: #339933;">,</span>
                name<span style="color: #339933;">,</span> WTERMSIG<span style="color: #009900;">&#40;</span>status<span style="color: #009900;">&#41;</span><span style="color: #339933;">,</span>
<span style="color: #339933;">#ifdef WCOREDUMP</span>
            WCOREDUMP<span style="color: #009900;">&#40;</span>status<span style="color: #009900;">&#41;</span> <span style="color: #339933;">?</span> <span style="color: #ff0000;">&quot; (core file generated)&quot;</span> <span style="color: #339933;">:</span> <span style="color: #ff0000;">&quot;&quot;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
<span style="color: #339933;">#else</span>
            <span style="color: #ff0000;">&quot;&quot;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
<span style="color: #339933;">#endif</span>
    <span style="color: #b1b100;">else</span> <span style="color: #b1b100;">if</span> <span style="color: #009900;">&#40;</span>WIFSTOPPED<span style="color: #009900;">&#40;</span>status<span style="color: #009900;">&#41;</span><span style="color: #009900;">&#41;</span>
        fprintf<span style="color: #009900;">&#40;</span>stderr<span style="color: #339933;">,</span> <span style="color: #ff0000;">&quot;child stopped, signal %d caught.&quot;</span><span style="color: #339933;">,</span>
                WSTOPSIG<span style="color: #009900;">&#40;</span>status<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> main<span style="color: #009900;">&#40;</span><span style="color: #993333;">int</span> argc<span style="color: #339933;">,</span> <span style="color: #993333;">char</span> <span style="color: #339933;">*</span> argv<span style="color: #009900;">&#91;</span><span style="color: #009900;">&#93;</span><span style="color: #009900;">&#41;</span>
<span style="color: #009900;">&#123;</span>
    <span style="color: #993333;">char</span> c<span style="color: #339933;">;</span>
    size_t idx<span style="color: #339933;">;</span>
    <span style="color: #993333;">int</span> r<span style="color: #339933;">;</span>
    <span style="color: #993333;">int</span> status<span style="color: #339933;">;</span>
&nbsp;
    <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>
        idx <span style="color: #339933;">=</span> <span style="color: #0000dd;">0</span><span style="color: #339933;">;</span>
        bzero<span style="color: #009900;">&#40;</span>line<span style="color: #339933;">,</span> LINE_MAX <span style="color: #339933;">+</span> <span style="color: #0000dd;">1</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
&nbsp;
        c <span style="color: #339933;">=</span> fgetc<span style="color: #009900;">&#40;</span>stdin<span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
        <span style="color: #b1b100;">while</span> <span style="color: #009900;">&#40;</span>c <span style="color: #339933;">&amp;&amp;</span> c <span style="color: #339933;">!=</span> <span style="color: #ff0000;">'<span style="color: #000099; font-weight: bold;">\n</span>'</span><span style="color: #009900;">&#41;</span> <span style="color: #009900;">&#123;</span>
            line<span style="color: #009900;">&#91;</span>idx<span style="color: #339933;">++</span><span style="color: #009900;">&#93;</span> <span style="color: #339933;">=</span> c<span style="color: #339933;">;</span>
            c <span style="color: #339933;">=</span> fgetc<span style="color: #009900;">&#40;</span>stdin<span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
        <span style="color: #009900;">&#125;</span>
&nbsp;
        parse_command<span style="color: #009900;">&#40;</span>line<span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
        r <span style="color: #339933;">=</span> fork<span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span> 
        CHKERR<span style="color: #009900;">&#40;</span>r<span style="color: #339933;">,</span> <span style="color: #ff0000;">&quot;fork&quot;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
        <span style="color: #b1b100;">if</span> <span style="color: #009900;">&#40;</span>r <span style="color: #339933;">==</span> <span style="color: #0000dd;">0</span><span style="color: #009900;">&#41;</span><span style="color: #009900;">&#123;</span>
            r <span style="color: #339933;">=</span> execvp<span style="color: #009900;">&#40;</span>args<span style="color: #009900;">&#91;</span><span style="color: #0000dd;">0</span><span style="color: #009900;">&#93;</span><span style="color: #339933;">,</span> args<span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
            <span style="color: #666666; font-style: italic;">//printf(&quot;ret : %d\n&quot;, r);</span>
            CHKERR<span style="color: #009900;">&#40;</span>r<span style="color: #339933;">,</span> args<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: #009900;">&#125;</span> <span style="color: #b1b100;">else</span> <span style="color: #009900;">&#123;</span>
            wait<span style="color: #009900;">&#40;</span><span style="color: #339933;">&amp;</span>status<span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
            pr_exit<span style="color: #009900;">&#40;</span>args<span style="color: #009900;">&#91;</span><span style="color: #0000dd;">0</span><span style="color: #009900;">&#93;</span><span style="color: #339933;">,</span> status<span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
        <span style="color: #009900;">&#125;</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>

<p>一个简单的命令解释器就这样完成了，下面的工作就是添加后台执行功能，休息一会^ ^</p>

	<h4>Related Post</h4>
	<ul class="st-related-posts">
	<li><a href="http://jackaldire.com/201001/write-your-own-shell-2-background-task/" title="自己动手写Linux Shell（二） —— 支持后台执行 (2010年01月31日)">自己动手写Linux Shell（二） —— 支持后台执行</a> (2)</li>
	<li><a href="http://jackaldire.com/201001/write-your-own-shell-3-io-redirection/" title="自己动手写Linux Shell（三） —— 支持IO重定向 (2010年01月31日)">自己动手写Linux Shell（三） —— 支持IO重定向</a> (1)</li>
	<li><a href="http://jackaldire.com/200905/linux-and-i/" title="我和Linux (2009年05月14日)">我和Linux</a> (0)</li>
	<li><a href="http://jackaldire.com/200906/archlinux-tor-config/" title="在Archlinux上的安装Tor (2009年06月8日)">在Archlinux上的安装Tor</a> (6)</li>
</ul>

]]></content:encoded>
			<wfw:commentRss>http://jackaldire.com/201001/write-your-own-shell-1-a-simple-command-interpreter/feed/</wfw:commentRss>
		<slash:comments>2</slash:comments>
<enclosure url="http://www.86comic.com/music/song/2007/9/14/86comic0914131614181.mp3" length="293170" type="audio/mpeg" />
		</item>
		<item>
		<title>在Archlinux上的安装Tor</title>
		<link>http://jackaldire.com/200906/archlinux-tor-config/</link>
		<comments>http://jackaldire.com/200906/archlinux-tor-config/#comments</comments>
		<pubDate>Mon, 08 Jun 2009 06:59:46 +0000</pubDate>
		<dc:creator>JackalDire</dc:creator>
				<category><![CDATA[Internet]]></category>
		<category><![CDATA[Linux与开源]]></category>
		<category><![CDATA[Archlinux]]></category>
		<category><![CDATA[Linux]]></category>
		<category><![CDATA[代理]]></category>

		<guid isPermaLink="false">http://jackaldire.com/?p=54</guid>
		<description><![CDATA[这几天网络环境急剧恶化，不得不把Tor搬出来 pacman -S tor 发现源里就有, 直接装之。装完以后默认的Socks绑定地址是127.0.0.1 9050, 当然也可以在配置文件里改掉: sudo vim /etc/tor/torrc 大概在20行的位置，还有就是默认情况下tor是作为服务启动的，如果想改成手动启动，把配置文件里的RunAsDaemon的值从1改成0就行了。 Tor装好后就要给浏览器设置代理了，firefox这种支持socks代理的浏览器直接把socks代理设置为 127.0.0.1 9050就行了，配合switch proxy tools这种切换代理的插件会很方便。像opera、konqueror等不支持socks代理的浏览器就需要privoxy来帮忙了： pacman -S privoxy privoxy可以将socks代理转换成http代理。需要改一下配置文件： sudo vim /etc/privoxy/config 把下面一行前面的注释去掉，直接加上也行 forward-socks4a / 127.0.0.1:9050 . 注意行末的点，如果改了tor的绑定地址，上边的地址也要相应的改变。然后设置映射到的http地址： listen-address 127.0.0.1:8118 也可以使用默认值，设置好以后把浏览器的代理地址设置成这个地址就ok了。 总算又看到久违的Twitter页面了~ Related Post 自己动手写Linux Shell（二） —— 支持后台执行 (2) 自己动手写Linux Shell（三） —— 支持IO重定向 (1) 自己动手写Linux Shell（一） —— 简单的命令解释器 (2) 我和Linux (0)]]></description>
			<content:encoded><![CDATA[<p id="fp">这几天网络环境急剧恶化，不得不把Tor搬出来</p>

<div class="wp_syntax"><div class="code"><pre class="bash" style="font-family:monospace;">pacman <span style="color: #660033;">-S</span> tor</pre></div></div>

<p>发现源里就有, 直接装之。装完以后默认的Socks绑定地址是127.0.0.1 9050, 当然也可以在配置文件里改掉:</p>

<div class="wp_syntax"><div class="code"><pre class="bash" style="font-family:monospace;"><span style="color: #c20cb9; font-weight: bold;">sudo</span> <span style="color: #c20cb9; font-weight: bold;">vim</span> <span style="color: #000000; font-weight: bold;">/</span>etc<span style="color: #000000; font-weight: bold;">/</span>tor<span style="color: #000000; font-weight: bold;">/</span>torrc</pre></div></div>

<p>大概在20行的位置，还有就是默认情况下tor是作为服务启动的，如果想改成手动启动，把配置文件里的RunAsDaemon的值从1改成0就行了。</p>
<p style="text-indent:2em">Tor装好后就要给浏览器设置代理了，firefox这种支持socks代理的浏览器直接把socks代理设置为 127.0.0.1 9050就行了，配合switch proxy tools这种切换代理的插件会很方便。像opera、konqueror等不支持socks代理的浏览器就需要privoxy来帮忙了：</p>
<p><span id="more-54"></span></p>

<div class="wp_syntax"><div class="code"><pre class="bash" style="font-family:monospace;">pacman <span style="color: #660033;">-S</span> privoxy</pre></div></div>

<p>privoxy可以将socks代理转换成http代理。需要改一下配置文件：</p>

<div class="wp_syntax"><div class="code"><pre class="bash" style="font-family:monospace;"><span style="color: #c20cb9; font-weight: bold;">sudo</span> <span style="color: #c20cb9; font-weight: bold;">vim</span> <span style="color: #000000; font-weight: bold;">/</span>etc<span style="color: #000000; font-weight: bold;">/</span>privoxy<span style="color: #000000; font-weight: bold;">/</span>config</pre></div></div>

<p>把下面一行前面的注释去掉，直接加上也行</p>

<div class="wp_syntax"><div class="code"><pre class="cpp" style="font-family:monospace;">forward<span style="color: #000040;">-</span>socks4a   <span style="color: #000040;">/</span>               127.0.0.1<span style="color: #008080;">:</span><span style="color: #0000dd;">9050</span> .</pre></div></div>

<p>注意行末的点，如果改了tor的绑定地址，上边的地址也要相应的改变。然后设置映射到的http地址：</p>

<div class="wp_syntax"><div class="code"><pre class="bash" style="font-family:monospace;">listen-address  127.0.0.1:<span style="color: #000000;">8118</span></pre></div></div>

<p>也可以使用默认值，设置好以后把浏览器的代理地址设置成这个地址就ok了。</p>
<p style="text-indent:2em">总算又看到久违的Twitter页面了~</p>

	<h4>Related Post</h4>
	<ul class="st-related-posts">
	<li><a href="http://jackaldire.com/201001/write-your-own-shell-2-background-task/" title="自己动手写Linux Shell（二） —— 支持后台执行 (2010年01月31日)">自己动手写Linux Shell（二） —— 支持后台执行</a> (2)</li>
	<li><a href="http://jackaldire.com/201001/write-your-own-shell-3-io-redirection/" title="自己动手写Linux Shell（三） —— 支持IO重定向 (2010年01月31日)">自己动手写Linux Shell（三） —— 支持IO重定向</a> (1)</li>
	<li><a href="http://jackaldire.com/201001/write-your-own-shell-1-a-simple-command-interpreter/" title="自己动手写Linux Shell（一） —— 简单的命令解释器 (2010年01月29日)">自己动手写Linux Shell（一） —— 简单的命令解释器</a> (2)</li>
	<li><a href="http://jackaldire.com/200905/linux-and-i/" title="我和Linux (2009年05月14日)">我和Linux</a> (0)</li>
</ul>

]]></content:encoded>
			<wfw:commentRss>http://jackaldire.com/200906/archlinux-tor-config/feed/</wfw:commentRss>
		<slash:comments>6</slash:comments>
		</item>
		<item>
		<title>我和Linux</title>
		<link>http://jackaldire.com/200905/linux-and-i/</link>
		<comments>http://jackaldire.com/200905/linux-and-i/#comments</comments>
		<pubDate>Thu, 14 May 2009 00:25:17 +0000</pubDate>
		<dc:creator>JackalDire</dc:creator>
				<category><![CDATA[Linux与开源]]></category>
		<category><![CDATA[Linux]]></category>

		<guid isPermaLink="false">http://jackaldire.com/?p=46</guid>
		<description><![CDATA[响应CasparAnt的号召，写了一下自己玩Linux的过程 老早我爸就开始玩Linux，不过没有装X，所以也就望而却步。直到大一遇到班上某牛S（现在投身ACM去了）玩Linux，又在宏福听了一场开源的讲座，兴趣大发，开始折腾。 我装Linux的过程那是相当曲折，Ubuntu7.04装完Grub引导出问题，那时候还不知道grub为何物，Google了N久发现ubuntu自带Grub和原来Vista Loader的Grub4Dos冲突，索性用Vista的安装盘把Vista Loader卸了，再把ubuntu重装了一遍（那时候还不会修复Grub），黑屏…又瞎折腾了几天，无果，就先扔一边去了。 过了两周，S牛不知从哪淘来一盒FC6，随便试了一下，竟然能进X了，第一次看到Gnome的桌面，那叫一个激动啊。兴奋了半天，发现缺各种驱动：显卡、声卡、网卡…没法上网、没法更新，除了玩玩小游戏，啥都做不了…于是乎又扔一边去了。 到了11月份，从遥远的波兰寄来的ubuntu 7.10的光盘到了，赶快装上，顺利进入X，以太网卡也能用了，赶紧插上根网线更新。还记得一条apt-get我至少Google了四五次才记住。接着就是解决无线网卡驱动的问题，Google到ndiswrapper，又折腾了一周。然后尝试各种软件，无休止的折腾。 总结一下，其实Linux主要需要折腾的就是下面几样： 1. 安装和驱动（现在的发行版硬件支持都很好了，安装一般没什么大问题了） 2. 中文支持和编码（包括中文显示、中文输入法、文件编码（mp3 tag）） 3. 寻找各种软件并进行配置（典型的就是vim，不改配置文件基本不能用） 4. wine和虚拟机 5. Shell命令（在解决各种问题中少不了和shell打交道，学习shell命令是顺带的） 6. 其他各种小问题（比如什么触摸板用不了、声音太小、分区自动挂载等等） 其实，直到去年下半年我才把Linux当作桌面环境用。原因是太懒，很多东西懒得去学。比如说写Makefile、用gdb调试程序、记shell命令。但是Linux对我来说具有无比的魅力。他开放而且富有活力：刚装完ubuntu7.10的一个月内至少更新了4个内核版本，导致我Grub菜单都要翻页了（但是还不知道怎么删。。），其他的更新更不必说。而Vista仅有几个安全补丁，标着KBXXXXXX，谁也不知道究竟补了啥。可以说用1天Linux学到的知识比用一年Windows还要多，这就是Linux的价值所在。 对于真正想玩Linux的人来说，ubuntu只是一个起步而已。寒假的时候格了硬盘重新分区，在选发行版的时候花了不少功夫。说实话我是实在不想用ubuntu了，在我的笔记本上，ubuntu开Firefox需要20s，amarok 半分钟，eclipse一分钟，浏览网页滚屏时老卡，鼠标点击响应也很慢。于是乎从fedora10、opensuse11到mandriva2009都试了一遍，最终选择了Archlinux。 Arch没有官方的LiveCD，只能用一个200M的core iso包安装，这让我发现了ubuntu以外的另一个世界。自己选择每一个包，在命令行下修改配置文件设置locale连上网、在光秃秃的base system上把整个系统包括X搭起来，才发现原来ubuntu安装的时候做了那么多事，同时装了那么多没有用的包。一遍装下来，对Linux系统又有了更准确的认识，而且系统也比以前好用了N倍（等有空写篇软文推荐一下Archlinux，实用主义者的首选）。 现在我对系统基本上是没需求了，只是迫于网银的问题还是得装个XP在虚拟机里。 对我来说玩linux是一个愉快的事，如果只是为了找工作来硬着头皮学，那肯定会很累。当你爱上Linux，Linux就会爱你~ 呼，这总有一千字了吧（真佩服我自己闲扯的能力） Related Post 自己动手写Linux Shell（二） —— 支持后台执行 (2) 自己动手写Linux Shell（三） —— 支持IO重定向 (1) 自己动手写Linux Shell（一） —— 简单的命令解释器 (2) 在Archlinux上的安装Tor (6)]]></description>
			<content:encoded><![CDATA[<p id="fp">响应CasparAnt的号召，写了一下自己玩Linux的过程</p>
<p style="text-indent:2em">老早我爸就开始玩Linux，不过没有装X，所以也就望而却步。直到大一遇到班上某牛S（现在投身ACM去了）玩Linux，又在宏福听了一场开源的讲座，兴趣大发，开始折腾。</p>
<p style="text-indent:2em">我装Linux的过程那是相当曲折，Ubuntu7.04装完Grub引导出问题，那时候还不知道grub为何物，Google了N久发现ubuntu自带Grub和原来Vista Loader的Grub4Dos冲突，索性用Vista的安装盘把Vista Loader卸了，再把ubuntu重装了一遍（那时候还不会修复Grub），黑屏…又瞎折腾了几天，无果，就先扔一边去了。</p>
<p style="text-indent:2em">过了两周，S牛不知从哪淘来一盒FC6，随便试了一下，竟然能进X了，第一次看到Gnome的桌面，那叫一个激动啊。兴奋了半天，发现缺各种驱动：显卡、声卡、网卡…没法上网、没法更新，除了玩玩小游戏，啥都做不了…于是乎又扔一边去了。</p>
<p style="text-indent:2em">到了11月份，从遥远的波兰寄来的ubuntu 7.10的光盘到了，赶快装上，顺利进入X，以太网卡也能用了，赶紧插上根网线更新。还记得一条apt-get我至少Google了四五次才记住。接着就是解决无线网卡驱动的问题，Google到ndiswrapper，又折腾了一周。然后尝试各种软件，无休止的折腾。</p>
<p><span id="more-46"></span></p>
<p>总结一下，其实Linux主要需要折腾的就是下面几样：<br />
1. 安装和驱动（现在的发行版硬件支持都很好了，安装一般没什么大问题了）<br />
2. 中文支持和编码（包括中文显示、中文输入法、文件编码（mp3 tag））<br />
3. 寻找各种软件并进行配置（典型的就是vim，不改配置文件基本不能用）<br />
4. wine和虚拟机<br />
5. Shell命令（在解决各种问题中少不了和shell打交道，学习shell命令是顺带的）<br />
6. 其他各种小问题（比如什么触摸板用不了、声音太小、分区自动挂载等等）</p>
<p style="text-indent:2em">其实，直到去年下半年我才把Linux当作桌面环境用。原因是太懒，很多东西懒得去学。比如说写Makefile、用gdb调试程序、记shell命令。但是Linux对我来说具有无比的魅力。他开放而且富有活力：刚装完ubuntu7.10的一个月内至少更新了4个内核版本，导致我Grub菜单都要翻页了（但是还不知道怎么删。。），其他的更新更不必说。而Vista仅有几个安全补丁，标着KBXXXXXX，谁也不知道究竟补了啥。可以说用1天Linux学到的知识比用一年Windows还要多，这就是Linux的价值所在。</p>
<p style="text-indent:2em">对于真正想玩Linux的人来说，ubuntu只是一个起步而已。寒假的时候格了硬盘重新分区，在选发行版的时候花了不少功夫。说实话我是实在不想用ubuntu了，在我的笔记本上，ubuntu开Firefox需要20s，amarok 半分钟，eclipse一分钟，浏览网页滚屏时老卡，鼠标点击响应也很慢。于是乎从fedora10、opensuse11到mandriva2009都试了一遍，最终选择了Archlinux。 Arch没有官方的LiveCD，只能用一个200M的core iso包安装，这让我发现了ubuntu以外的另一个世界。自己选择每一个包，在命令行下修改配置文件设置locale连上网、在光秃秃的base system上把整个系统包括X搭起来，才发现原来ubuntu安装的时候做了那么多事，同时装了那么多没有用的包。一遍装下来，对Linux系统又有了更准确的认识，而且系统也比以前好用了N倍（等有空写篇软文推荐一下Archlinux，实用主义者的首选）。</p>
<p style="text-indent:2em">现在我对系统基本上是没需求了，只是迫于网银的问题还是得装个XP在虚拟机里。</p>
<p style="text-indent:2em">对我来说玩linux是一个愉快的事，如果只是为了找工作来硬着头皮学，那肯定会很累。当你爱上Linux，Linux就会爱你~</p>
<p>呼，这总有一千字了吧（真佩服我自己闲扯的能力）</p>

	<h4>Related Post</h4>
	<ul class="st-related-posts">
	<li><a href="http://jackaldire.com/201001/write-your-own-shell-2-background-task/" title="自己动手写Linux Shell（二） —— 支持后台执行 (2010年01月31日)">自己动手写Linux Shell（二） —— 支持后台执行</a> (2)</li>
	<li><a href="http://jackaldire.com/201001/write-your-own-shell-3-io-redirection/" title="自己动手写Linux Shell（三） —— 支持IO重定向 (2010年01月31日)">自己动手写Linux Shell（三） —— 支持IO重定向</a> (1)</li>
	<li><a href="http://jackaldire.com/201001/write-your-own-shell-1-a-simple-command-interpreter/" title="自己动手写Linux Shell（一） —— 简单的命令解释器 (2010年01月29日)">自己动手写Linux Shell（一） —— 简单的命令解释器</a> (2)</li>
	<li><a href="http://jackaldire.com/200906/archlinux-tor-config/" title="在Archlinux上的安装Tor (2009年06月8日)">在Archlinux上的安装Tor</a> (6)</li>
</ul>

]]></content:encoded>
			<wfw:commentRss>http://jackaldire.com/200905/linux-and-i/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
	</channel>
</rss>
