<?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>IGI&#039;s Blog</title>
	<atom:link href="http://www.igigo.net/feed" rel="self" type="application/rss+xml" />
	<link>http://www.igigo.net</link>
	<description></description>
	<lastBuildDate>Fri, 09 Dec 2011 04:19:40 +0000</lastBuildDate>
	<language>en</language>
	<sy:updatePeriod>hourly</sy:updatePeriod>
	<sy:updateFrequency>1</sy:updateFrequency>
	<generator>http://wordpress.org/?v=3.0.4</generator>
	
<!-- Start Of Script Generated By WP-PostViews Plus -->
<script type='text/javascript' src='http://www.igigo.net/wp-includes/js/jquery/jquery.js?ver=1.4.2'></script>
<script type="text/javascript">
/* <![CDATA[ */
/* ]]> */
</script>
<!-- End Of Script Generated By WP-PostViews Plus -->
	<item>
		<title>Debian在线升级dell服务器BIOS</title>
		<link>http://www.igigo.net/archives/192</link>
		<comments>http://www.igigo.net/archives/192#comments</comments>
		<pubDate>Fri, 09 Dec 2011 04:15:38 +0000</pubDate>
		<dc:creator>igi</dc:creator>
				<category><![CDATA[小砸碎]]></category>
		<category><![CDATA[debian]]></category>
		<category><![CDATA[dell]]></category>

		<guid isPermaLink="false">http://www.igigo.net/?p=192</guid>
		<description><![CDATA[Debian在线升级dell服务器BIOS]]></description>
			<content:encoded><![CDATA[<p>  1. 安装libsmbios软件包:<br />
    * 工具主页及文档: <a href="http://linux.dell.com/libsmbios/main/index.html">http://linux.dell.com/libsmbios/main/index.html</a></p>
<pre class="brush: bash; title: ;">
aptitude update
aptitude install libsmbios-bin
</pre>
<p>  2. 查看当前BIOS版本及编号: 需要记住 System ID 及 BIOS Version 的值</p>
<pre class="brush: bash; title: ;">
hostname:/home/igi# getSystemId
Libsmbios:    2.0.3
System ID:    0x01B3
Service Tag:  XXXXXXX
Express Service Code: XXXXXXXXX
Product Name: PowerEdge 1950
BIOS Version: 2.2.6
Vendor:       Dell Inc.
Is Dell:      1
</pre>
<p>  3. 下载对应BIOS的最新版本: <a href="http://linux.dell.com/repo/firmware/bios-hdrs/">http://linux.dell.com/repo/firmware/bios-hdrs/</a><br />
    * url格式: system_bios_ven_0x1028_dev_SYSTEM_ID_version_BIOS_VERSION<br />
以 System ID为 0x01B3， BIOS Version为 2.2.6 为例<br />
则需要找到: http://linux.dell.com/repo/firmware/bios-hdrs/ 下<br />
对应的 system_bios_ven_0x1028_dev_0x01b3_version_x.x.x (x.x.x需要大于当前版本，如没有特别需求，使用最新版本即可)<br />
对应的url为: http://linux.dell.com/repo/firmware/bios-hdrs/system_bios_ven_0x1028_dev_0x01b3_version_x.x.x/bios.hdr</p>
<pre class="brush: bash; title: ;">
wget http://linux.dell.com/repo/firmware/bios-hdrs/system_bios_ven_0x1028_dev_0x01b3_version_x.x.x/bios.hdr
</pre>
<p>  4. 加载升级所需内核模块dell_rbu</p>
<pre class="brush: bash; title: ;">
modprobe dell_rbu
#确认模块已加载
lsmod | grep dell_rbu
dell_rbu                6800  0
firmware_class          7584  2 dell_rbu,bnx2
</pre>
<p>  注意： 默认的debian内核已经有此模块，如果是其他内核，需要编译内核时做调整，推荐编译成模块</p>
<pre class="brush: bash; title: ;">
Firmware Drivers ---&gt;
&lt;M&gt; BIOS update support for DELL systems via sysfs
</pre>
<p>  5. 升级BIOS</p>
<pre class="brush: bash; title: ;">
dellBiosUpdate -u -f bios.hdr
</pre>
<p>输出示例</p>
<pre class="brush: bash; title: ;">
dellBiosUpdate -u -f bios.hdr

WARNING: packet updates are not fully tested yet for packet modes v0/v2.
         We recommend that only monlithic updates be used at this point.
         You should only use packet mode on v0/v2 systems if you know what you are
         doing (for example, testing.)

Forcing MONOLITHIC mode...

Supported RBU type for this system: (MONOLITHIC, PACKET)
Using RBU v2 driver. Initializing Driver.
Setting RBU type in v2 driver to: MONOLITHIC (FORCED)
Prep driver for data load.
Writing RBU data (4096bytes/dot): .................................................
Notify driver data is finished.
Activate CMOS bit to notify BIOS that update is ready on next boot.
Update staged sucessfully. BIOS update will occur on next reboot.
</pre>
<p>  6. 重启系统<br />
  7. 确认BIOS版本号</p>
<pre class="brush: bash; title: ;">
hostname:/home/igi# getSystemId
Libsmbios:    2.0.3
System ID:    0x01B3
Service Tag:  XXXXXXX
Express Service Code: XXXXXXXXXX
Product Name: PowerEdge 1950
BIOS Version: 2.7.0
Vendor:       Dell Inc.
Is Dell:      1
</pre>
]]></content:encoded>
			<wfw:commentRss>http://www.igigo.net/archives/192/feed</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Dash与Bash的语法区别</title>
		<link>http://www.igigo.net/archives/169</link>
		<comments>http://www.igigo.net/archives/169#comments</comments>
		<pubDate>Sat, 19 Feb 2011 06:25:36 +0000</pubDate>
		<dc:creator>igi</dc:creator>
				<category><![CDATA[shell]]></category>
		<category><![CDATA[bash]]></category>
		<category><![CDATA[dash]]></category>

		<guid isPermaLink="false">http://www.igigo.net/?p=169</guid>
		<description><![CDATA[如今Debian和Ubuntu中，/bin/sh默认已经指向dash，这是一个不同于bash的shell，它主要是为了执行脚本而出现，而不是交互，它速度更快，但功能相比bash要少很多，语法严格遵守POSIX标准，下面简要列举下从bash迁移到dash一般需要注意的问题 1.定义函数 bash: function在bash中为关键字 igi@gentoo ~ $ foo(){ echo $0;} igi@gentoo ~ $ foo /bin/bash igi@gentoo ~ $ function foo2(){ echo $0;} igi@gentoo ~ $ foo2 /bin/bash dash: dash中没有function这个关键字 $ foo(){ echo $0;} $ foo dash $ function foo2(){ echo $0;} dash: Syntax error: &#34;(&#34; unexpected 2.select var in list; do command; done bash:支持 igi@gentoo [...]]]></description>
			<content:encoded><![CDATA[<p>如今Debian和Ubuntu中，/bin/sh默认已经指向dash，这是一个不同于bash的shell，它主要是为了执行脚本而出现，而不是交互，它速度更快，但功能相比bash要少很多，语法严格遵守POSIX标准，下面简要列举下从bash迁移到dash一般需要注意的问题</p>
<h1>1.定义函数</h1>
<p>bash: function在bash中为关键字</p>
<pre class="brush: bash; title: ;">
igi@gentoo ~ $ foo(){ echo $0;}
igi@gentoo ~ $ foo
/bin/bash
igi@gentoo ~ $ function foo2(){ echo $0;}
igi@gentoo ~ $ foo2
/bin/bash
</pre>
<p>dash: dash中没有function这个关键字                                                                              </p>
<pre class="brush: bash; title: ;">
$ foo(){ echo $0;}
$ foo
dash
$ function foo2(){ echo $0;}
dash: Syntax error: &quot;(&quot; unexpected
</pre>
<h1>2.select var in list; do command; done</h1>
<p>bash:支持</p>
<pre class="brush: bash; title: ;">
igi@gentoo ~ $ select input in A B
&gt; do
&gt;   case $input in
&gt;     A)
&gt;        echo 'Input:A'
&gt;        break
&gt;        ;;
&gt;     B)
&gt;        echo 'Input:B'
&gt;        break
&gt;        ;;
&gt;   esac
&gt; done
1) A
2) B
#? 1
Input:A
igi@gentoo ~ $ echo $0
/bin/bash
</pre>
<p>dash:不支持, 替代方法:采用while+read+case来实现</p>
<pre class="brush: bash; title: ;">
menu(){ echo -n &quot;1)A;\n2)B\n&gt;&quot;;}
menu
while read input
do
    case $input in
      1)
         echo 'A'
         break
         ;;
      2)
         echo 'B'
         break
         ;;
      *)
         menu
         continue
         ;;
    esac
done
</pre>
<h1>3. echo {0..10}</h1>
<p>bash:支持{n..m}展开</p>
<pre class="brush: bash; title: ;">
igi@gentoo ~ $ echo $0
/bin/bash
igi@gentoo ~ $ echo {0..10}
0 1 2 3 4 5 6 7 8 9 10
</pre>
<p>dash:不支持，替代方法, 采用seq外部命令</p>
<pre class="brush: bash; title: ;">
$ echo $0
dash
$ echo {0..10}
{0..10}
$ echo `seq 0 10`
0 1 2 3 4 5 6 7 8 9 10
</pre>
<h1>4. here string</h1>
<p>bash:支持here string</p>
<pre class="brush: bash; title: ;">
igi@gentoo ~ $ cat &lt;&lt;&lt;&quot;string&quot;
string
igi@gentoo ~ $ echo $0
/bin/bash
</pre>
<p>dash:不支持, 替代方法:可采用here documents</p>
<pre class="brush: bash; title: ;">
$ echo $0
dash
$ cat &lt;&lt;&lt;&quot;string&quot;
dash: Syntax error: redirection unexpected
$ cat &lt;&lt;EOF
&gt; string
&gt; EOF
string
</pre>
<h1>5. >&#038;word重定向标准输出和标准错误</h1>
<p>bash: 当word为非数字时，>&#038;word变成重定向标准错误和标准输出到文件word, 常见用法>&#038;/dev/null</p>
<pre class="brush: bash; title: ;">
igi@gentoo ~/test $ ls
a
igi@gentoo ~/test $ ls a b
ls: cannot access b: No such file or directory
a
igi@gentoo ~/test $ ls a b &gt;&amp;/dev/null
igi@gentoo ~/test $ ls a b &gt;/dev/null 2&gt;&amp;1
igi@gentoo ~/test $ echo $0
/bin/bash
</pre>
<p>dash: >&#038;word, word不支持非数字, 替代方法: >word 2>&#038;1; 常见用法 >/dev/null 2>&#038;1</p>
<pre class="brush: bash; title: ;">
$ echo $0
dash
$ ls a
a
$ ls a b
ls: cannot access b: No such file or directory
a
$ ls a b &gt;&amp;/dev/null
dash: Syntax error: Bad fd number
$ ls a b &gt;/dev/null 2&gt;&amp;1
$
</pre>
<h1>6. 数组</h1>
<p>bash: 支持数组, bash4支持关联数组</p>
<pre class="brush: bash; title: ;">
igi@gentoo ~/test $ echo $0
/bin/bash
igi@gentoo ~/test $ array=( a b c )
igi@gentoo ~/test $ echo ${array[2]}
c
</pre>
<p>dash: 不支持数组，替代方法, 采用变量名+序号来实现类似的效果</p>
<pre class="brush: bash; title: ;">
$ for i in a b c
&gt; do
&gt; id=$((${id:=-1}+1))
&gt; eval array_$id=$i
&gt; done
$ echo ${array_1}
b
$ echo $0
dash
</pre>
<p>很蛋疼的方法，非不得以不建议这么用</p>
<h1>7. 子字符串扩展</h1>
<p>bash: 支持${parameter:offset:length},${parameter:offset}</p>
<pre class="brush: bash; title: ;">
igi@gentoo ~/test $ string='hello'
igi@gentoo ~/test $ echo ${string:1:3}
ell
igi@gentoo ~/test $ echo ${string:1}
ello
igi@gentoo ~/test $ echo $0
/bin/bash
</pre>
<p>dash: 不支持， 替代方法:采用expr或cut外部命令代替</p>
<pre class="brush: bash; title: ;">
$ string='hello'
$ expr substr &quot;$string&quot; 2 3
ell
$ echo &quot;$string&quot; | cut -c2-4
ell
$ expr substr &quot;$string&quot; 2 &quot;${#string}&quot;
ello
$ echo &quot;$string&quot; | cut -c2-
ello
$ echo $0
dash
$
</pre>
<h1>8. 大小写转换</h1>
<p>bash: 支持${parameter^pattern},${parameter^^pattern},${parameter,pattern},${parameter,,pattern}</p>
<pre class="brush: bash; title: ;">
igi@gentoo ~/test $ string=&quot;abcABC&quot;
igi@gentoo ~/test $ echo ${string^^}
ABCABC
igi@gentoo ~/test $ echo ${string,,}
abcabc
igi@gentoo ~/test $ echo ${string^^b}
aBcABC
igi@gentoo ~/test $ echo $0
/bin/bash
</pre>
<p>dash: 不支持，替代方法:采用tr/sed/awk等外部命令转换</p>
<pre class="brush: bash; title: ;">
$ string='abcABC'
$ echo &quot;$string&quot; | tr '[a-z]' '[A-Z]'
ABCABC
$ echo &quot;$string&quot; | tr '[A-Z]' '[a-z]'
abcabc
$ echo &quot;$string&quot; | sed 's/b/\U&amp;/g'
aBcABC
$
</pre>
<h1>9. 进程替换<(command), >(command)</h1>
<p>bash: 支持进程替换</p>
<pre class="brush: bash; title: ;">
igi@gentoo ~ $ diff &lt;(seq 3) &lt;(seq 4)
3a4
&gt; 4
igi@gentoo ~ $ echo $0
/bin/bash
</pre>
<p>dash: 不支持, 替代方法, 通过临时文件中转</p>
<pre class="brush: bash; title: ;">
$ diff &lt;(seq 3) &lt;(seq 4)
dash: Syntax error: &quot;(&quot; unexpected
$ seq 3 &gt;tmp1
$ seq 4 &gt;tmp2
$ diff tmp1 tmp2
3a4
&gt; 4
$ echo $0
dash
$
</pre>
<h1>10. [ string1 = string2 ] 和 [ string1 == string2 ]</h1>
<p>bash: 支持两者</p>
<pre class="brush: bash; title: ;">
igi@gentoo ~ $ [ 'a' = 'a' ] &amp;&amp; echo 'equal'
equal
igi@gentoo ~ $ [ 'a' == 'a' ] &amp;&amp; echo 'equal'
equal
igi@gentoo ~ $ echo $0
/bin/bash
</pre>
<p>dash: 只支持=</p>
<pre class="brush: bash; title: ;">
$ [ 'a' = 'a' ] &amp;&amp; echo 'equal'
equal
$ [ 'a' == 'a' ] &amp;&amp; echo 'equal'
[: 2: a: unexpected operator
$ echo $0
dash
$
</pre>
<h1>11. [[ 加强版test</h1>
<p>bash: 支持[[ ]], 可实现正则匹配等强大功能</p>
<pre class="brush: bash; title: ;">
igi@gentoo ~ $ [[ 'xyz123' =~ xyz[0-9]+ ]] &amp;&amp; echo 'equal'
equal
igi@gentoo ~ $ echo $0
/bin/bash
</pre>
<p>dash: 不支持[[ ]], 替代方法，采用外部命令</p>
<pre class="brush: bash; title: ;">
$ [[ 'xyz123' =~ xyz[0-9]+ ]] &amp;&amp; echo 'equal'
dash: [[: not found
$ echo 'xyz123' | grep -q 'xyz[0-9]\+' &amp;&amp; echo 'equal'
equal
$ echo $0
dash
$
</pre>
<h1>12. for (( expr1 ; expr2 ; expr3 )) ; do list ; done</h1>
<p>bash: 支持C语言格式的for循环 </p>
<pre class="brush: bash; title: ;">
igi@gentoo ~ $ for((i=0;i&lt;=3;i++));do echo &quot;$i&quot;;done
0
1
2
3
igi@gentoo ~ $ echo $0
/bin/bash
</pre>
<p>dash: 不支持该格式的for, 替代方法，用while+$((expression))实现</p>
<pre class="brush: bash; title: ;">
$ i=0
$ while [ &quot;$i&quot; -le 3 ]
&gt; do
&gt; echo &quot;$i&quot;
&gt; i=$((i+1))
&gt; done
0
1
2
3
$ echo $0
dash
$
</pre>
<h1>13. let命令和((expression))</h1>
<p>bash: 有内置命令let, 也支持((expression))方式</p>
<pre class="brush: bash; title: ;">
igi@gentoo ~ $ i=0
igi@gentoo ~ $ let i++
igi@gentoo ~ $ echo $i
1
igi@gentoo ~ $ ((i++))
igi@gentoo ~ $ echo $i
2
igi@gentoo ~ $ echo $0
/bin/bash
</pre>
<p>dash: 不支持，替代方法，采用$((expression))或者外部命令做计算</p>
<pre class="brush: bash; title: ;">
$ i=0
$ i=$((i+1))
$ echo $i
1
$ echo $0
dash
$
</pre>
<h1>14. $((expression))</h1>
<p>bash: 支持id++,id--,++id,--id这样到表达式</p>
<pre class="brush: bash; title: ;">
igi@gentoo ~ $ i=0
igi@gentoo ~ $ echo $((i++))
0
igi@gentoo ~ $ echo $i
1
igi@gentoo ~ $ echo $((++i))
2
igi@gentoo ~ $ echo $i
2
igi@gentoo ~ $ echo $0
/bin/bash
</pre>
<p>dash: 不支持++,--, 替代方法:id+=1,id-=1, id=id+1,id=id-1</p>
<pre class="brush: bash; title: ;">
$ i=0
$ echo $((i++))
dash: arithmetic expression: expecting primary: &quot;i++&quot;
$ echo $i;i=$((i+1))
0
$ echo $i
1
$ echo $((i+=1))
2
$ echo $i
2
$ echo $0
dash
$
</pre>
<p>以上列举的都是常见容易混淆的地方，更多区别可以查看manpage</p>
]]></content:encoded>
			<wfw:commentRss>http://www.igigo.net/archives/169/feed</wfw:commentRss>
		<slash:comments>5</slash:comments>
		</item>
		<item>
		<title>Bash星号的那点事</title>
		<link>http://www.igigo.net/archives/164</link>
		<comments>http://www.igigo.net/archives/164#comments</comments>
		<pubDate>Mon, 14 Feb 2011 08:12:00 +0000</pubDate>
		<dc:creator>igi</dc:creator>
				<category><![CDATA[bash那点事]]></category>
		<category><![CDATA[shell]]></category>
		<category><![CDATA[bash]]></category>
		<category><![CDATA[star]]></category>

		<guid isPermaLink="false">http://www.igigo.net/?p=164</guid>
		<description><![CDATA[星号，这是个神奇的符号，在bash中，星号也充满魔力，它是通配符之一。 简单列举下星号的功能，被称为万能字符不是没有理由的. 1)文件名匹配: 默认情况下匹配所有非隐藏文件(即非.开头到文件) 2)字符串匹配: 匹配任意字符 3)$*匹配所有参数 4)${array[*]}，表示了所有数组元素 5)乘法运算 6)** 冪运算 7)** bash4中提供的更牛b的文件名匹配，包含递归功能 接下我们来见识下它强大到魔力： 1)文件名匹配: igi@gentoo ~ $ ls a b c d igi@gentoo ~ $ ls -A a b c d .t .u .v .w .x .y igi@gentoo ~ $ echo * a b c d 我们可以看到，*号匹配了所有非隐藏文件名，如果要匹配所有文件名(包括隐藏文件)，可以打开dotglob开关 igi@gentoo ~ $ ls -A a b [...]]]></description>
			<content:encoded><![CDATA[<p>    星号，这是个神奇的符号，在bash中，星号也充满魔力，它是通配符之一。<br />
    简单列举下星号的功能，被称为万能字符不是没有理由的.<br />
        1)文件名匹配: 默认情况下匹配所有非隐藏文件(即非.开头到文件)<br />
        2)字符串匹配: 匹配任意字符<br />
        3)$*匹配所有参数<br />
        4)${array[*]}，表示了所有数组元素<br />
        5)乘法运算<br />
        6)** 冪运算<br />
        7)** bash4中提供的更牛b的文件名匹配，包含递归功能<br />
    接下我们来见识下它强大到魔力：<br />
1)文件名匹配:</p>
<pre class="brush: bash; title: ;">
igi@gentoo ~ $ ls
a  b  c  d
igi@gentoo ~ $ ls -A
a  b  c  d  .t  .u  .v  .w  .x  .y
igi@gentoo ~ $ echo *
a b c d
</pre>
<p>我们可以看到，*号匹配了所有非隐藏文件名，如果要匹配所有文件名(包括隐藏文件)，可以打开dotglob开关                                                                                        </p>
<pre class="brush: bash; title: ;">
igi@gentoo ~ $ ls -A
a  b  c  d  .t  .u  .v  .w  .x  .y
igi@gentoo ~ $ echo *
a b c d
igi@gentoo ~ $ shopt -s dotglob
igi@gentoo ~ $ echo *
a b c d .t .u .v .w .x .y
</pre>
<p>如果只是匹配隐藏文件呢？可别想得太复杂了哦                                                                                                                                              </p>
<pre class="brush: bash; title: ;">
igi@gentoo ~ $ ls -a
.  ..  a  b  c  d  .t  .u  .v  .w  .x  .y
igi@gentoo ~ $ echo .*
. .. .t .u .v .w .x .y
</pre>
<p>需要注意到是，.*会把当前目录下到.目录和..目录也匹配进去</p>
<p>2)字符串匹配:这一般用在case语句、字符串截取中</p>
<pre class="brush: bash; title: ;">
igi@gentoo ~ $ case &quot;abc&quot; in
&gt; a)
&gt;   echo 'a'
&gt;   ;;
&gt; a*)
&gt;   echo 'a*'
&gt;   ;;
&gt; esac
a*
igi@gentoo ~ $ var='abc123'
igi@gentoo ~ $ echo &quot;${var%c*}&quot;
ab
</pre>
<p>可以看到*号匹配了任意字符，在这里，先提醒一下，这里用的是模式匹配，而不是正则(正则与模式匹配不同，以后到文章中，将会仔细对比这两者到区别)</p>
<p>3)$*表示所有参数</p>
<pre class="brush: bash; title: ;">
igi@gentoo ~ $ foo() { for i in $*; do echo &quot;var: $i&quot;; done; }
igi@gentoo ~ $ foo a b &quot;c cc&quot;
var: a
var: b
var: c
var: cc
igi@gentoo ~ $ foo() { for i in &quot;$*&quot;; do echo &quot;var: $i&quot;; done; }
igi@gentoo ~ $ IFS=&quot;|&quot; foo a b &quot;c cc&quot;
var: a|b|c cc
</pre>
<p>最后到例子中，我设置了新到IFS变量，只是为了让大家更清晰到看到，bash是如何对待&#8221;$*&#8221;的，bash用IFS变量，把所有参数拼成一个字符串，这就是&#8221;$*&#8221;<br />
这里先说下$@和&#8221;$@&#8221;，在没有用双引号包围时，$@和$*一样表示了 $1 $2 $3 &#8230;<br />
而&#8221;$@&#8221; 则与&#8221;$*&#8221;不同，&#8221;$@&#8221;表示了 &#8220;$1&#8243; &#8220;$2&#8243; &#8220;$3&#8243; &#8230;(注意这里到双引号，双引号中的字符串是一个整体)，似乎有点不明白，看看下面的例子</p>
<pre class="brush: bash; title: ;">
igi@gentoo ~ $ foo() { for i in $*;do echo &quot;var: $i&quot;;done;}
igi@gentoo ~ $ foo a b &quot;c cc&quot;
var: a
var: b
var: c
var: cc
igi@gentoo ~ $ foo() { for i in $@;do echo &quot;var: $i&quot;;done;}
igi@gentoo ~ $ foo a b &quot;c cc&quot;
var: a
var: b
var: c
var: cc
igi@gentoo ~ $ foo() { for i in &quot;$*&quot;;do echo &quot;var: $i&quot;;done;}
igi@gentoo ~ $ foo a b &quot;c cc&quot;
var: a b c cc
igi@gentoo ~ $ foo() { for i in &quot;$@&quot;;do echo &quot;var: $i&quot;;done;}
igi@gentoo ~ $ foo a b &quot;c cc&quot;
var: a
var: b
var: c cc
</pre>
<p>4)${array[*]}表示所有数组元素</p>
<pre class="brush: bash; title: ;">
igi@gentoo ~ $ array=( a b &quot;c cc&quot; )
igi@gentoo ~ $ for i in ${array[*]};do echo &quot;array: $i&quot;; done
array: a
array: b
array: c
array: cc
igi@gentoo ~ $ for i in ${array[@]};do echo &quot;array: $i&quot;; done
array: a
array: b
array: c
array: cc
igi@gentoo ~ $ for i in &quot;${array[*]}&quot;;do echo &quot;array: $i&quot;; done
array: a b c cc
igi@gentoo ~ $ for i in &quot;${array[@]}&quot;;do echo &quot;array: $i&quot;; done
array: a
array: b
array: c cc
</pre>
<p>细心的你应该不难看出，这和$*是一样的，我就不罗嗦了。</p>
<p>5、6)*号乘法运算, **冪运算</p>
<pre class="brush: bash; title: ;">
igi@gentoo ~ $ ((num=3*4))
igi@gentoo ~ $ echo $num
12
igi@gentoo ~ $ let num=3*3
igi@gentoo ~ $ echo $num
9
igi@gentoo ~ $ ((num=2**4))
igi@gentoo ~ $ echo $num
16
igi@gentoo ~ $ let num=2**2
igi@gentoo ~ $ echo $num
4
</pre>
<p>乘法运算和冪运算应该很容易理解吧。</p>
<p>7)bash4中更牛B的通配符**</p>
<pre class="brush: bash; title: ;">
igi@gentoo ~/test $ tree
.
├── a
│   ├── 1
│   ├── 2
│   ├── 3
│   ├── 4
│   └── 5
└── c
    ├── 2.txt
    ├── 3.txt
    ├── 4.txt
    └── dir

3 directories, 8 files
igi@gentoo ~/test $ shopt globstar
globstar        off
igi@gentoo ~/test $ echo **
a c
igi@gentoo ~/test $ echo **/
a/ c/
igi@gentoo ~/test $ echo *
a c
igi@gentoo ~/test $ echo **
a c
igi@gentoo ~/test $ echo */
a/ c/
igi@gentoo ~/test $ echo **/
a/ c/
</pre>
<p>默认情况下，globstar是关闭的，也就是**与*是一样的，我们来看看打开globstar后是怎么个牛b法？</p>
<pre class="brush: bash; title: ;">
igi@gentoo ~/test $ tree
.
├── a
│   ├── 1
│   ├── 2
│   ├── 3
│   ├── 4
│   └── 5
└── c
    ├── 2.txt
    ├── 3.txt
    ├── 4.txt
    └── dir

3 directories, 8 files
igi@gentoo ~/test $ shopt -s globstar
igi@gentoo ~/test $ shopt globstar
globstar        on
igi@gentoo ~/test $ echo *
a c
igi@gentoo ~/test $ echo **
a a/1 a/2 a/3 a/4 a/5 c c/2.txt c/3.txt c/4.txt c/dir
igi@gentoo ~/test $ echo */
a/ c/
igi@gentoo ~/test $ echo **/
a/ c/ c/dir/
</pre>
<p>可以看到打开globstar后，**递归的匹配了所有文件和目录， 如果**后面跟着/(即是**/)，则只匹配目录。<br />
问题来了，如果递归显示以.txt结尾到文件，是不是**.txt? 非也，来看看</p>
<pre class="brush: bash; title: ;">
igi@gentoo ~/test $ shopt -s globstar
igi@gentoo ~/test $ shopt globstar
globstar        on
igi@gentoo ~/test $ find . -name '*.txt'
./a.txt
./c/3.txt
./c/2.txt
./c/4.txt
igi@gentoo ~/test $ echo **.txt
a.txt
igi@gentoo ~/test $ echo **/*.txt
a.txt c/2.txt c/3.txt c/4.txt
</pre>
<p>看到了吧，**.txt是无法递归的，而**/*.txt就可以了，同理， foo**这样也不行，**/foo*这样到才可以。<br />
这个功能是bash4才有的哦，使用之前，先确认下你到bash版本。</p>
<p>接下来，我们来看看常见到错误<br />
1)用单引号或双引号包围了星号<br />
在&#8217;<a href="http://www.igigo.net/archives/128">Bash引号的那点事</a>&#8216;中我讲过，单引号中到字符都只有字符的原本意义，而双引号中，*号也是它本身到字符意义，在单双引号中，*号将失去它到魔力，这里就不再罗嗦<br />
如果在双引号中，$*将表示一个由所有参数拼接而成到字符串，上面已经提到过。</p>
<p>2)没有考虑星号匹配不到任何文件的情况<br />
如果指定到目录下没有任何文件时，使用星号匹配，会有啥现象？</p>
<pre class="brush: bash; title: ;">
igi@gentoo ~ $ rm -rf *
igi@gentoo ~ $ ls
igi@gentoo ~ $ echo *
*
</pre>
<p>看到了吧，如果星号匹配不到任何文件时，它变回了自己原本到意思(就是字符*)</p>
<pre class="brush: bash; title: ;">
igi@gentoo ~ $ ls
a  b  c  d
igi@gentoo ~ $ for i in *;do echo &quot;file: $i&quot; ;done
file: a
file: b
file: c
file: d
igi@gentoo ~ $ rm -rf *
igi@gentoo ~ $ ls
igi@gentoo ~ $ for i in *;do echo &quot;file: $i&quot; ;done
file: *
</pre>
<p>只是一个echo时，似乎没多大问题，但你想想，如果你在for中对文件做某些操作，如果匹配不到，变成对*号文件进行操作，我想结果肯定不是你要的，多数情况下，我们想要是，匹配不到则不进行任何操作，有没有办法？办法很多，例如你可以先做个判断，bash中，有个nullglob, 利用它，我们可以直接达到我们要到效果。</p>
<pre class="brush: bash; title: ;">
igi@gentoo ~ $ rm -rf *
igi@gentoo ~ $ shopt nullglob
nullglob        off
igi@gentoo ~ $ for i in *;do echo &quot;file: $i&quot;; done
file: *
igi@gentoo ~ $ shopt -s nullglob
igi@gentoo ~ $ for i in *;do echo &quot;file: $i&quot;; done
igi@gentoo ~ $
</pre>
<p>当然你也可以设置failglob，使得匹配不到文件时报错，这里就不再罗嗦了。</p>
<p>3)混淆模式匹配和正则<br />
先申明，这两者是不同到，这里不打算详细阐述，只列举些常见错误做法</p>
<pre class="brush: bash; title: ;">
igi@gentoo ~/test $ ls
foo-a-log  foo-b-log  foo-c-log  zoo-a-log  zoo-b-log  zoo-c-log
igi@gentoo ~/test $ ls foo.*
ls: cannot access foo.*: No such file or directory
igi@gentoo ~/test $ ls foo*
foo-a-log  foo-b-log  foo-c-log
</pre>
<p>.*在正则中匹配了所有，但请记住，shell中绝大多数用的是模式匹配([[ "$string" =~ RE ]]例外)<br />
在模式匹配中*匹配了所有，?匹配了单个字符，.号没有特殊意义，还是.号<br />
所以，第二个命令才是正确</p>
]]></content:encoded>
			<wfw:commentRss>http://www.igigo.net/archives/164/feed</wfw:commentRss>
		<slash:comments>5</slash:comments>
		</item>
		<item>
		<title>Bash空格的那点事</title>
		<link>http://www.igigo.net/archives/152</link>
		<comments>http://www.igigo.net/archives/152#comments</comments>
		<pubDate>Wed, 19 Jan 2011 08:58:45 +0000</pubDate>
		<dc:creator>igi</dc:creator>
				<category><![CDATA[bash那点事]]></category>
		<category><![CDATA[shell]]></category>
		<category><![CDATA[bash]]></category>
		<category><![CDATA[space]]></category>

		<guid isPermaLink="false">http://www.igigo.net/?p=152</guid>
		<description><![CDATA[空格，一个看不见的字符，很不起眼，也正由于不起眼，很多人经常忽略它，导致代码出错，却还找不着北。这里，我们来聊聊bash中空格的那点事。 先了解下bash中什么时候该用空格，什么时候不该用。 1. 等号赋值两边不能有空格 2. 命令与选项之间需要空格 3. 管道两边空格可有可无 我们来看看常见的问题 1. 赋值时等号两边或者只有左边多了空格 igi@gentoo ~ $ var1 = test bash: var1: command not found igi@gentoo ~ $ echo ${var1:?error} bash: var1: error igi@gentoo ~ $ echo ${var1?error} bash: var1: error igi@gentoo ~ $ var2 =test bash: var2: command not found igi@gentoo ~ $ echo ${var2:?error} bash: var2: [...]]]></description>
			<content:encoded><![CDATA[<p>空格，一个看不见的字符，很不起眼，也正由于不起眼，很多人经常忽略它，导致代码出错，却还找不着北。这里，我们来聊聊bash中空格的那点事。<br />
先了解下bash中什么时候该用空格，什么时候不该用。</p>
<pre>
    1. 等号赋值两边不能有空格
    2. 命令与选项之间需要空格
    3. 管道两边空格可有可无
</pre>
<p>我们来看看常见的问题<br />
1. 赋值时等号两边或者只有左边多了空格</p>
<pre class="brush: bash; title: ;">
igi@gentoo ~ $ var1 = test
bash: var1: command not found
igi@gentoo ~ $ echo ${var1:?error}
bash: var1: error
igi@gentoo ~ $ echo ${var1?error}
bash: var1: error
igi@gentoo ~ $ var2 =test
bash: var2: command not found
igi@gentoo ~ $ echo ${var2:?error}
bash: var2: error
igi@gentoo ~ $ echo ${var2?error}
bash: var2: error
</pre>
<p>这里我用了bash的变量扩展，${var1:?error}当var1为unset或null(未定义或空)时, 报指定错误; ${var1?error}当var1为unset时，报指定错误 。从执行结果来看，如果等号左边有空格，则变量名当成命令执行，结果报command not found，变量没有被赋值</p>
<p>2. 赋值时等号左边没有空格，右边有空格(这种情况有点特别，你会发现两种情况)</p>
<pre class="brush: bash; title: ;">
igi@gentoo ~ $ var= test
igi@gentoo ~ $ var= nocmd
bash: nocmd: command not found
</pre>
<p>同样是等号右边有空格，第一条命令没报错，而第二条报错了。<br />
这是因为shell中有这么一种执行命令的方式: var=string command<br />
命令command将得到变量var的值(至于在命令执行后，变量var的值是否保留下来，bash4中没有保留，但我在dash中发现时保留下来的，不同的shell对这个的处理不同), 由于test是个命令，而nocmd不是，所以报了command not found.</p>
<pre class="brush: bash; title: ;">
igi@gentoo ~ $ var=newtest eval echo \$var
newtest
igi@gentoo ~ $ echo $var
</pre>
<p>注意: 这里我使用了eval, 是想避免在第一次解析时$var被替换成空字符串, 不然就会出现下面的情况(下面是错误的测试方法，在echo还没执行时，$var已经被替换成空字符串)</p>
<pre class="brush: bash; title: ;">
igi@gentoo ~ $ var=newtest echo $var

igi@gentoo ~ $ echo $var
</pre>
<p>到这里，相信大家都明白了吧， 对于等号赋值，左右两边不可以有空格，虽然右边有空格不一定报错，但那绝对不是你想要的结果。</p>
<p>3. 命令和选项之间必须有空格<br />
这个似乎大家都明白，为何我还这么罗嗦呢？说到这里，不得不提一下一个非常特别的命令: [ 命令(你没看错，是[ ), 也就是test命令(当然bash中，这是个内置命令，但在这里不影响<br />
我们的理解)。或许你会觉得[命令眼熟，没错，我保证你见过它，来看看下面的例子</p>
<pre class="brush: bash; title: ;">
igi@gentoo ~ $ if [ &quot;abc&quot; = &quot;abc&quot; ]; then echo &#8216;they are the same&#8217;; fi
they are the same
igi@gentoo ~ $ type -a [
[ is a shell builtin
[ is /usr/bin/[
</pre>
<p>想起来了吧？[命令经常用到if判断中，当然也有人喜欢这么写</p>
<pre class="brush: bash; title: ;">
igi@gentoo ~ $ [ &quot;abc&quot; = &quot;cba&quot; ] || echo &#8216;they are not the same&#8217;
they are not the same
igi@gentoo ~ $ type -a [
[ is a shell builtin
[ is /usr/bin/[
</pre>
<p>[ 命令正名叫test命令，它们两者几乎一样，为什么不是完全一样？来看看这个</p>
<pre class="brush: bash; title: ;">
igi@gentoo ~ $ [ &quot;abc&quot; = &quot;cba&quot;
bash: [: missing `]&#8216;
igi@gentoo ~ $ [ &quot;abc&quot; = &quot;cba&quot; ]
igi@gentoo ~ $ test &quot;abc&quot; = &quot;cba&quot; ]
bash: test: too many arguments
igi@gentoo ~ $ test &quot;abc&quot; = &quot;cba&quot;
</pre>
<p>清晰了吧，用[命令时，你必须给它个尾巴], 用test命令时，就不能加个尾巴。尾巴］是[最后一个参数，不可缺少的参数, 代表[命令的结束</p>
<p>扯了这么多，那到底这个和空格有毛关系？说这些，是先让大家明白: [在shell中是个命令，它左右必须有空格！]是[的最后不可缺少的参数，它两边也需要空格(虽然有些命令的参数能连一起，例如ps, 但［命令不行，它的参数之间必须有空格)。让我们看看关于[常见的错误</p>
<p>a. if 与 [ 之间缺少空格</p>
<pre class="brush: bash; title: ;">
igi@gentoo ~ $ if[ &quot;$HOME&quot; = &quot;/home/igi&quot;];then echo 'equal'; fi
bash: syntax error near unexpected token `then'
igi@gentoo ~ $ if[ &quot;$HOME&quot; = &quot;/home/igi&quot; ];then echo 'equal'; fi
bash: syntax error near unexpected token `then'
igi@gentoo ~ $ if[&quot;$HOME&quot; = &quot;/home/igi&quot;];then echo 'equal'; fi
bash: syntax error near unexpected token `then'
igi@gentoo ~ $ if[&quot;$HOME&quot; = &quot;/home/igi&quot; ];then echo 'equal'; fi
bash: syntax error near unexpected token `then'
</pre>
<p>语法分析错误，很明显，if[ 对于bash来说，不知道是什么鬼东西</p>
<p>b. [与后面的参数之间缺少空格</p>
<pre class="brush: bash; title: ;">
igi@gentoo ~ $ if [&quot;$HOME&quot; = &quot;/home/igi&quot; ];then echo 'equal'; fi
bash: [/home/igi: No such file or directory
igi@gentoo ~ $ if [&quot;$HOME&quot; = &quot;/home/igi&quot;];then echo 'equal'; fi
bash: [/home/igi: No such file or directory
</pre>
<p>["$HOME" 对于bash来说，也不知道是什么鬼东西 </p>
<p>c. [ ] 之间的参数之间缺少空格</p>
<pre class="brush: bash; title: ;">
igi@gentoo ~ $ if [ &quot;abc&quot;=&quot;abc&quot; ]; then echo 'equal'; fi
equal
igi@gentoo ~ $ if [ &quot;abc&quot;=&quot;cba&quot; ]; then echo 'equal'; fi
equal
</pre>
<p>第一条命令似乎是对的(实际上是正巧而已)，看看第二条命令"abc" 和 "cba"明显不同，但却判断为相同。这是因为参数之间缺少了空格，被[命令认为内部是个值而已。看看下面的命令，你就会释然</p>
<pre class="brush: bash; title: ;">
igi@gentoo ~ $ if [ 0 ]; then echo 'equal'; fi
equal
igi@gentoo ~ $ if [ &quot;1&quot; ]; then echo 'equal'; fi
equal
igi@gentoo ~ $ if [ &quot;&quot; ]; then echo 'equal'; fi
igi@gentoo ~ $ if [ ]; then echo 'equal'; fi
</pre>
<p>在[ ] 内部，如果只有一个值(那些因为缺少了空格而连一起的也算)，不是空字符串就为真。所以在[ ] 之间的参数，也要两边有空格，而不能堆一起</p>
<p>d. 参数和尾巴]之间缺少空格<br />
这个就不罗嗦了，尾巴]也是[命令的参数，如同上面所讲，参数之间必须有空格</p>
<p>扯了这么多[命令与空格的事，但有些时候，缺了空格却能正确运行, 当然这只是你好运, 一起来看看</p>
<pre class="brush: bash; title: ;">
igi@gentoo ~ $ var=' abc'
igi@gentoo ~ $ if [$var = &quot;abc&quot; ];then echo 'equal'; fi
equal
igi@gentoo ~ $ if [&quot;$var&quot; = &quot;abc&quot; ];then echo 'equal'; fi
bash: [ abc: command not found
</pre>
<p>之前<a href="http://www.igigo.net/archives/128">Bash引号那点事</a>提到过，双引号包围起来的是一个整体，而没双引号的时候，字符串前后的空格或制表符都被切开。如果恰巧你遇到了或者你故意要丢弃字符串前后的空格或制表符，那也不是不可能, 但非常不建议你这么写，你的代码将是非常脆弱的。</p>
<p>或者你该加的空格都加了，但还是报错，这也可能和缺少双引号有关。这样的情况很普遍，最后再看看</p>
<pre class="brush: bash; title: ;">
igi@gentoo ~ $ var=''
igi@gentoo ~ $ if [ &quot;$var&quot; = &quot;abc&quot; ];then echo 'equal'; fi
igi@gentoo ~ $ if [ $var = &quot;abc&quot; ];then echo 'equal'; fi
bash: [: =: unary operator expected
igi@gentoo ~ $ dvar='a b c'
igi@gentoo ~ $ if [ $dvar = &quot;a b c&quot; ];then echo 'equal'; fi
bash: [: too many arguments
igi@gentoo ~ $ if [ &quot;$dvar&quot; = &quot;a b c&quot; ];then echo 'equal'; fi
equal
</pre>
<p>我再罗嗦一次，不要轻易省略双引号。很清楚了吧？如果你还不明白，<br />
请读读<a href="http://www.igigo.net/archives/128">Bash引号那点事</a></p>
<p>最后，对于管道两边可有可无的空格，就不扯淡了，因为没遇到有人对此有疑惑.</p>
]]></content:encoded>
			<wfw:commentRss>http://www.igigo.net/archives/152/feed</wfw:commentRss>
		<slash:comments>1</slash:comments>
		</item>
		<item>
		<title>Bash引号的那点事</title>
		<link>http://www.igigo.net/archives/128</link>
		<comments>http://www.igigo.net/archives/128#comments</comments>
		<pubDate>Fri, 14 Jan 2011 06:27:12 +0000</pubDate>
		<dc:creator>igi</dc:creator>
				<category><![CDATA[bash那点事]]></category>
		<category><![CDATA[shell]]></category>
		<category><![CDATA[bash]]></category>
		<category><![CDATA[quote]]></category>

		<guid isPermaLink="false">http://www.igigo.net/?p=128</guid>
		<description><![CDATA[促使我想写这个系列的文章，是因为看到总有人提到相同的问题，犯相同的错误，曾经我也是这么过来的，不忍心看到后面还有人经常这么曲折的过来。 先了解下，在bash脚本中，有三种引号 1. 单引号 ' 2. 双引号 " 3. 反引号 ` 单引号 两个单引号包围起来的字符串就是普通的字符串，它将保留原始的字面意思. 双引号 两个双引号包围起来的字符串，部分特殊字符将起到它们的作用. 这些特殊字符有: 美元符$, 反斜杠\, 反引号, 感叹号!. 反引号 两个反引号包围起来的字符串，将作为命令来运行， 执行的输出结果作为该反引号的内容，称为命令替换， 它有另一种更好的写法: $(command) 我们来看几个例子，更直接的了解这三种引号的特性. 1. 美元符$在单、双引号中的表现: 在双引号中的$, 将发生变量引用, 而在单引号中的$, 将保留它的字面意思 igi@gentoo ~ $ echo '$HOME' $HOME igi@gentoo ~ $ echo &#34;$HOME&#34; /home/igi 注: HOME为内部变量 2. 反斜杠\ 在单、双引号中的表现: 在双引号中的\, 将转义它后面的字符，使其具有特殊意义或者失去原来的特殊意义, 在单引号中的\, 将保留它的字面意思 igi@gentoo ~ [...]]]></description>
			<content:encoded><![CDATA[<p>促使我想写这个系列的文章，是因为看到总有人提到相同的问题，犯相同的错误，曾经我也是这么过来的，不忍心看到后面还有人经常这么曲折的过来。</p>
<p>先了解下，在bash脚本中，有三种引号</p>
<pre>
1. 单引号 '
2. 双引号 "
3. 反引号 `

单引号
        两个单引号包围起来的字符串就是普通的字符串，它将保留原始的字面意思.
双引号
        两个双引号包围起来的字符串，部分特殊字符将起到它们的作用.
        这些特殊字符有: 美元符$, 反斜杠\, 反引号,  感叹号!.
反引号
        两个反引号包围起来的字符串，将作为命令来运行，
        执行的输出结果作为该反引号的内容，称为命令替换，
        它有另一种更好的写法: $(command)
</pre>
<p>我们来看几个例子，更直接的了解这三种引号的特性.<br />
1. 美元符$在单、双引号中的表现: 在双引号中的$, 将发生变量引用, 而在单引号中的$, 将保留它的字面意思</p>
<pre class="brush: bash; title: ;">
igi@gentoo ~ $ echo '$HOME'
$HOME
igi@gentoo ~ $ echo &quot;$HOME&quot;
/home/igi
</pre>
<p>注: HOME为内部变量</p>
<p>2. 反斜杠\ 在单、双引号中的表现: 在双引号中的\, 将转义它后面的字符，使其具有特殊意义或者失去原来的特殊意义, 在单引号中的\, 将保留它的字面意思</p>
<pre class="brush: bash; title: ;">
igi@gentoo ~ $ echo '\$HOME'
\$HOME
igi@gentoo ~ $ echo &quot;\$HOME&quot;
$HOME
</pre>
<p>注: 双引号中的\，后面跟着$, 这里发生了转义，使得$失去特殊意义, 变成普通字符.</p>
<p>3. 反引号与其他两种引号的不同: 反引号包围起来的字符串将被运行，取其结果</p>
<pre class="brush: bash; title: ;">
igi@gentoo ~ $ echo 'date'
date
igi@gentoo ~ $ echo &quot;date&quot;
date
igi@gentoo ~ $ echo `date`
Fri Dec 3 18:34:09 CST 2010
</pre>
<p>注: 在反引号中的date被当成命令执行，包含的正是命令的输出信息</p>
<p>了解了他们的不同，我们来聊一聊常见的问题</p>
<p>1. 把反引号` 写 成单引号&#8217;</p>
<p>不得不说，它们长得确实很像，个别书的印刷字体区别度不高或者印刷质量不过关, 导致了很多新手认错，常把反引号`写成单引号&#8217;。如果你不知道反引号在哪，请看看Esc键下面的那个按键, 那个就是反引号。当然也不排除有些人看书不注意，这也是常有的事。只要我们明白了反引号与单引号作用的区别，什么时候要用单引号，什么时候要用反引号就一清二楚了。当你需要一个字符串时，使用单引号； 而当你需要捕捉命令的输出时，请用反引号。</p>
<p>2. 总是忘了加双引号<br />
双引号不总是多余的，被它包围的数据变得很安全，不至于被bash切开对待。</p>
<pre class="brush: bash; title: ;">
igi@gentoo ~ $ seq 3
1
2
3
igi@gentoo ~ $ echo `seq 3`
1 2 3
igi@gentoo ~ $ echo &quot;`seq 3`&quot;
1
2
3
</pre>
<p>注: seq输出的是包含换行的信息，但echo `seq 3` 却丢失了换行符，因为bash在解析时认为`seq 3`的输出结果是3个独立的字符，解析后与echo 1 2 3相同(这个过程，bash做了很多工作，有兴趣的可以了解下bash解析顺序); 而echo &#8220;`seq 3`&#8221;时，bash把`seq 3`的输出结果当成一个整体对待(因为它被双引号包围),所以输出的结果不会被bash拆分对待，换行符得以保留。所以，当你需要保留变量或者命令替换的完整信息, 特别是换行符时，请记得给它们戴上双引号作保险，时刻加个双引号是个好习惯（为什么不是单引号呢？前面解释了，单引号里面没有魔法，变量也变不了了，命令替换也替换不了了)。再次提醒: &#8220;$var&#8221;, &#8220;`command`&#8221;, 都比$var, `command`安全得多，很多情况下，前面的才是你要的结果，除非你知道你在做什么，否则不要轻易省略双引号。</p>
<p>3. 引号嵌套总是混乱的<br />
引号中包含其他引号，只要能理解单引号和双引号中字符的表现，就不难掌握</p>
<pre class="brush: bash; title: ;">
igi@gentoo ~ $ echo &quot;abc\&quot;abc&quot;
abc&quot;abc
igi@gentoo ~ $ echo &quot;abc\'abc&quot;
abc'abc
igi@gentoo ~ $ echo &quot;abc\`abc&quot;
abc`abc
</pre>
<p>如你所见，双引号中加入其他引号很容易，你只需要用反斜杠\转义你要添加的引号(双引号中加单引号可以不用转义)。 那么单引号中是否如此简单？</p>
<pre class="brush: bash; title: ;">
igi@gentoo ~ $ echo 'abc&quot;abc'
abc&quot;abc
igi@gentoo ~ $ echo 'abc`abc'
abc`abc
</pre>
<p>到这里，确实很简单，单引号中都是普通字符，所以完全不需要转义，如果加了反斜杠\, 那么反斜杠依然是它自己，直接打印出来。</p>
<pre class="brush: bash; title: ;">
igi@gentoo ~ $ echo 'abc\&quot;\`abc'
abc\&quot;\`abc
</pre>
<p>问题来了，单引号中如何包含单引号？这个时候，反斜杠\也是无用的, 如果直接写单引号，那么bash会认为引号还没结束。好吧，如果你不幸碰到这样的问题，还是有办法解决的</p>
<pre class="brush: bash; title: ;">
igi@gentoo ~ $ echo $'abc\'abc'
abc'abc
igi@gentoo ~ $ echo -e 'abc\x27abc'
abc'abc
igi@gentoo ~ $ echo 'abc'\''abc'
abc'abc
</pre>
<p>第一种方法是bash特有的，$&#8217;string&#8217; 之间到反斜杠都将转义字符，第二种方法，通过单引号的ASCII码来打印单引号，而第三种方法，则是通过截断命令，在中间插入单引号来实现。一般用第一种方法是最优雅的。</p>
<p>最后: 希望能更多的人喜欢Bash，使用Bash。</p>
]]></content:encoded>
			<wfw:commentRss>http://www.igigo.net/archives/128/feed</wfw:commentRss>
		<slash:comments>1</slash:comments>
		</item>
		<item>
		<title>crontab中不支持变量互相引用</title>
		<link>http://www.igigo.net/archives/118</link>
		<comments>http://www.igigo.net/archives/118#comments</comments>
		<pubDate>Wed, 01 Dec 2010 08:05:56 +0000</pubDate>
		<dc:creator>igi</dc:creator>
				<category><![CDATA[小砸碎]]></category>
		<category><![CDATA[crontab]]></category>

		<guid isPermaLink="false">http://www.igigo.net/?p=118</guid>
		<description><![CDATA[今天心血来潮, 整理起某台服务器的crontab， 添加了两个变量来代替冗长的路径 HOME=/home/data/usr LOGDIR=$HOME/logs 一开始没在意, 保存后发现所有涉及这两个变量的条目无法正确执行了. 看了man, 确定crontab是支持变量的, 变量写的路径也正确. 无奈之中加了条echo进crontab中, 想看看这两个变量解析后的样子 echo $HOME $LOGDIR /home/data/usr $HOME/logs 原来crontab是不支持变量的互相引用的&#8230;&#8230;.]]></description>
			<content:encoded><![CDATA[<p style="text-indent:2em" >今天心血来潮, 整理起某台服务器的crontab， 添加了两个变量来代替冗长的路径</p>
<pre class="brush: bash; title: ;">
HOME=/home/data/usr
LOGDIR=$HOME/logs
</pre>
<p style="text-indent:2em" >一开始没在意, 保存后发现所有涉及这两个变量的条目无法正确执行了. 看了man, 确定crontab是支持变量的, 变量写的路径也正确. 无奈之中加了条echo进crontab中, 想看看这两个变量解析后的样子</p>
<pre class="brush: bash; title: ;">
echo $HOME $LOGDIR
/home/data/usr $HOME/logs
</pre>
<p>原来crontab是不支持变量的互相引用的&#8230;&#8230;.</p>
]]></content:encoded>
			<wfw:commentRss>http://www.igigo.net/archives/118/feed</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>clusterssh (Cssh) KDE下无法正确重排窗口的问题</title>
		<link>http://www.igigo.net/archives/103</link>
		<comments>http://www.igigo.net/archives/103#comments</comments>
		<pubDate>Thu, 02 Sep 2010 03:18:18 +0000</pubDate>
		<dc:creator>igi</dc:creator>
				<category><![CDATA[小砸碎]]></category>
		<category><![CDATA[clusterssh]]></category>
		<category><![CDATA[cssh]]></category>
		<category><![CDATA[kde]]></category>

		<guid isPermaLink="false">http://www.igigo.net/?p=103</guid>
		<description><![CDATA[cssh 是一个不错的多服务器登录工具， 采用平铺窗口的方式， 相比konsole的多tab, 更来得直观。 我也把它融合到自己的myssh中。 cssh在打开多窗口后， 会有个重排窗口使之不重叠的功能， 之前在gnome下用很正常， 但现在换到KDE， 却发现重排后依然没变化，乱且重叠了。搜了下，还真没找到啥解决方法， 想想cssh是perl写的， 就硬着头皮看看， 希望能解决这个小问题 稍微看了下函数， 发现有个与窗口重排有关的send_resizemove， 从函数名应该可以猜到它的作用。 整个cssh中， 只有一处地方调用了这函数. 大概在1367行。 logmsg( 2, &#34;Moving $server window&#34; ); send_resizemove( $servers{$server}{wid}, $current_x, $current_y, $config{internal_terminal_width}, #该参数指定了重排时窗口的新宽度 $config{internal_terminal_height} #该参数指定了重排时窗口的新高度 ); 我修改了代码中最后两个参数， 并打开logmsg的调试信息， 希望能找到无法重排及重新调整窗口大小的问题。 写死了新的窗口大小， 但出来的结果却是只有最后一个窗口会改变大小， 其他窗口都没变化， 这倒很有意思， 不是send_resizemove无法起作用， 而是无法在全部窗口起作用。 Tiling top left going bot right x:5 y:5, r:0 c:0 Moving [...]]]></description>
			<content:encoded><![CDATA[<p style="text-indent:2em" >cssh 是一个不错的多服务器登录工具， 采用平铺窗口的方式， 相比konsole的多tab,  更来得直观。 我也把它融合到自己的myssh中。 </p>
<p style="text-indent:2em" >cssh在打开多窗口后， 会有个重排窗口使之不重叠的功能， 之前在gnome下用很正常， 但现在换到KDE， 却发现重排后依然没变化，乱且重叠了。搜了下，还真没找到啥解决方法， 想想cssh是perl写的， 就硬着头皮看看， 希望能解决这个小问题</p>
<p style="text-indent:2em" >稍微看了下函数， 发现有个与窗口重排有关的send_resizemove， 从函数名应该可以猜到它的作用。 整个cssh中， 只有一处地方调用了这函数. 大概在1367行。</p>
<pre class="brush: perl; title: ;">
        logmsg( 2, &quot;Moving $server window&quot; );
        send_resizemove(
            $servers{$server}{wid},
            $current_x, $current_y,
            $config{internal_terminal_width},    #该参数指定了重排时窗口的新宽度
            $config{internal_terminal_height}    #该参数指定了重排时窗口的新高度
        );
</pre>
<p style="text-indent:2em" >我修改了代码中最后两个参数， 并打开logmsg的调试信息， 希望能找到无法重排及重新调整窗口大小的问题。 写死了新的窗口大小， 但出来的结果却是只有最后一个窗口会改变大小， 其他窗口都没变化， 这倒很有意思， 不是send_resizemove无法起作用， 而是无法在全部窗口起作用。</p>
<pre class="brush: bash; title: ;">
Tiling top left going bot right
x:5 y:5, r:0 c:0
Moving 15.238.122.15  window
Moving window 65011726 to x:5 y:5 (size x:488 y:242)
x:498 y:5, r:0 c:1
Moving 15.238.122.16  window
Moving window 88080398 to x:498 y:5 (size x:488 y:242)
x:991 y:5, r:0 c:2
Moving 15.238.122.17  window
Moving window 75497486 to x:991 y:5 (size x:488 y:242)
x:1484 y:5, r:0 c:3
Moving 15.238.122.18  window
Moving window 62914574 to x:1484 y:5 (size x:488 y:242)
x:1977 y:5, r:0 c:4
Moving 115.238.122.19  window
Moving window 83886094 to x:1977 y:5 (size x:488 y:242)
x:2470 y:5, r:0 c:5
Moving 15.238.122.20  window
Moving window 92274702 to x:2470 y:5 (size x:488 y:242)
x:5 y:252, r:1 c:0
Moving 15.238.122.22  window
Moving window 77594638 to x:5 y:252 (size x:488 y:242)
x:498 y:252, r:1 c:1
Moving 15.238.122.23  window
Moving window 67108878 to x:498 y:252 (size x:488 y:242)
x:991 y:252, r:1 c:2
Moving 15.238.122.24  window
Moving window 69206030 to x:991 y:252 (size x:488 y:242)
x:1484 y:252, r:1 c:3
Moving 15.238.122.25  window
Moving window 73400334 to x:1484 y:252 (size x:488 y:242)
x:1977 y:252, r:1 c:4
Moving 15.238.122.26  window
Moving window 71303182 to x:1977 y:252 (size x:488 y:242)
x:2470 y:252, r:1 c:5
Moving 15.238.122.27  window
Moving window 81788942 to x:2470 y:252 (size x:488 y:242)
x:5 y:499, r:2 c:0
Moving 15.238.122.29  window
Moving window 79691790 to x:5 y:499 (size x:488 y:242)
x:498 y:499, r:2 c:1
Moving 15.238.122.20  window
Moving window 94371854 to x:498 y:499 (size x:488 y:242)
x:991 y:499, r:2 c:2
Moving 15.238.122.21  window
Moving window 90177550 to x:991 y:499 (size x:488 y:242)
x:1484 y:499, r:2 c:3
Moving 15.238.122.22  window
Moving window 96469006 to x:1484 y:499 (size x:488 y:242)
x:1977 y:499, r:2 c:4
Moving 15.238.122.23  window
Moving window 85983246 to x:1977 y:499 (size x:488 y:242)
x:2470 y:499, r:2 c:5
Moving 15.238.122.24  window
Moving window 111149070 to x:2470 y:499 (size x:488 y:242)
Setting focus on 15.238.122.24
Setting focus on 15.238.122.23
Setting focus on 15.238.122.22
Setting focus on 15.238.122.21
Setting focus on 15.238.122.20
Setting focus on 15.238.122.29
Setting focus on 15.238.122.27
Setting focus on 15.238.122.26
Setting focus on 15.238.122.15
Setting focus on 15.238.122.24
Setting focus on 15.238.122.23
Setting focus on 15.238.122.22
Setting focus on 15.238.122.20
Setting focus on 15.238.122.19
Setting focus on 15.238.122.18
Setting focus on 15.238.122.17
Setting focus on 15.238.122.16
Setting focus on 15.238.122.15
Sending console to front
</pre>
<p style="text-indent:2em" >这是cssh的调试信息中与窗口重排相关的部分， 最后的Setting focus 提示了我， 当前是重排所有窗口后， 再把焦点逐个定位到每个窗口(相当于鼠标点中的窗口状态)， 是否在KDE下没有做这一步就无法调整大小?  根据Setting focus， 我找到了cssh中 相关的代码</p>
<pre class="brush: perl; title: ;">
    # Now remap in right order to get overlaps correct
    if ( $config{window_tiling_direction} =~ /right/i ) {
        foreach my $server ( reverse(@hosts) ) {
            logmsg( 2, &quot;Setting focus on $server&quot; );
            $xdisplay-&gt;req( 'MapWindow', $servers{$server}{wid} );

            # flush every time and wait a moment (The WMs are so slow...)
            $xdisplay-&gt;flush();
            select( undef, undef, undef, 0.1 );    # sleep for a mo
        }
    }
    else {
        foreach my $server (@hosts) {
            logmsg( 2, &quot;Setting focus on $server&quot; );
            $xdisplay-&gt;req( 'MapWindow', $servers{$server}{wid} );

            # flush every time and wait a moment (The WMs are so slow...)
            $xdisplay-&gt;flush();
            select( undef, undef, undef, 0.1 );    # sleep for a mo
        }
    }
</pre>
<p style="text-indent:2em" >不难看出， &#8216;$xdisplay->req( &#8216;MapWindow&#8217;, $servers{$server}{wid} );&#8217; 这一句就是我要的， $servers{$server}{wid} 就是窗口的ID, 依葫芦画瓢， 我加了这么一句到send_resizemove的函数调用之前</p>
<pre class="brush: perl; title: ;">
       logmsg( 2, &quot;Moving $server window&quot; );
       $xdisplay-&gt;req( 'MapWindow', $servers{$server}{wid} );
        send_resizemove(
            $servers{$server}{wid},
            $current_x, $current_y,
            $config{internal_terminal_width},    #该参数指定了重排时窗口的新宽度
            $config{internal_terminal_height}    #该参数指定了重排时窗口的新高度
        );
</pre>
<p style="text-indent:2em" >很幸运的， 确实如我所想， 终于能在KDE下正确重排窗口了！！  </p>
]]></content:encoded>
			<wfw:commentRss>http://www.igigo.net/archives/103/feed</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>bash重定向详解</title>
		<link>http://www.igigo.net/archives/79</link>
		<comments>http://www.igigo.net/archives/79#comments</comments>
		<pubDate>Wed, 23 Jun 2010 05:11:49 +0000</pubDate>
		<dc:creator>igi</dc:creator>
				<category><![CDATA[shell]]></category>
		<category><![CDATA[bash]]></category>
		<category><![CDATA[linux]]></category>
		<category><![CDATA[Redirections]]></category>

		<guid isPermaLink="false">http://www.igigo.net/?p=79</guid>
		<description><![CDATA[首先我们先回顾下bash现有的重定向符号 1.重定向输入输出，目标是文件word [n]&#60;word 默认n为0 [n]&#62;word 默认n为1 [n]&#62;&#124;word 默认n为1 noclobber选项有关，直接例子就明白它的用处了 [n]&#62;&#62;word 默认n为1 igi@igi-debian:~$ rm -f testfile igi@igi-debian:~$ touch testfile igi@igi-debian:~$ cat testfile igi@igi-debian:~$ set -o noclobber igi@igi-debian:~$ echo 2 &#62;testfile bash: testfile: cannot overwrite existing file igi@igi-debian:~$ echo 2 &#62;&#124; testfile igi@igi-debian:~$ cat testfile 2 2.重定向标准错误和标准输出到指定文件描述符 &#38;&#62;word 更通用 &#62;&#38;word &#62;word 2&#62;&#38;1 追加输出 &#38;&#62;&#62;word 没有&#62;&#62;&#38;word的表达方法 &#62;&#62;word 2&#62;&#38;1 [...]]]></description>
			<content:encoded><![CDATA[<p>首先我们先回顾下bash现有的重定向符号</p>
<h3>1.重定向输入输出，目标是文件word</h3>
<pre class="brush: plain; gutter: false; title: ;">
[n]&lt;word    默认n为0
[n]&gt;word    默认n为1
[n]&gt;|word   默认n为1    noclobber选项有关，直接例子就明白它的用处了
[n]&gt;&gt;word   默认n为1
</pre>
<pre class="brush: bash; title: ;">
igi@igi-debian:~$ rm -f testfile
igi@igi-debian:~$ touch testfile
igi@igi-debian:~$ cat testfile
igi@igi-debian:~$ set -o noclobber
igi@igi-debian:~$ echo 2 &gt;testfile
bash: testfile: cannot overwrite existing file
igi@igi-debian:~$ echo 2 &gt;| testfile
igi@igi-debian:~$ cat testfile
2
</pre>
<h3>2.重定向标准错误和标准输出到指定文件描述符</h3>
<pre class="brush: plain; gutter: false; title: ;">
&amp;&gt;word      更通用
&gt;&amp;word
&gt;word 2&gt;&amp;1
</pre>
<p>追加输出</p>
<pre class="brush: plain; gutter: false; title: ;">
&amp;&gt;&gt;word     没有&gt;&gt;&amp;word的表达方法
&gt;&gt;word 2&gt;&amp;1
</pre>
<h3>3.Here Documents</h3>
<pre class="brush: plain; gutter: false; title: ;">
 &lt;&lt;[-]word
   here-document
delimiter
-符号将删除所有行开头的tab符
</pre>
<h3>4.Here Strings</h3>
<pre class="brush: plain; gutter: false; title: ;">
&lt;&lt;&lt;word
</pre>
<h3>5.复制文件描述符</h3>
<pre class="brush: plain; gutter: false; title: ;">
[n]&lt;&amp;word   默认n为0，如果为数字，必须得为打开的文件描述符
[n]&lt;&amp;-      关闭文件描述符

[n]&gt;&amp;word   默认n为1，如果为数字，必须得为打开的文件描述符
[n]&gt;&amp;-      关闭文件描述符
</pre>
<h3>6.移动文件描述符</h3>
<pre class="brush: plain; gutter: false; title: ;">
[n]&lt;&amp;digit- 默认n为0
[n]&gt;&amp;digit- 默认n为1
</pre>
<h3>7.以读写方式打开文件描述符</h3>
<pre class="brush: plain; gutter: false; title: ;">
[n]&lt;&gt;word   文件不在时会被创建
</pre>
<p>如果要深刻理解重定向，先要明白以下2点<br />
1.shell(bash或者csh等)负责重定向，对于程序或者函数，这一切都是透明的，它只管输入输出，至于从哪输入哪输出，是shell解释器负责<br />
2.shell命令解析过程中，在实际执行命令前，IO重定向先设置好</p>
<p>我们来看以下的例子</p>
<h4>1.&#8217;echo 1 a1 >a2&#8242; 与 &#8216;echo 1 >a2 a1&#8242;</h4>
<pre class="brush: bash; title: ;">
igi@igi-debian:~$ echo 1 a1 &gt;a2
igi@igi-debian:~$ cat a2
1 a1
igi@igi-debian:~$ rm a2
igi@igi-debian:~$ echo 1 &gt;a2 a1
igi@igi-debian:~$ cat a2
1 a1
</pre>
<p>IO重定向是在命令执行前设置好，所以上面两种情况，最后的效果一样，bash先把输出重定向到a2文件，再执行&#8217;echo 1 a1&#8242;</p>
<h4>2.&#8217;ls nothisfile >res 2>&#038;1&#8242; 与 &#8216;ls nothisfile 2>&#038;1 >res&#8217;</h4>
<pre class="brush: bash; title: ;">
igi@igi-debian:~/rtest$ ls nothisfile
ls: cannot access nothisfile: No such file or directory
igi@igi-debian:~/rtest$ ls nothisfile &gt;res 2&gt;&amp;1
igi@igi-debian:~/rtest$ cat res
ls: cannot access nothisfile: No such file or directory
igi@igi-debian:~/rtest$ ls nothisfile 2&gt;&amp;1 &gt;res
ls: cannot access nothisfile: No such file or directory
igi@igi-debian:~/rtest$ cat res
igi@igi-debian:~/rtest$ ls -1
a
b
c
res
igi@igi-debian:~/rtest$ ls -1 2&gt;&amp;1 &gt;res
igi@igi-debian:~/rtest$ cat res
a
b
c
res
</pre>
<p>
&#8216;ls nothisfile >res 2>&#038;1&#8242;，文件描述符1被重定向到文件res(本来是标准输出)，然后再把文件描述符2重定向到文件描述符1(此时是文件描述符1指向文件res)，最后执行&#8221;ls nothisfile&#8221;，产生错误，被送往文件描述符2，最后流向文件res。<br />
&#8216;ls nothisfile 2>&#038;1 >res&#8217;，文件描述符2被重定向到文件描述符1(即标准输出：屏幕)，然后再把文件描述符1重定向到文件res，结果是文件描述符2被重定向到标准输出，文件描述符1被重定向到文件res，最后执行&#8221;ls nothisfile&#8221;产生的错误就被送往屏幕。
</p>
<h4>3.&#8217;ls nothisfile a >&#038;word&#8217; 与 &#8216;ls nothisfile a >&#038;123456&#8242;</h4>
<pre class="brush: bash; title: ;">
igi@igi-debian:~/test/shell$ ls -1
a
igi@igi-debian:~/test/shell$ cat a
this is a
igi@igi-debian:~/test/shell$ ls nothisfile a &gt;&amp;word
igi@igi-debian:~/test/shell$ cat word
ls: cannot access nothisfile: No such file or directory
a
igi@igi-debian:~/test/shell$ ls nothisfile a &gt;&amp;123456
-bash: 123456: Bad file descriptor
igi@igi-debian:~/test/shell$ cat 123456
cat: 123456: No such file or directory
</pre>
<p>
>&#038;这个重定向符号，在前面有提到，“重定向标准错误和标准输出到指定文件描述符“ 和 “复制文件描述符“ 都有这个符号, 实际上“重定向标准错误和标准输出到指定文件描述符“ 是 “复制文件描述符“ 的一种特别情况， 即当 [n]>&#038;word 的n省略 且  word不是数字时， 会重定向标准错误和标准输出 到指定文件。<br />
&#8220;ls nothisfile a >&#038;word&#8221; , 由于word不是纯数字， bash解析成 ”重定向标准错误和标准输出到指定文件描述符“， 效果相当于 &#8221; ls nothisfile a >word 2>&#038;1&#8243;<br />
&#8220;ls nothisfile a >&#038;123456&#8243;, 由于123456是纯数字， bash解析成 &#8220;复制文件描述符&#8221;, 相当于 &#8221; ls nothisfile a 1>&#038;123456&#8243; , 但由于 “ 复制文件描述符 “规定　“如果为数字，必须得为打开的文件描述符”<br />
所以发生了错误。
</p>
<h4>4.&#8217;ls a 1>&#038;-&#8217; 与 &#8216; ls a >&#038;1- &#8216;</h4>
<pre class="brush: bash; title: ;">
igi@igi-debian:~/test/shell$ ls
a
igi@igi-debian:~/test/shell$ cat a
this is a
igi@igi-debian:~/test/shell$ ls a &gt;&amp;1-
a
igi@igi-debian:~/test/shell$ ls a 1&gt;&amp;-
ls: write error: Bad file descriptor
</pre>
<p>
“  ls a >&#038;1- “，　>&#038;1-属于“移动文件描述符” 提到的 &#8220;[n]>&#038;digit-&#8221;, 用文件描述符digit替换掉文件描述符n, n描述符被关闭.n默认为1.  &#8220;ls a >&#038;1-&#8221;,  相当与 &#8221; ls a 1>&#038;1- &#8220;,  把文件描述符1替换掉原<br />
文件描述符1, 然后关闭原文件描述符1, 没发生变化, 输出依然被送到屏幕<br />
&#8221; ls a 1>&#038;- &#8220;,  >&#038;- 属于 &#8220;复制文件描述符&#8221; 提到的&#8221;关闭文件描述符&#8221;,  &#8221; ls a 1>&#038;- &#8220;, 关闭了文件描述符1, 在运行&#8221; ls a&#8221;, 由于输出默认都送到文件描述符1, 而它被关闭, 报&#8221;错误的文件描述符&#8221;
</p>
<h4>5.&#8217;ls a nothisfile 1>&#038;2-&#8217; 与 &#8216; ls a nothisfile 1<&#038;2- '</h4>
<pre class="brush: bash; title: ;">
igi@igi-debian:~/test/shell$ ls -1
a
igi@igi-debian:~/test/shell$ ls a nothisfile 1&lt;&amp;2-
a
igi@igi-debian:~/test/shell$ ls a nothisfile 1&gt;&amp;2-
a
igi@igi-debian:~/test/shell$ exec 3&lt;&gt;test
igi@igi-debian:~/test/shell$ ls a nothisfile 1&gt;&amp;3-
ls: cannot access nothisfile: No such file or directory
igi@igi-debian:~/test/shell$ cat test
a
igi@igi-debian:~/test/shell$
</pre>
<p>
&#8216; 1>&#038;2- &#8216; 与 &#8216; 1<&#038;2- ' 是一个效果的, [n]>&#038;digit- 和 [n]<&#038;digit-  这两个移动文件描述符的操作, 都是移动digit 到 n , 区别在n没有指定时, <&#038;digit- 等于 0<&#038;digit-,  而 >&#038;digit- 等于 1>&#038;digit-<br />
移动文件描述符, 就是把描诉符digit的指向给描述符n, 然后关了digit.  例子中的exec很好的解释移动文件描述符的行为, 文件描述符3被定向到文件test, 然后1>&#038;3-, 会使得1也定向到3所定向的文件test, 然后文件描诉符3被关闭, 效果就是标准输出被定向到test文件.</p>
]]></content:encoded>
			<wfw:commentRss>http://www.igigo.net/archives/79/feed</wfw:commentRss>
		<slash:comments>1</slash:comments>
		</item>
		<item>
		<title>apt-get remove 与 apt-get autoremove、aptitude remove的不同</title>
		<link>http://www.igigo.net/archives/88</link>
		<comments>http://www.igigo.net/archives/88#comments</comments>
		<pubDate>Tue, 22 Jun 2010 08:10:13 +0000</pubDate>
		<dc:creator>igi</dc:creator>
				<category><![CDATA[系统设置]]></category>
		<category><![CDATA[apt-get]]></category>
		<category><![CDATA[aptitude]]></category>
		<category><![CDATA[autoremove]]></category>
		<category><![CDATA[debian]]></category>

		<guid isPermaLink="false">http://www.igigo.net/?p=88</guid>
		<description><![CDATA[apt-get remove 与 apt-get autoremove、aptitude remove的不同 apt-get remove的行为我们很好理解，就是删除某个包的同时，删除依赖于它的包 例如： A 依赖于 B, B 依赖于 C apt-get remove 删除B的同时，将删除A(很好理解，A依赖于B，B被删了，A也就无法正常运行了) 先说明下apt-get autoremove与aptitude remove是一样的效果的, 我们先了解下这两者的瓜葛 apt-get一开始并没有记录auto-install的信息，在apt(0.6.44.2exp1)此版本时(06年)，apt-get增加了类似于aptitude的auto-install记录(/var/lib/apt/extended_states)。此后，aptitude在版本0.4.5.1(07年)转向使用apt-get的auto-install记录，而抛弃了自己原先的记录方式，再随后apt-get在版本0.7.7(07年)增加了autoremove的选项。 依赖关系是一个复杂而交错的链条，我们把举几个例子来看看它们的行为 以下图中， 绿色圆是为了满足依赖关系而apt-get或aptitude自动安装上的包 蓝色圆是管理员使用apt-get install 或 aptitude install 指定安装的包，简称为手动安装的包 例子1: 1. C 依赖于或推荐B软件包(apt-get和aptitude在安装软件时除了安装必要的依赖包，默认也会安装Recommends关系的包) 2. B 依赖于或推荐A, A被其他手动安装的包依赖 apt-get remove C 将删除C, 同时提示你用apt-get autoremove去清除B apt-get autoremove C 将删除B, C aptitude remove C 将删除B, [...]]]></description>
			<content:encoded><![CDATA[<p>apt-get remove 与 apt-get autoremove、aptitude remove的不同</p>
<p>apt-get remove的行为我们很好理解，就是删除某个包的同时，删除依赖于它的包<br />
例如： A 依赖于 B, B 依赖于 C<br />
apt-get remove 删除B的同时，将删除A(很好理解，A依赖于B，B被删了，A也就无法正常运行了)</p>
<p>先说明下apt-get autoremove与aptitude remove是一样的效果的,  我们先了解下这两者的瓜葛</p>
<p>apt-get一开始并没有记录auto-install的信息，在apt(0.6.44.2exp1)此版本时(06年)，apt-get增加了类似于aptitude的auto-install记录(/var/lib/apt/extended_states)。此后，aptitude在版本0.4.5.1(07年)转向使用apt-get的auto-install记录，而抛弃了自己原先的记录方式，再随后apt-get在版本0.7.7(07年)增加了autoremove的选项。</p>
<p>依赖关系是一个复杂而交错的链条，我们把举几个例子来看看它们的行为</p>
<pre class="brush: bash; title: ;">
以下图中， 绿色圆是为了满足依赖关系而apt-get或aptitude自动安装上的包
蓝色圆是管理员使用apt-get install 或 aptitude install
指定安装的包，简称为手动安装的包
</pre>
<p>例子1:<br />
1. C 依赖于或推荐B软件包(apt-get和aptitude在安装软件时除了安装必要的依赖包，默认也会安装Recommends关系的包)<br />
2. B 依赖于或推荐A, A被其他手动安装的包依赖<br />
<a href="http://www.igigo.net/wp-content/uploads/2010/06/abc1.jpg"><img class="aligncenter size-full wp-image-91" title="abc" src="http://www.igigo.net/wp-content/uploads/2010/06/abc1.jpg" alt="" width="348" height="503" /></a></p>
<pre class="brush: bash; title: ;">
apt-get remove C         将删除C, 同时提示你用apt-get autoremove去清除B
apt-get autoremove C     将删除B, C
aptitude remove C        将删除B, C
</pre>
<p>我的理解: 删除C, 那么B这个包既是自动安装的,且没有其他手动安装的包依赖于它,<br />
则可以判定B也是没必要的</p>
<p>例子2:<br />
1. 在例子1的基础上, D 依赖于或者推荐B, 且D没有被其他手动安装的包依赖<br />
这样的情况一般出现在用apt-get remove 某个手动安装的包之后.</p>
<p style="text-align: center;"><a href="http://www.igigo.net/wp-content/uploads/2010/06/abcd.jpg"><img class="size-full wp-image-90 aligncenter" title="abcd" src="http://www.igigo.net/wp-content/uploads/2010/06/abcd.jpg" alt="" width="413" height="546" /></a></p>
<pr
<pre class="brush: bash; title: ;">
apt-get remove C         将删除C, 同时提示你用apt-get autoremove去清除B,D
apt-get autoremove C     将删除B, C, D
aptitude remove C        将删除B, C, D
</pre>
<p>我的理解: 删除C, 那么B,D 这两个包既是自动安装的,且没有其他手动安装的包依赖于它们,<br />
则可以判定B,D也是没必要的</p>
<p>例子3:<br />
1. 在例子2的基础上, 有个手动安装的包E推荐D(既E Recommends D,手动安装E时,也会把D装上)</p>
<p><a href="http://www.igigo.net/wp-content/uploads/2010/06/abcd4.jpg"><img class="aligncenter size-full wp-image-92" title="abcd4" src="http://www.igigo.net/wp-content/uploads/2010/06/abcd4.jpg" alt="" width="387" height="577" /></a></p>
<pre class="brush: bash; title: ;">
apt-get remove C         将删除C, 同时提示你用apt-get autoremove去清除B,D
apt-get autoremove C     将删除B, C, D
aptitude remove C        将删除B, C, D
</pre>
<p>我的理解: 删除C, 那么B,D 这两个包既是自动安装的,且没有其他手动安装的包依赖于它们,<br />
则可以判定B,D也是没必要的<br />
虽然D被E Recommend, 但为啥是这么设计的, 我也没猜出开发人员的想法</p>
<p>例子4:<br />
1. 在例子3的基础上, D变成依赖于B, E变成依赖于D</p>
<p><a href="http://www.igigo.net/wp-content/uploads/2010/06/abcd1.jpg"><img class="aligncenter size-full wp-image-93" title="abcd1" src="http://www.igigo.net/wp-content/uploads/2010/06/abcd1.jpg" alt="" width="400" height="644" /></a></p>
<pre class="brush: bash; title: ;">
apt-get remove C         将删除C
apt-get autoremove C     将删除C
aptitude remove C        将删除C
</pre>
<p>我的理解: 只删除C, 因为B被D依赖, D被E依赖, 间接来说,E不能没有B,D而正常运行,所以B,D被保留</p>
<p>例子5:<br />
1. 在例子4的基础上, D变成推荐B, E依然依赖于D</p>
<p><a href="http://www.igigo.net/wp-content/uploads/2010/06/abcd2.jpg"><img class="aligncenter size-full wp-image-94" title="abcd2" src="http://www.igigo.net/wp-content/uploads/2010/06/abcd2.jpg" alt="" width="423" height="680" /></a></p>
<pre class="brush: bash; title: ;">
apt-get remove C         将删除C, 同时提示你用apt-get autoremove去清除B
apt-get autoremove C     将删除B, C
aptitude remove C        将删除B, C
</pre>
<p>我的理解: 删除C, 而B没有被其他手动安装的包直接依赖或者间接依赖(我指那些一层层depend on的关系), D被E依赖<br />
所以B不是必要的,可以删除, 而D不能删除</p>
]]></content:encoded>
			<wfw:commentRss>http://www.igigo.net/archives/88/feed</wfw:commentRss>
		<slash:comments>3</slash:comments>
		</item>
		<item>
		<title>ssh无法通过公钥登录的问题</title>
		<link>http://www.igigo.net/archives/67</link>
		<comments>http://www.igigo.net/archives/67#comments</comments>
		<pubDate>Thu, 25 Mar 2010 10:30:36 +0000</pubDate>
		<dc:creator>igi</dc:creator>
				<category><![CDATA[小砸碎]]></category>
		<category><![CDATA[key]]></category>
		<category><![CDATA[linux]]></category>
		<category><![CDATA[ssh]]></category>

		<guid isPermaLink="false">http://www.igigo.net/?p=67</guid>
		<description><![CDATA[帮一师弟解决一个无法通过公钥登录ssh服务器问题, 顺便总结下 现象: test帐号使用key无法登录某ssh服务器, 而同机器下的test2帐号却可以登录, 两个帐号都可以通过密码登录 在排查了所有配置错误的可能后, 初步怀疑test帐号的权限设置出问题 test@client:~$ ls -l ~/.ssh/ -rw------- 1 test test 1675 2010-03-25 15:15 id_rsa test@server:~$ ls -l ~/.ssh/ -rw-r--r-- 1 test test 396 2010-03-25 15:15 authorized_keys 查看了客户端及服务器端的.ssh目录下的公钥与私钥权限, 可以看出, 并没有问题 私钥必须是600权限, 而公钥至少是644或者更严格的权限, 这都符合, 但依然无法登录 test@server:~$ ls -la ~ &#124; grep -w .ssh drwxr-xr-x 2 test test 4.0K 12-23 16:59 .ssh [...]]]></description>
			<content:encoded><![CDATA[<p>帮一师弟解决一个无法通过公钥登录ssh服务器问题, 顺便总结下</p>
<p>现象: test帐号使用key无法登录某ssh服务器, 而同机器下的test2帐号却可以登录, 两个帐号都可以通过密码登录</p>
<p><span style="color: #008000;">在排查了所有配置错误的可能后</span>, 初步怀疑test帐号的权限设置出问题</p>
<pre class="brush: bash; title: ;">
test@client:~$ ls -l ~/.ssh/
-rw------- 1 test test   1675 2010-03-25 15:15 id_rsa
</pre>
<pre class="brush: bash; title: ;">
test@server:~$ ls -l ~/.ssh/
-rw-r--r-- 1 test test    396 2010-03-25 15:15 authorized_keys
</pre>
<p>查看了客户端及服务器端的.ssh目录下的公钥与私钥权限, 可以看出, 并没有问题<br />
私钥必须是600权限, 而公钥至少是644或者更严格的权限, 这都符合, 但依然无法登录</p>
<pre class="brush: bash; title: ;">
test@server:~$ ls -la ~ | grep -w .ssh
drwxr-xr-x  2 test  test  4.0K 12-23 16:59 .ssh
</pre>
<p>查看了服务器端的.ssh目录权限, 是755, 也是没问题的, ssh服务器要求在使用key登录时.ssh目录的权限必须是其他用户不可写。<br />
一开始实在想不明为啥test2帐号使用key可以登录,test帐号使用key无法登录, ssh_config和sshd_config在检查了多遍后确实没有问题, 最后在服务器端对比两个帐号的不同时, 发现了可疑的地方</p>
<pre class="brush: bash; title: ;">
$ls -l /home/
drwxrwxrwx   3 test test 4096 2009-12-31 17:31 test
drwxr-xr-x   6 test2 test2 4096 2010-03-23 15:59 test2
</pre>
<p>两个帐号的home目录权限不同, test帐号是777, test2帐号是755, 会不会是这里不同导致的? 在服务器端把test目录修改成777后, 解决问题</p>
<h3>为啥home目录的权限也会影响ssh的key登录?</h3>
<p>
ssh服务器的key方式登录对权限要求严格。对于客户端: 私钥必须为600权限或者更严格权限(400), 一旦其他用户可读, 私钥就不起作用(如640), 表现为系统认为不存在私钥<br />
对于服务器端: 要求必须公钥其他用户不可写, 一旦其他用户可写(如660), 就无法用key登录, 表现为:Permission denied (publickey).<br />
同时要求.ssh目录其他用户不可写,一旦其他用户可写(如770), 就无法使用key登录, 表现为:Permission denied (publickey).</p>
<h3>但为什么home目录的可写也影响到ssh使用key登录?</h3>
<p>我们知道linux下目录也是文件, 目录其他用户可写,代表其他用户可以删除目录里的所有文件或子目录,重命名目录下的所有文件或子目录.<br />
home目录的可写,表示其他用户对.ssh子目录也有改写的权限(删除或重命令),也就导致ssh判断.ssh为其他用户可写, 拒绝使用key登录</p>
]]></content:encoded>
			<wfw:commentRss>http://www.igigo.net/archives/67/feed</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
	</channel>
</rss>

