在此记录下自己的一些经验:
Bash
A.关联数组参数传递。
关联数组在bash中是无法Export的,无法export也就无法进行大量的参数传递。
可以有几种办法来解决这个问题:
1. 如果是主体与内部函数之间传递,可以用eval模拟引用的方式解决。
2. 如果是进程和子进程之间,只将数据转化成参数[K1]=V1 [K2]=V2 [K3]=V3 的模式,到子进程内部进行再组合。返回也是用这种形式,用assocArray=($@)进行重构。
B. bash FUNCNAME数组
在写日志的时候,需要将信息的传递者体现出来,由于日志的输出方式基本都放在一个子函数中,在FUNCNAME功能还没出来的时候,基本都是这样调用:
logmsg $debuglevel $funcname $msg
使用FUNCNAME后:
这样用
logmsg $debuglevel $msg
内部如何知道是谁发出的消息呢?
FUNCNAME是一个bash提供的系统Call Stack Array,所以每加一个Caller就从左向右shift进这个函数的名字。
这样就容易了:
只要${FUNCNAME[0]}, 永远是当前的子函数名字。那么${FUNCNAME[1]},就是Caller的名字。
所以,使用该功能后,程序结构变更简洁清晰了。
C. 数组操作
普通数组和关联数组,区别
普通数组,index是整数
关联数组,index是string,value是另一个string
declare -A aArray
declare -a iArray
清空
aArray=()
iArray=()
访问方式:
直接分配元素
aArray=([S]=V1 [S]=V2 ... )
iArray=(V1 V2 ....)
在尾部添加
iArray+=(nv1 nv2 ...)
提取一个元素值
A=${iArray[N]}
A=${aArray[Key]}
提取所有元素值
${iArray[@]} "${iArray[@]}" ${iArray[*]} "${iArray[*]}"
${aArray[@]} "${aArray[@]}" ${aArray[*]} "${aArray[*]}"
数据分片提取,类似python slicing功能:
提取部分元素,Index 从M开始的N个元素(包含iArray[M])
${iArray[@]:M:N}
${iArray[@]:M} 返回从M号元素到数据最后一个元素
数组元数据操作:
${#iArray[N]} 提取index为N的数组成员的String长度
${#aArray[String]} 提取key为String的aArray数组成员String长度
${#iArray[@]} ${#aArray[*]} 返回数据元素个数
${!aArray[@]} 返回Key值组成的数组
删除数组:
unset -v iArray; unset -v aArray
unset -v iArray[@]; unset -v aArray[*]
删除一个数组元素:
unset -v iArray[N]; unset -v aArray[String]
Korn shell
由于Korn shell的一些优秀功能,使korn shell在programming的群中非常受欢迎,不是bash不好,而是只有korn shell才行。
但是没办法,bash已经成为linux的事实标准,korn只能成为骨灰级玩家的工具了。ksh93还是需要单独安装的。一般在比较重要的场合才会用一下。
A. lastpipe和命名管道
ksh天生的lastpipe功能,加上netcat+命名管道可以实现网络服务器双向通信的简单构架,在极其有限的资源环境中,可以构架简单实用的服务器进行验证测试。
使用如下结构:
点击(此处)折叠或打开
-
while :; do
-
( cat namedpipe | while read line:; do
-
processRequestbyLine $line;
-
) | netcat -lp $port >namedpipe
-
done
B:支持天生的数据用户自定义数据类型,可以直接支持类似OOP的方式。
可以关注typeset -T的方式,定义一个类,可以有私有变量和公有方法, ksh居然可以这样使用。
-
#!/bin/ksh93
-
-
typeset -T Point_t=(
-
integer -h 'x coordinate' x=0
-
integer -h 'y coordinate' y=0
-
typeset -h 'point color' color="red"
-
-
function getcolor {
-
print -r ${_.color}
-
}
-
-
function setcolor {
-
_.color=$1
-
}
-
-
setxy() {
-
_.x=$1; _.y=$2
-
}
-
-
getxy() {
-
print -r "(${_.x},${_.y})"
-
}
-
)
-
-
Point_t point
-
-
echo "Initial coordinates are (${point.x},${point.y}). Color is ${point.color}"
-
-
point.setxy 5 6
-
point.setcolor blue
-
-
echo "New coordinates are ${point.getxy}. Color is ${point.getcolor}"
-
-
exit 0
C: 天生支持伪编译
shcomp, 本身就支持伪编译,suse自身已经带了,redhat系列好像没有。可以从网上单独安装。编译出来的伪码,需要加ksh scriptname执行, 直接vi,在头上加入#!/bin/ksh,居然就可以直接执行了。
bash还是需要shc的帮忙, 其实脚本也不指望能保护到什么地步,但是对现网的脚本加些保护,可以预防一知半解的人的破坏性尝试。这样的尝试对系统的破坏性还是很强的。
其他好用的功能 (bash 适用):
1. 字符串前后缀处理
删除前缀
取abs 中的文件名称:(最长匹配)
a=/a/b/c/d/e/f/g/h;
echo ${a##/*/}
h
取abs中的root folder:(最短匹配)
a=/a/b/c/d/e/f/g/h; echo ${a#/*/}
/a
删除后缀
取abs中的路径:(最短匹配)
a=/a/b/c/d/e/f/g/h; echo ${a%/*}
/a/b/c/d/e/f/g
2. eval和全局变量GLOBIGNORE的妙用
eval和GLOBIGNORE的使用
自动化中命令行的组建和Metachar的正确传递都是非常关键的。
在python中,命令基本都用triple quote和r前缀来disable所有meta char的功能。这也是python为啥这样流行又一好处。
在bash和ksh中,却没有这样的表达方式。有时候,要传送*的本身,而不希望*变成扩展成文件名。
我是这样实现的:
先组建命令字串。然后用eval 将字串当成命令去执行
当需要传送*或其他meta char时,先运行 GLOBIGNORE="${metachar}",指定需要disable glob的meta char。
eval运行完后,可以GLOBIGNORE=,清空该内置全局变量,恢复meta char的本身功能。
3. 完整的日志功能
还是日志的问题,有时候程序需要进行日志记录,如何在同时输出日志文件和终端消息的时候,不影响function使用的substitution的功能,由于substitution是占用stdout通道的。解决方法是可以,将所有日志输出到文件,同时将stderr和stdout彻底分开。
即, 让出stdout通道给substitution方式的功能调用,不影响function调用的正常的替换操作,所有日志相关的调试消息,同步输出到stderr和日志文件。
命令行很简单:
echo "blablabla" >&1 | tee -a $logfile >&2
4. 为没有时间戳的日志输出添加输出时间戳
依赖ts工具的实现方案
# install ts tools
apt-get install moreutils
do_something 2>&1 | ts
简单无依赖包的bash实现方案,
验证方案可行性的方法:
cat /var/log/boot.log | xargs -i bash -c 'sleep 1; echo "$(date): {}"'
实际使用时的方法:
do_something 2>&1 | xargs -i bash -c 'echo "$(date): {} "'
5. || &&
# (( 1 & 1)) || echo hello
# (( 0 & 1)) || echo hello
hello
# (( 0 & 1)) && echo hello
# (( 0 & 1)) || echo hello
hello
# (( 0 & 1))
# echo $?
1
# (( 1 & 1))
# echo $?
0
6. 发现关联数组的更新方式的不同点
associate["test"]=”anything” 和 associate+=(["test"]="anything") 还是不同的。
前者是更新元素
后者在appending元素
7. 用 for进行判断是否元素存在的好处。
a=($(command arg1 arg2))
for aa in ${a[@]}; do
do somehting with aa
done
用统一的方式处理单个元素或多个元素。
如果没有正常返回内容,该段会直接跳过,而不会报错。
如果是其他if语句,如果处理不好容易发生报错现象。
8. indexof in shell 的几种实现
expr index String char
例如: expr index "hello world" o
5
s1="hello world"
s2=lo
match=${s1%%*$s2*}
${match:+:} eval "idx=$(expr "x${s1%$s2*}" : '.*')"
echo "${idx-0}"
4
20180528, Cloud Automation update
Zenith
阅读(2063) | 评论(0) | 转发(0) |