Linux学习心得:细细品味shell脚本中的细节与用户体验 ^_^
2011-07-26 22:24
871 查看
学习Linux已经有一周半了,在马哥的强压下,写了二十几个shell脚本。。。shell正则表达式,awk语句,程序执行流,test语句,sed语句,函数还有一些其他的小命令,如tr,grep,cut,wc等等。越发觉得shell脚本的可爱,没错,是可爱!因为它的快速上手,迷人的正则表达式,变换莫测的程序执行流和awk语句,还有强大的功能,很难想象这么简单的语言和linux如此完美的结合在一起,好像是linux的可爱的“妻子”。
听马哥说,中国的程序员并不是不如印度,国际上很多编程大赛,中国程序员都拿奖,但是软件外包却不如印度。并不是他们编的程序好,而是中国的程序员编程有点“豆腐渣程——只把要求实现的功能都实现了,其他的不管了。。。同样是一个小程序,印度人可能写几百行,上前行,而中国人只写几十行。。并不是人家不能写那么短,而是为了“用户体验”。
废话不说了,切入正题。
###########################
shell脚本中的细节:
首先是变量的运用:有时候我们不得不多次输入一个路径,这个时候我们就可以把路径定义成变量,例如:FILE=/etc/passwd,在使用时用$FILE引用即可。这个技巧很好用,但是当一个脚本有多个路径或多个变量的时候,变量的名字会容易记混,或者打错。所以,在我看来变量的使用原则如下:
1. 尽量避免引用过多的变量,不能贪多,否则整个脚本充满了变量,反而不易读懂。
2. 变量是用来使整个脚本变的方便的,所有应该是出现多次的参数才需要变量来引用。
3. 变量的名字应该易读,易记,易输入,尽量避免过于相似的变量。
4. 有些时候,变量需要在一个脚本中被多次重新赋值,但要注意使用,否则容易出错。
所有的语句都需要精简吗?
以前我一直认为,代码要短越好,这样执行效率会更高,但是现在有一个问题,再好的代码,如果容易“崩溃”的话,再精简有什么用?有些时候,不得不在完成程序功能的基础上考虑程序的可用性。比如当用户输入错误怎么办,用户中突退出怎么办,用户输入的数据怎么是否需要验证。比如,你一个不懂网络知识的人误将IP地址和GATEWAY设为不同的网段,那么这个操作就会造成无法接入互联网。举个例子
写一个脚本:
1、提示用户选择所要设置的网卡;
2、提示用户使用dhcp或者static作为选定网卡的BOOTPROTO
a、如果用户选择dhcp,则将其配置文件中的BOOTPROTO的值设为dhcp,而后重启此网卡;
b、如果用户选择static,则将其配置文件中的BOOTPROTO的值设为static,并提示用户输入IP地址,子网掩码和网关;其中网关可以为空,但IP地址或子网掩码不能为空;设置完成后重启此网卡;
3、无论上述动态或静态设定,设定完成后将网卡IP地址设定后信息再次显示给用户;
我们来分析:这个程序的功能其实很简单,只要求能够识别用户的输入信息是dhcp还是static,然后进行相应的设置,但是我来考虑:
考虑:1、如果用户没有做出任何修改之前就不想设置了,如何退出?
2、如果用户已经设定了一些信息,如IP地址等却又不想设置了,而使用了Ctrl+c,如何处置?
3、如果用户输入的是错误的IP信息怎么办?
4、如果用户输入的是错误的NETMASK怎么办?
5、如果用户输入的是不匹配的IP和GATEWAY怎么办?
6、如果用户输入的信息已经存在怎么办?
7、用户输入的网卡是否存在?
8、万一网卡重启发生错误怎么办?
整个代码如下
听马哥说,中国的程序员并不是不如印度,国际上很多编程大赛,中国程序员都拿奖,但是软件外包却不如印度。并不是他们编的程序好,而是中国的程序员编程有点“豆腐渣程——只把要求实现的功能都实现了,其他的不管了。。。同样是一个小程序,印度人可能写几百行,上前行,而中国人只写几十行。。并不是人家不能写那么短,而是为了“用户体验”。
废话不说了,切入正题。
###########################
shell脚本中的细节:
首先是变量的运用:有时候我们不得不多次输入一个路径,这个时候我们就可以把路径定义成变量,例如:FILE=/etc/passwd,在使用时用$FILE引用即可。这个技巧很好用,但是当一个脚本有多个路径或多个变量的时候,变量的名字会容易记混,或者打错。所以,在我看来变量的使用原则如下:
1. 尽量避免引用过多的变量,不能贪多,否则整个脚本充满了变量,反而不易读懂。
2. 变量是用来使整个脚本变的方便的,所有应该是出现多次的参数才需要变量来引用。
3. 变量的名字应该易读,易记,易输入,尽量避免过于相似的变量。
4. 有些时候,变量需要在一个脚本中被多次重新赋值,但要注意使用,否则容易出错。
所有的语句都需要精简吗?
以前我一直认为,代码要短越好,这样执行效率会更高,但是现在有一个问题,再好的代码,如果容易“崩溃”的话,再精简有什么用?有些时候,不得不在完成程序功能的基础上考虑程序的可用性。比如当用户输入错误怎么办,用户中突退出怎么办,用户输入的数据怎么是否需要验证。比如,你一个不懂网络知识的人误将IP地址和GATEWAY设为不同的网段,那么这个操作就会造成无法接入互联网。举个例子
写一个脚本:
1、提示用户选择所要设置的网卡;
2、提示用户使用dhcp或者static作为选定网卡的BOOTPROTO
a、如果用户选择dhcp,则将其配置文件中的BOOTPROTO的值设为dhcp,而后重启此网卡;
b、如果用户选择static,则将其配置文件中的BOOTPROTO的值设为static,并提示用户输入IP地址,子网掩码和网关;其中网关可以为空,但IP地址或子网掩码不能为空;设置完成后重启此网卡;
3、无论上述动态或静态设定,设定完成后将网卡IP地址设定后信息再次显示给用户;
我们来分析:这个程序的功能其实很简单,只要求能够识别用户的输入信息是dhcp还是static,然后进行相应的设置,但是我来考虑:
考虑:1、如果用户没有做出任何修改之前就不想设置了,如何退出?
2、如果用户已经设定了一些信息,如IP地址等却又不想设置了,而使用了Ctrl+c,如何处置?
3、如果用户输入的是错误的IP信息怎么办?
4、如果用户输入的是错误的NETMASK怎么办?
5、如果用户输入的是不匹配的IP和GATEWAY怎么办?
6、如果用户输入的信息已经存在怎么办?
7、用户输入的网卡是否存在?
8、万一网卡重启发生错误怎么办?
整个代码如下
#!/bin/bash #创建临时文件和标识 FLAG=0 TMPFILE=`mktemp /tmp/eth.XXXXXXXX` #读取用户输入 read -p "Interface: " ETHCARD #判定用户输入的网卡是否存在 ALLECARD=`ifconfig -a | awk '/^[^[:space:]l]/{print $1}'` until echo $ALLECARD | grep "$ETHCARD" &> /dev/null; do echo -e "\033[31mWrong Card name.\033[0m" read -p "Interface: " ETHCARD done #网卡路径的变量,以后要多次应用 ETHFILE=/etc/sysconfig/network-scripts/ifcfg-$ETHCARD #判定用户输入的协议是否正确 read -p "Boot Protocol: " MYBOOTPROTO until echo $MYBOOTPROTO | grep -E "dhcp|static" &> /dev/null ; do echo -e "\033[31mWrong BOOTPROTO.\033[0m" read -p "Boot Protocol: " MYBOOTPROTO done #判定DHCP和static if [ "$MYBOOTPROTO" == "dhcp" ]; then sed -i "s/^BOOTPROTO=.*/BOOTPROTO=dhcp/g" $ETHFILE if [ $? -eq 0 ]; then ifdown $ETHCARD && ifup $ETHCARD [ $? -eq 0 ] && echo "Set $ETHCARD done." fi elif [ "$MYBOOTPROTO" == "static" ]; then cat $ETHFILE > $TMPFILE read -p "Ip Address: " MYIP #判定IP的正确性 until [[ $MYIP =~ ^([1-9]|[1-9][0-9]|1[0-9]{1,2}|2[01][0-9]|22[0-3])(\.([0-9]|[1-9][0-9]|1[0-9]{2}|2[0-4][0-9]|25[0-4])){2}(\.([1-9]|[1-9][0-9]|1[0-9]{2}|2[0-4][0-9]|25[0-4]))$ ]];do echo -e "\033[31mWrong IP.\033[0m" read -p "Ip Address: " MYIP done #判定NETMASK的正确性 read -p "Netmask: " MYNM until [[ $MYNM =~ ^255(\.(0|255)){3}$ ]]; do echo -e "\033[31mWrong NetMask.\033[0m" read -p "Netmask: " MYNM done read -p "Gateway: " MYGW #判定IP与GATEWAY的匹配 for I in {1..4}; do [ $[`echo $MYIP | cut -d. -f $I`&`echo $MYNM | cut -d. -f $I`] -ne $[`echo $MYGW | cut -d. -f $I`&`echo $MYNM | cut -d. -f $I`] ] && FLAG=1 && break done until [[ $MYGW =~ ^([1-9]|[1-9][0-9]|1[0-9]{1,2}|2[01][0-9]|22[0-3])(\.([0-9]|[1-9][0-9]|1[0-9]{2}|2[0-4][0-9]|25[0-4])){2}(\.([1-9]|[1-9][0-9]|1[0-9]{2}|2[0-4][0-9]|25[0-4]))$ ]] && [ $FLAG -eq 0 ];do echo -e "\033[31mWrong GateWay.\033[0m" read -p "Gateway: " MYGW for I in {1..4}; do [ $[`echo $MYIP | cut -d. -f $I`&`echo $MYNM | cut -d. -f $I`] -ne $[`echo $MYGW | cut -d. -f $I`&`echo $MYNM | cut -d. -f $I`] ] && FLAG=1 && break || FLAG=0 done done #文件里信息是否存在,调用临时文件 sed -i "s/^BOOTPROTO=.*/BOOTPROTO=static/g" $TMPFILE grep "^IPADDR=" $TMPFILE &> /dev/null && sed -i "s/IPADDR=.*/IPADDR=$MYIP/" $TMPFILE || echo "IPADDR=$MYIP" >> $TMPFILE grep "^NETMASK=" $TMPFILE &> /dev/null && sed -i "s/NETMASK=.*/NETMASK=$MYNM/" $TMPFILE || echo "NETMASK=$MYNM" >> $TMPFILE if [ -z $MYGW ]; then sed -i '/^GATEWAY=.*/d' $TMPFILE else grep "^GATEWAY=" $TMPFILE &> /dev/null && sed -i "s/GATEWAY=.*/GATEWAY=$MYGW/" $TMPFILE || echo "GATEWAY=$MYGW" >> $TMPFILE fi cp -f $TMPFILE $ETHFILE ifdown $ETHCARD && ifup $ETHCARD [ $? -eq 0 ] && echo "Set $ETHCARD done." else echo "No such options." exit 1 fi #删除临时文件,避免临时文件过多 rm -f $TMPFILE
相关文章推荐
- Linux系统命令及Shell脚本学习笔记二:用户管理
- Linux学习-shell脚本编程基础之处理用户输入
- Linux-Shell脚本学习心得之批量创建、删除用户
- Linux-Shell脚本学习心得(第二天)
- shell脚本学习笔记:通过shell实现linux用户管理和监控
- Linux-Shell脚本学习心得(若干天后)
- Linux学习日志(11))- 写个切换目录的小shell脚本
- linux学习(四) shell脚本(1)
- [Linux学习]Shell脚本(1)--函数,输入,if判断(持续更新)+删除空行 +保存当前路径
- linux下shell脚本学习
- Linux下查看所有用户(shell脚本获取)
- 脚本学习python和linux-shell和jQuery(javascript)
- linux学习(九) shell脚本(6)
- 我的linux学习8 shell脚本
- Linux系统命令及Shell脚本学习笔记四:Linux文件系统
- shell脚本学习:不得不细心之sed和grep,sort和uniq,从细节看“认真”
- Linux 系统学习 之 shell脚本学习
- linux学习笔记-第十二课-Shell脚本之正则表达式(一)
- Linux学习之学习shell脚本续写2
- Linux系统Shell脚本的入门学习