存档

文章标签 ‘bash’

shell程序中for循环的一个小技巧

2009年12月2日 哈哈 没有评论

在服务器上跑一些命令
经常都会用到简单的shell也算是编程
用的比较多的是for语句

for i in a b c d; do

这样的
但当in后面的列表比较长的时候
往往就不知道怎么写了
今天偶尔翻到bash的faq(?貌似是这个)
发现如果后面是一系列有规律的数字的话可以这样处理:

for i in ((i = 0; i < 10000; i++ ))

这样就行
呵呵
再联想到bash下(())括起来的可以是运算
比如echo $((3+4))
输出是7
那这种写法也就不难理解了

分类: tips 标签: , , , ,

诡异现象:echo一个字串都会导致ssh sesion退出

2009年4月27日 哈哈 1 条评论

就好像是敲入exit命令或Ctrl+D一样
奇怪的是
在我的两台rhel as5的机器上有这个问题
在另外两台fedora core的机器上就没问题
貌似可能还不是echo的版本的问题(2台fc,一台是”echo (GNU coreutils) 5.2.1″,一台是”echo (GNU coreutils) 6.9″,都没问题)
两台有问题的rhel as5都是”echo (GNU coreutils) 5.97″

貌似跟shell有关系
我换了tcsh和 zsh都没问题
然后再敲bash回bash
再echo的话
就报”Segmentation fault”

linux下脚本取up的网络设备名

2009年1月13日 哈哈 没有评论

这是我的服务器初始化系统里的一个东东
改写过n多次
最早是写死2个设备:eth0和eth1
后来又用ip+grep+cut+awk写了个
最近改用ifconfig+sed了
就是这样:

ifconfig | sed -e ‘/\s*Link encap:Ethernet\s*.*/!d;s///’

这里为什么用ifconfig而不用ifconfig -a
因为我偶然发现ifconfig返回所有状态是up的网络设备
而如果是ifconfig -a的话,往往是连状态是down的网络设备都列出来
显然ifconfig的输出是我所要的

还有,这里比较诡异的是sed命令”s///
我就是这里怎么也没想明白
但是因为好用,就囫囵吞枣,直接用了
表面上讲
s///
的意思应该是把”空”替换成”空”
但实际上
这里的”s///“起到的作用是把前面比配到行里的匹配上的字符串”\s*Link encap:Ethernet\s*.*“替换成空

怎样用shell程序判断ip地址是否为内网地址(保留地址)

2009年1月5日 哈哈 没有评论

rfc里把以下ip地址作为保留地址

10.0.0.0 – 10.255.255.255 (10/8 prefix)
172.16.0.0 – 172.31.255.255 (172.16/12 prefix)
192.168.0.0 – 192.168.255.255 (192.168/16 prefix)

但是怎样在shell程序里判断一个ip是否是内网地址呢
我是这样搞的

#!/usr/bin/bash
function gennip ()
{
re=`echo $1 | awk -F. ‘{printf “%d”,$1*256^3+$2*256^2+$3*256+$4}’`
echo “$re”
}
ipn=`gennip $ip`
if [ $ipn -ge 167772160 -a $ipn -le 184549376 -o $ipn -ge 2130706432 -a $ipn -le 2147483648 -o $ipn -ge 2886729728 -a $ipn -le 2887778304 -o $ipn -ge 3232235520 -a $ipn -le 3232301056 ]; then
echo “it is a private ip addr!”
else
echo “it is have an internet ip addr”
fi

关于linux下bash的环境变量PROMPT_COMMAND

2008年4月21日 哈哈 1 条评论

问题提出

作为系统管理员
经常需要在模拟终端上远程登上服务器做各种操作
而且很多时候需要同时用不同的窗口登上不同的服务器
当登上服务器太多的时候
就偶然会发现突然不知道哪个窗口登的是哪台服务器了
这可是个大问题
如果在错误的服务器里执行了特定命令
有时候后果是非常严重的
因而就想能否有种办法能让人一目了然的分辨出哪个窗口登陆的是哪台机器
因为我们分辨机器大多是靠ip地址
就想能否在窗口的标题部分显示机器的ip就最好了

技术实现

bash支持环境变量PROMPT_COMMAND
将其设置为一个命令行字符串或者是包含命令行字符串的一个文件的文件名
命令行用来在显示prompt之前执行
而xterm又支持3种escape序列
可以用来更改xterm的“icon name”和”title”两者之其一或两者都改
还有
在redhat系列的机器上(redhat、fedora)
都支持文件/etc/sysconfig/bash-prompt-xterm来保存bash+xterm下的PROMPT_COMMAND环境变量的内容
结合这几点
我们就可以轻松实现“在窗口标题部分显示已登陆服务器的ip地址”这个功能
我当前用的是

echo -ne “\e]2;$(ifconfig | awk ‘/inet addr:/ && ! /inet addr:127\./ { sub (“addr:”, “”); print $2 }’ | sed -e :a -e ‘$!N;s/\n/\|/g;ta’):${PWD}\a”

这里的”\e]2″是xterm支持的第三种escape序列,用来设置窗口的标题
“$(.*)”的内容是shell命令,用来取出服务器的当前ip地址(除去127.x.x.x)列表,并用”|”连接起来
“${PWD}”是指当前的工作目录
“\a”是xterm支持的escape序列的结束符

引申一下

后来发现,所谓”xterm支持的3种escape序列”,基本上其他的term都支持
起码secure CRT里所带的term类型都支持(我测过)
而且redhat系列的服务器(redhat, fedora)除了支持/etc/sysconfig/bash-prompt-xterm外
还支持/etc/sysconfig/bash-prompt-screen、/etc/sysconfig/bash-prompt-default
用来存储当term类型是screen时和term类型不是xterm和screen时的PROMPT_COMMAND环境变量的值
于是乎

cp /etc/sysconfig/bash-prompt-xterm /etc/sysconfig/bash-prompt-default
cp /etc/sysconfig/bash-prompt-xterm /etc/sysconfig/bash-prompt-screen

这样的话
不管secure crt里term设成什么
都能在其标题里显示服务器ip

补充一下

为什么这里还有个term被设成screen的case呢
那是因为我们常用的命令screen
执行的时候会将环境变量PROMPT_COMMAND设成”screen”

在SecureCRT之类的终端仿真程序的标题显示远程server的全部ip地址

2005年8月27日 哈哈 1 条评论

作为系统管理员

大概都有这种体会

管理的机器多了

经常同时用终端仿真程序连好几台机器

而且需要一会儿在这台上操作、一会儿又需要在那台机器上操作

很容易搞混机器:)

bash通过环境变量PROMPT_COMMAND支持在显示提示符PS1之前执行命令

而且xterm的终端类型又支持更改标题

所以……呵呵

我用bash的环境变量PROMPT_COMMAND+xterm

可以说已经解决了这个问题

具体的方法是

vi /etc/sysconfig/bash-prompt-xterm

添加一行,像下面这样:

echo -ne "\e]2;$(/sbin/ip -4 -o addr show | awk ‘{print $4}’ | awk -F/ ‘{print $1}’ | grep -v "^127\." | sed -e :a -e ‘$!N;s/\n/\//g;ta’)\a"

如果终端显示模式不是xterm的话

需要用命令export TERM=xterm将终端显示模式设置成为xterm

即可

其实这个问题也有别的解决方法

把每台机器的hostname设成这台机器的ip

然后再通过环境变量PS1来把ip地址显示在提示符里

不过这需要把环境变量PS1中的\h改成\H

\H能显示完整的ip地址

\h只能显示一个字节

像这样:

export PS1="[@\H \W]\\$ "