October 6, 2009
在水木上看到这个帖子,本来觉得自己看过一遍Bash的manual已经对bash相当的了解了,没想到还有很多细节被忽略了,看来看manual和reference的时候,一定得相当的细心并且耐心才行啊…
说正事,如何显示shell脚本的最后一个参数呢?
$#这个bash内置变量记录了脚本接受到的参数个数,那么${$#}就应该可以显示最后一个参数了,可惜中括号里面是一个变量,bash作变量替换的时候,只进行一次扫描,那么上面的语法就被bash理解成了${name#substitute}这种语法了.
byang@byang-desktop:~$ echo $#
0
byang@byang-desktop:~$ echo $0
bash
byang@byang-desktop:~$ echo ${$#}
9033
byang@byang-desktop:~$ echo $$
9033
byang@byang-desktop:~$ echo ${$%}
9033
byang@byang-desktop:~$
如果要用如上方法,显示最后一个参数,那就只能让bash作两次变量替换,对,用eval。
byang@byang-desktop:~$ eval echo \${$#}
bash
byang@byang-desktop:~$
或者,使用bash提供的间接变量替换
byang@byang-desktop:~$ echo ${!#}
bash
byang@byang-desktop:~$
bash中以${!name}形式出现的变量替换,就是间接替换。bash首先,计算$name的值,并用它的值来替换中括号里面的值,再作一次变量替换。
这个语法,在bash的manual的一个小小的段落里面,真不明白这么重要的语法bash manual为什么不详细介绍一下。如果你在看bash manual的话,关于这种语法的介绍在3.5.3 Shell Parameter Expansion一节的第四段,或者可以打开bash manual,搜索indirect expansion,整个manual仅此一处,好好看看,别漏过去,呵呵…
Filed under:
Bash by Yang Bo
September 30, 2009
Bash通过/dev/proto/host/port这一方式,提供给用户直接通过最基本的read/write命令用proto指定的网络协议来访问host:port这个端口的能力。举个例子,我们通过tcp协议,来访问time.nist.gov的13端口来获得当前的网络时间:
cat </dev/tcp/time.nist.gov/13
或者,更复杂的,获取google的主页:
exec 3<>/dev/tcp/www.google.com/80
echo -e "GET / HTTP/1.1\r\nhost: http://www.google.com\r\nConnection: close\r\n\r\n" >&3
cat <&3
当然,/dev/proto这个字符串,Bash会负责解释,它并没有对应到真正的文件系统中的节点,所以,你不会在/dev目录下看到tcp这个文件,^_^
http://www.linuxjournal.com/content/more-using-bashs-built-devtcp-file-tcpip
Filed under:
Bash by Yang Bo
September 30, 2009
做日常的Linux管理,很多时候需要用bash写个CGI,确实很方便,下面的这个链接是个很不错的入门材料,在此记录一下:
http://foxlx.acmesystems.it/?id=165
Filed under:
Bash by Yang Bo
September 29, 2009
今天,尝试将一个操作防火墙的脚本加上setuid标志位,以让普通用户也能在一定条件下,通过认证,添加自己需要的防火墙规则,发现,在脚本之上的setuid标志位居然不起作用,后来search了一下,才知道,原来setuid和setgid都只能用在可执行的binary上,而不能在脚本之上的setuid和setgid无效。
想一想,这样貌似不太合理,究竟二进制文件和脚本文件有什么分别呢。linux内核执行二进制的时候,会检查其标志位,如果有setuid或者getgid,就会将进程的effetive user和effective group设置成相应的用户和组。当内核发现,要执行的不是一个二进制文件,而是一个脚本文件,内核就会读它的第一行,获得“#!”之后的字符串,作为解释器,为解释器启动进程,然后将脚本文件作为参数,传给解释器。貌似,这个过程,解释了,为什么脚本上设置的setuid没有作用,因为真正的脚本解释进程,并没有以相应的effective user来运行。但是,linux内核也完全可以以脚本setuid的user来运行解释器,但是内核没有这么做,这其中的原因,我暂时也没想明白,呵呵
下面这篇文章就是我搜到的,在此记录一下:
http://serverfault.com/questions/8449/cannot-set-uid-on-shell-scripts
Filed under:
Bash by Yang Bo
September 11, 2009
http://codex.wordpress.org/Excerpt
Filed under:
Bash by Yang Bo