在服务器上跑一些命令
经常都会用到简单的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
那这种写法也就不难理解了
就好像是敲入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”
这是我的服务器初始化系统里的一个东东
改写过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*.*“替换成空
问题提出:
作为系统管理员
经常需要在模拟终端上远程登上服务器做各种操作
而且很多时候需要同时用不同的窗口登上不同的服务器
当登上服务器太多的时候
就偶然会发现突然不知道哪个窗口登的是哪台服务器了
这可是个大问题
如果在错误的服务器里执行了特定命令
有时候后果是非常严重的
因而就想能否有种办法能让人一目了然的分辨出哪个窗口登陆的是哪台机器
因为我们分辨机器大多是靠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”
作为系统管理员
大概都有这种体会
管理的机器多了
经常同时用终端仿真程序连好几台机器
而且需要一会儿在这台上操作、一会儿又需要在那台机器上操作
很容易搞混机器:)
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]\\$ "
最近评论