shell 编程的一些 Tips
本文主要总结编写 shelll 脚本时会遇到的一些坑,另外总结 shell 编程中如何实现外部传参。
shell 编程
注意事项
.sh 文件头部需要添加如下信息,笔者曾因为漏写了 bin 前面的/,执行时出现各种未知问题。
#!/bin/bash
注意.sh 文件的编码格式,打开.sh 文件
vim example.sh
不进入.sh 文件的编辑模式,输入如下命令然后回车查看文件格式
:set ff
文件编码的格式必须如下所示,为 unix 类型。如果是 dos 类型,执行脚本时可能会报错。
fileformat=unix
注意重定向和追加的区别
# 将输出内容重定向至 test.log,此时 test.log 内容被覆盖为新内容。
$ echo "This is a Test." > /var/test.log
# 追加到 test.log 文件的内容后,不覆盖原有内容
$ echo "Test for >>" >> /var/test.log
常用函数理解
shift 函数
主要用来左移位置参数。比如执行 shift 2 命令表示将原来的外部参数\$3 变成\$1,原来的\$1 和\$2 被丢弃。而不带参数的 shift 命令相当于 shift 1。创建 test_shift.sh 文件,内容如下所示。
#!/bin/sh
until [$# -eq 0]
do
echo "第一个参数为:$1,参数个数为:$#"
shift
done
执行脚本
./test_shift.sh a b c d
getopt 函数
这里讲的 getopt 函数其实就是 Linux 系统的 getopt 命令,它主要用来传递参数,支持长参数和短参数。
在 Linux 命令中,给命令附上不同的参数,命令能够实现不同的功能,比如下面的例子。
ls -l
有时候我们需要在自己写的 shell 脚本上实现外部传参时,就需要用到 getopt 这个函数。执行如下命令查看帮助信息。比较常用的的是-a,-l,-o 等选项。
$ getopt -h
Usage:
getopt <optstring> <parameters>
getopt [options] [--] <optstring> <parameters>
getopt [options] -o|--options <optstring> [options] [--] <parameters>
Parse command options.
Options:
-a, --alternative allow long options starting with single -
-l, --longoptions <longopts> the long options to be recognized
-n, --name <progname> the name under which errors are reported
-o, --options <optstring> the short options to be recognized
-q, --quiet disable error reporting by getopt(3)
-Q, --quiet-output no normal output
-s, --shell <shell> set quoting conventions to those of <shell>
-T, --test test for getopt(1) version
-u, --unquoted do not quote the output
-h, --help display this help
-V, --version display version
-o 后面为短参数,-l 后面为长参数。具体这两者没什么区别。不过按照约定俗称,-后面接单个字母不带参数值,–后面接单词,带参数值。例如下面内容所示,其中短参数 t 后面可以带参数值,而长参数 help,version 不能带参数值。
argv=`getopt -a -o hv,t: -l name:,age:,help,version -- $@`
eval set -- $argv
创建 test_getopt.sh 文件,内容如下所示
#!/bin/sh
#
argv=`getopt -a -o hv -l name:,age:,help,version -- $@`
#将符合 getopt 参数规则的参数摆在前面,其他摆在后面,并在最后面添加--
eval set -- $argv
#help 函数,打印此 shell 脚本的帮助信息
help()
{
Usage="Usage: $0\n\
options:\n\
[--name] \t ---your name\n \
[--age] \t ---your age\n \"
}
#函数,打印此 shell 脚本的版本
show_version()
{
echo "Version1.0"
}
#给定参数默认参数值
Name=""
Age=0
#解析外部传参数,将外部传入的参数值赋给内部变量
while true
do
case $i in:
--name)
Name=$2
shift 2
;;
--age)
Age=$2
shift 2
;;
-h | --help)
help
shift
;;
-v | --version)
show_version
shitf
;;
--)
break
;;
esac
done
if [-n $Name -a $Age -eq 0]
then
echo "Hello,My Name is $Name."
elif [-n $Name -a $Age -nq 0]
then
echo "Hello,My Name is $Name.I am $Age"
fi
外部传参并执行 test_getopt.sh 文件
$ chmod +x test_getopt.sh
$ ./test_getopt.sh -h
$ ./test_getopt.sh --name Alan --age 19
代码实例
实例一
#!/bin/sh
#config_W522U.sh
# ---------------------------------------------------------------------#
# Description: 配置 W522U 网卡
#
# History:
# <author> <time> <version > <desc>
# ---------------------------------------------------------------------#
help()
{
Usage="Usage: $0\n\
Options:\n\
[--intf if_name] \t-- W522U 接口名称,默认为 ra0\n \
[--scan 2.4/5] \t-- 扫描无线列表信息(扫描 2.4G 或 5G 无线列表)\n \
[--ssid ssid] \t\t-- 连接 SSID\n \
[--workhz 2.4/5] \t-- 连接无线的频段,默认 2.4G\n \
[--channel 信道] \t-- 设置信道\n \
[--authmode mode] \t-- 认证模式 取值范围\"OPEN, SHARED, WPAPSK, WPA2PSK\"\n \
[--encryptype type] \t-- 加密类型 取值范围\"NONE, TKIP, AES, WEP\"\n \
[--wpapsk wpa 密码] \t-- WPA 密码\n \
[--defkeyid num] \t-- wep 默认密码\n \
[--key1 wep 密码 1] \t-- wep 密码 1\n \
[--key2 wep 密码 2] \t-- wep 密码 2\n \
[--key3 wep 密码 3] \t-- wep 密码 3\n \
[--key4 wep 密码 4] \t-- wep 密码 4\n \
[-h | --help] \t\t-- 显示此帮助信息\n \
"
echo -e $Usage
}
#定义公共变量
normal='\033[0m';red='\033[31m';green='\033[32m';yellow='\033[33m'
Intf="ra0"
Scan="0"
WorkHz="2.4"
SSID=""
Channel=""
AuthMode="OPEN"
EncrypType="NONE"
WpaPsk=""
DefKeyId="1"
Key1="12345"
Key2="12345"
Key3="12345"
Key4="12345"
#定义选项变量
OPTIND=1
argv=`getopt -a -o h -l intf:,scan:,ssid:,channel:,workhz:,authmode:,encryptype:,wpapsk:,defkeyid:,key1:,key2:,key3:,key4:,help -- $@`
#[ $? -ne 0 ] && (help;exit 127)
if [ "$?" != "0" ]
then
help
exit 127
fi
eval set -- $argv
while true
do
case "$1" in
--intf)
Intf=$2
shift 2
;;
--scan)
if [ "$2" == "2.4" -o "$2" == "5" ]
then
Scan=$2
else
help
exit 0
fi
shift 2
;;
--ssid)
SSID=$2
shift 2
;;
--channel)
Channel=$2
shift 2
;;
--workhz)
WorkHz=$2
shift 2
;;
--authmode)
AuthMode=$2
shift 2
;;
--encryptype)
EncrypType=$2
shift 2
;;
--wpapsk)
WpaPsk=$2
shift 2
;;
--defkeyid)
DefKeyId=$2
shift 2
;;
--key1)
Key1=$2
shift 2
;;
--key2)
Key2=$2
shift 2
;;
--key3)
Key3=$2
shift 2
;;
--key4)
Key4=$2
shift 2
;;
-h | --help)
help
exit 0
shift
;;
--)
break
;;
esac
done
:<<BLOCK
echo -e ${green}
echo Scan=$Scan
echo SSID=$SSID
echo WorkHz=$WorkHz
echo AuthMode=$AuthMode
echo EncrypType=$EncrypType
echo WpaPsk=$WpaPsk
echo DefKeyId=$DefKeyId
echo Key1=$Key1
echo Key2=$Key2
echo Key3=$Key3
echo Key4=$Key4
echo -e ${normal}
BLOCK
ifconfig $Intf up
if [ "$Scan" != "0" ]
then
WirelessMode=`iwpriv $Intf show WirelessMode |awk '{print $3}'`
case $WirelessMode in
"11B")
WirelessMode="1"
;;
"11A")
WirelessMode="2"
;;
"11A/B/G")
WirelessMode="3"
;;
"11G")
WirelessMode="4"
;;
"11A/B/G/N")
WirelessMode="5"
;;
"11N")
WirelessMode="6"
;;
"11G/N")
WirelessMode="7"
;;
"11A/N")
WirelessMode="8"
;;
"11B/G/N")
WirelessMode="9"
;;
"11A/G/N")
WirelessMode="10"
;;
esac
SSID=`iwpriv $Intf show SSID |awk '{print $3}'`
AuthMode=`iwpriv $Intf show AuthMode |awk '{print $3}'`
EncrypType=`iwpriv $Intf show EncrypType |awk '{print $3}'`
WpaPsk=`iwpriv $Intf show WPAPSK |awk '{print $5}'`
DefKeyId=`iwpriv $Intf show DefaultKeyID |awk '{print $3}'`
Key1=`iwpriv $Intf show Key1 |awk '{print $3}'`
Key2=`iwpriv $Intf show Key2 |awk '{print $3}'`
Key3=`iwpriv $Intf show Key3 |awk '{print $3}'`
Key4=`iwpriv $Intf show Key4 |awk '{print $3}'`
iwpriv $Intf set SSID=""
:<<BLOCK
echo -e ${yellow}
echo WirelessMode=$WirelessMode
echo SSID=$SSID
echo AuthMode=$AuthMode
echo EncrypType=$EncrypType
echo WpaPsk=$WpaPsk
echo DefKeyId=$DefKeyId
echo Key1=$Key1
echo Key2=$Key2
echo Key3=$Key3
echo Key4=$Key4
echo -e ${normal}
BLOCK
if [ "$Scan" == "2.4" ]
then
iwpriv $Intf set WirelessMode="9"
iwpriv $Intf set CountryRegion="5"
else
iwpriv $Intf set WirelessMode="8"
iwpriv $Intf set CountryRegion="7"
fi
echo -e ${green}"正在使用 W522U 扫描${Scan}G 无线信号..."${normal}
#sleep 2
#iwpriv $Intf set SiteSurvey="1"
sleep 4
iwpriv $Intf get_site_survey
iwpriv $Intf set WirelessMode="${WirelessMode}" &>/dev/null
iwpriv $Intf set SSID="${SSID}" &>/dev/null
iwpriv $Intf set CountryRegionABand="7" &>/dev/null
iwpriv $Intf set CountryRegion="5" &>/dev/null
iwpriv $Intf set AuthMode="${AuthMode}" &>/dev/null
iwpriv $Intf set EncrypType="${EncrypType}" &>/dev/null
iwpriv $Intf set WPAPSK="${WpaPsk}" &>/dev/null
iwpriv $Intf set DefaultKeyID="${DefKeyId}" &>/dev/null
iwpriv $Intf set Key1="${Key1}" &>/dev/null
iwpriv $Intf set Key2="${Key2}" &>/dev/null
iwpriv $Intf set Key3="${Key3}" &>/dev/null
iwpriv $Intf set Key4="${Key4}" &>/dev/null
exit 0
fi
if [ "$WorkHz" == "2.4" ]
then
iwpriv $Intf set WirelessMode="9"
else
iwpriv $Intf set WirelessMode="8"
fi
if [ "$Channel" != "" ]
then
iwpriv $Intf set Channel="${Channel}" &>/dev/null
fi
iwpriv $Intf set SSID="${SSID}" &>/dev/null
iwpriv $Intf set CountryRegionABand="7" &>/dev/null
iwpriv $Intf set CountryRegion="5" &>/dev/null
iwpriv $Intf set AuthMode="${AuthMode}" &>/dev/null
iwpriv $Intf set EncrypType="${EncrypType}" &>/dev/null
iwpriv $Intf set WPAPSK="${WpaPsk}" &>/dev/null
iwpriv $Intf set DefaultKeyID="${DefKeyId}" &>/dev/null
iwpriv $Intf set Key1="${Key1}" &>/dev/null
iwpriv $Intf set Key2="${Key2}" &>/dev/null
iwpriv $Intf set Key3="${Key3}" &>/dev/null
iwpriv $Intf set Key4="${Key4}" &>/dev/null
echo -e ${green}"正在使用 W522U ${WorkHz}G 连接 SSID:${SSID}"${normal}
suctime=0
for((i=1;i<=45;i++))
do
result=`iwpriv $Intf connStatus |grep Disconnected |wc -m`
if [ "$result" == "0" ]
then
suctime=`expr $suctime + 1`
if [ "$suctime" -ge "3" ]
then
break
fi
fi
sleep 1
done
iwpriv $Intf connStatus
if [ "$i" -ge "46" ]
then
echo Link Fail
else
echo Link Suc
fi
exit 0
实例二
主要实现配置 PPPoE server 的参数。
#!/bin/sh
#config_PppoeSerCfg.sh
# ---------------------------------------------------------------------#
# FileName: config_PppoeSerCfg.sh
# Version: V1.0
# Description: 编辑 PPPoE 服务器配置文件
#
# History:
# <author> <time> <version > <desc>
# ---------------------------------------------------------------------#
help()
{
Usage="Usage: config_PppoeSerCfg.sh\n\
Options:\n\
[--auth pap|chap|mschap|mschap-v2] \t-- 配置认证方式,默认为 chap 加密\n \
[--mppe type] \t\t\t\t-- MPPE 加密要求,type[40,128,both],若开启此选项,认证协议将自动使用 mschap-v2 协议\n \
[--mtu num] \t\t\t\t-- 配置 MTU 值选项\n \
[--mru num] \t\t\t\t-- 配置 MRU 值选项,0 为拒绝协商\n \
[--echointerval num] \t\t\t-- 配置维链次数选项,默认 12\n \
[--echofailure num] \t\t\t-- 配置维链失败次数选项,默认 8s\n \
[--dns dnsip] \t\t\t\t-- 配置下发的 DNS 地址\n \
[--wins winsip] \t\t\t-- 配置下发的 WINS 地址\n \
[--custom args] \t\t\t-- 添加自定义参数,按 pppoe-server 配置文件格式即可\n \
[-o options file] \t\t\t-- 输出到配置文件(默认:/etc/ppp/pppoe-options\n \
[-h | --help] \t\t\t\t-- 显示此帮助信息\n \
"
echo -e $Usage
}
#定义公共变量
normal='\033[0m';red='\033[31m';green='\033[32m';yellow='\033[33m'
tmp=0
AUTH=chap
MPPE=""
MRU=""
MTU=""
EchoInterval=12
EchoFailure=8
DNS=""
dnsnum=0
WINS=""
winsnum=0
CUSTOM="" #自定义参数
customnum=0
OPTDIR=""
#定义配置文件
PPPOESEROPT=/etc/ppp/pppoe-server-options
#定义选项变量
OPTIND=1
argv=`getopt -a -o o:,h -l auth:,mppe:,mtu:,mru:,echointerval:,echofailure:,dns:,wins:,custom:,help -- $@`
#[ $? -ne 0 ] && (help;exit 127)
if [ "$?" != "0" ]
then
help
exit 127
fi
eval set -- $argv
while true
do
case "$1" in
--auth)
if [ $2 == pap -o $2 == chap -o $2 == mschap -o $2 == mschap-v2 ]
then
AUTH=$2
else
help
exit 0
fi
shift 2
;;
--mppe)
if [ $2 == 40 -o $2 == 128 -o $2 == both ]
then
MPPE=$2
else
help
exit 0
fi
shift 2
;;
--mtu | --mru | --echointerval | --echofailure)
expr $2 + 1 &>/dev/null
if [ $? -eq 0 ]
#if [ `echo $2 |grep [0-9]` ]
then
case "$1" in
--mtu)
MTU=$2
;;
--mru)
MRU=$2
;;
--echointerval)
EchoInterval=$2
;;
--echofailure)
EchoFailure=$2
;;
--)
break
;;
esac
else
help
exit 0
fi
shift 2
;;
--dns)
DNS[$dnsnum]=$2
dnsnum=`expr $dnsnum + 1`
shift 2
;;
--wins)
WINS[$winsnum]=$2
winsnum=`expr $winsnum + 1`
shift 2
;;
--custom)
CUSTOM[customnum]=$2
customnum=`expr $customnum + 1`
shift 2
;;
-o)
PPPOESEROPT=$2
shift 2
;;
-h | --help)
help
exit 0
shift
;;
--)
break
;;
esac
done
echo -e ${green}auth=$AUTH
echo MPPE=$MPPE
echo MTU=$MTU
echo MRU=$MRU
echo EchoInterval=$EchoInterval
echo EchoFailure=$EchoFailure
for((i=0;i<$dnsnum;i++))
do
echo DNS[$i]=${DNS[$i]}
done
for((i=0;i<$winsnum;i++))
do
echo WINS[$i]=${WINS[$i]}
done
for((i=0;i<customnum;i++))
do
echo CUSTOM[$i]=${CUSTOM[$i]}
done
echo PPPOESEROPT=$PPPOESEROPT
echo -e ${normal}
#重新创建配置文件
OPTDIR=`expr ${PPPOESEROPT%/*}`
mkdir -p ${OPTDIR}
rm -rf $PPPOESEROPT
echo "# PPP options for the PPPoE server" > $PPPOESEROPT
echo "# LIC: GPL" >> $PPPOESEROPT
if [ $MPPE ]
then
echo "refuse-pap" >> $PPPOESEROPT
echo "refuse-chap" >> $PPPOESEROPT
echo "refuse-mschap" >> $PPPOESEROPT
echo "require-mschap-v2" >> $PPPOESEROPT
if [ $MPPE == "both" ]
then
echo "require-mppe" >> $PPPOESEROPT
else
echo "require-mppe-${MPPE}" >> $PPPOESEROPT
fi
else
case "$AUTH" in
pap)
echo "require-pap" >> $PPPOESEROPT
echo "refuse-chap" >> $PPPOESEROPT
echo "refuse-mschap" >> $PPPOESEROPT
echo "refuse-mschap-v2" >> $PPPOESEROPT
;;
chap)
echo "refuse-pap" >> $PPPOESEROPT
echo "require-chap" >> $PPPOESEROPT
echo "refuse-mschap" >> $PPPOESEROPT
echo "refuse-mschap-v2" >> $PPPOESEROPT
;;
mschap)
echo "refuse-pap" >> $PPPOESEROPT
echo "refuse-chap" >> $PPPOESEROPT
echo "require-mschap" >> $PPPOESEROPT
echo "refuse-mschap-v2" >> $PPPOESEROPT
;;
mschap-v2)
echo "refuse-pap" >> $PPPOESEROPT
echo "refuse-chap" >> $PPPOESEROPT
echo "refuse-mschap" >> $PPPOESEROPT
echo "require-mschap-v2" >> $PPPOESEROPT
;;
*)
echo "refuse-pap" >> $PPPOESEROPT
echo "require-chap" >> $PPPOESEROPT
echo "refuse-mschap" >> $PPPOESEROPT
echo "refuse-mschap-v2" >> $PPPOESEROPT
;;
esac
fi
if [ $MRU ]
then
if [ $MRU == 0 ]
then
echo "-mru" >> $PPPOESEROPT
else
echo "mru $MRU" >> $PPPOESEROPT
fi
fi
if [ $MTU ]
then
echo "mtu $MTU" >> $PPPOESEROPT
fi
echo "lcp-echo-interval $EchoInterval" >> $PPPOESEROPT
echo "lcp-echo-failure $EchoFailure" >> $PPPOESEROPT
for((i=0;i<$dnsnum;i++))
do
echo "ms-dns ${DNS[$i]}" >> $PPPOESEROPT
done
for((i=0;i<$winsnum;i++))
do
echo "ms-wins ${WINS[$i]}" >> $PPPOESEROPT
done
for((i=0;i<$customnum;i++))
do
echo "${CUSTOM[$i]}" >> $PPPOESEROPT
done
exit 0
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
上一篇: scapy 包总结
下一篇: 彻底找到 Tomcat 启动速度慢的元凶
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论