当前位置: 操作系统/服务器>linux
关于Shell脚本效率优化的一些个人想法
来源: 互联网 发布时间:2014-10-13
本文导语: 一、先说一下Shell脚本语言自身的局限性 作为解释型的脚本语言,天生就有效率上边的缺陷。尽管它调用的其他命令可能效率上是不错的。 Shell脚本程序的执行是顺序执行,而非并行执行的。这很大程度上浪费了可能能利用上...
一、先说一下Shell脚本语言自身的局限性
作为解释型的脚本语言,天生就有效率上边的缺陷。尽管它调用的其他命令可能效率上是不错的。
Shell脚本程序的执行是顺序执行,而非并行执行的。这很大程度上浪费了可能能利用上的系统资源。
Shell每执行一个命令就创建一个新的进程,如果脚本编写者没有这方面意识,编写脚本不当的话,是非常浪费系统资源的。
二、我们在Shell脚本语言的局限性上尽可能的通过我们有经验的编码来提高脚本的效率。
1、比如我想做一个循环处理数据,可能是简单的处理一下数据,这样会让人比较容易就想到Shell里的循环类似这样:
sum=0
for((i=0;i /dev/null
这句的效率三次分别是:
real 0m3.691s
user 0m5.219s
sys 0m0.630s
real 0m3.660s
user 0m5.169s
sys 0m0.618s
real 0m3.660s
user 0m5.150s
sys 0m0.612s
平均时间大概3.6秒,这前后效率大概有4倍的差距,虽然不像上一个有百倍的差距,但是也足够让4小时变成1小时了。我想你懂这个差距的。
其实这个正则实例你可以尝试推测其他的情况,因为正则每次运行都是需要启动字符串匹配的,而且默认的分隔符会较快的按字段区分出。所以我们在知道一些数据规律之后可以尝试大幅度的缩短我们将要进行复杂正则匹配的字符串,这样会根据你缩减数据规模有一个非常明显的效率提升,上边还是验证的比较简单的正则匹配情况,只有一个单字符“”,你可以试想如果正则表达式是这样:
$7!~/.jpg$/&&$7~/.[s]?html|.php|.xml|/$/&&($9==200||$9==304)&&$1!~/^103.108|^224.215|^127.0|^122.110.5/
我想你可以想象的出一个目标匹配字符串从500个字符缩减到50个字符的时候的巨大意义!
ps:另外详细的正则优化请看这个日期之后发的一篇博文。
3、再说一下shell的重定向和管道。这个条目我不会再举例子,只是说一下我个人的理解。
周所周知,很多程序或者语言都有一个比较突出的效率瓶颈就是IO,Shell也不例外(个人这么考虑)。所以建议尽可能的少用重定向来进行输入输出这样的操作或者创建临时文件来供后续使用,当然,如果必须这么干的时候那就这么干吧,我只是讲一个尽量的过程。
我们可以用Shell提供的管道来实现命令间数据的传递。如果进行连续的对数据进行过滤性命令的时候,尽量把一次性过滤较多的命令放在前边,这个原因都懂吧?减少数据传递规模。
最后我想说的连管道也尽量的少用的,虽然管道比正常的同定向IO快几个数量级的样子,但是那也是需要消耗额外的资源的,好好设计你的代码来减少这个开销吧。比如sort | uniq 命令,完全可以使用 sort -u 来实现。
4、再说一下Shell脚本程序的顺序执行。这块的优化取决于你的系统负载是否达到了极限,如果你的系统连命令的顺序执行负载都到了一个较高的线的话,你就没有必要进行Shell脚本程序的并行改造了。下边给出一个例子,如果你要模仿这个优化,请保证你的系统还能有负载空间。比如现在有这样一个程序:
supportdatacommand1
supportdatacommand2
supportdatacommand3
supportdatacommand4
supportdatacommand5
supportdatacommand6
need13datacommand
need24datacommand
need56datacommand
大意就是有6个提供数据的命令在前边,后面有3个需要数据的命令,第一个需要数据的命令需要数据13,第二个需要24,第三个需要56。但是正常情况下Shell会顺序的执行这些命令,从supportdatacommand1,一条一条执行到need56datacommand。这样的过程你看着是不是也很蛋疼?明明可以更好的做这一块的,蛋疼的程序可以这样改造:
supportdatacommand1 &
supportdatacommand2 &
supportdatacommand3 &
supportdatacommand4 &
supportdatacommand5 &
supportdatacommand6 &
#2012-02-22 ps:这里的循环判断后台命令是否执行完毕是有问题的,pidnum循#环减到最后也还是1不会得到0值,具体解决办法看附录,因为还有解释,就不在这#里添加和修改了。
while true
do
sleep 10s
pidnum=`jobs -p | wc -l`
if [ $pidnum -le 0 ]
then
echo "run over"
break
fi
done
need13datacommand &
need24datacommand &
need56datacommand &
wait
...
可以类似上边的改造。这样改造之后蛋疼之感就纾解的多了。但还是感觉不是很畅快,那好吧,我们可以再畅快一点(我是指程序。。。),可以类似这样:
for((i=0;i
shell脚本如何调用另外一个shell脚本的函数?
急救!关于Shell脚本删除过期文件的问题,Shell脚本达人乱入
shell 脚本中命令别名在脚本外无法使用
傻瓜问题,请问shell编程和shell脚本编程的关系
C语言调用shell脚本后,通过何种方法能获取脚本中变量的值
想用shell脚本定时执行另一个脚本
一个shell执行另一个带参数shell脚本????????????
如何给shell脚本加密,脚本中有密码。最好是比较直接的,不要说让用 shc
Shell脚本调用Sql脚本并向其中传递变量
请问,Shell中如何执行另外一个Shell脚本?
如何传递参数给linux shell 脚本(当脚本从标准输入而不是从文件获取时)
nohup执行的shell脚本,全局变量不能传递到脚本中使用吗?
cd、zip等命令在shell提示符下能执行,在shell脚本中为什么不能执行呢?
shell脚本问题 关于父脚本和子脚本的问题
shell脚本错误输出
请教shell脚本启动程序
关于shell脚本的。
关于arm linux下的别名配置脚本如何在进入用户时让shell执行的问题,如bashrc,profile,.bash_profile等脚本,寻求高手解答
高分请教关于Shell脚本执行中断问题?
作为解释型的脚本语言,天生就有效率上边的缺陷。尽管它调用的其他命令可能效率上是不错的。
Shell脚本程序的执行是顺序执行,而非并行执行的。这很大程度上浪费了可能能利用上的系统资源。
Shell每执行一个命令就创建一个新的进程,如果脚本编写者没有这方面意识,编写脚本不当的话,是非常浪费系统资源的。
二、我们在Shell脚本语言的局限性上尽可能的通过我们有经验的编码来提高脚本的效率。
1、比如我想做一个循环处理数据,可能是简单的处理一下数据,这样会让人比较容易就想到Shell里的循环类似这样:
代码如下:
sum=0
for((i=0;i /dev/null
这句的效率三次分别是:
real 0m3.691s
user 0m5.219s
sys 0m0.630s
real 0m3.660s
user 0m5.169s
sys 0m0.618s
real 0m3.660s
user 0m5.150s
sys 0m0.612s
平均时间大概3.6秒,这前后效率大概有4倍的差距,虽然不像上一个有百倍的差距,但是也足够让4小时变成1小时了。我想你懂这个差距的。
其实这个正则实例你可以尝试推测其他的情况,因为正则每次运行都是需要启动字符串匹配的,而且默认的分隔符会较快的按字段区分出。所以我们在知道一些数据规律之后可以尝试大幅度的缩短我们将要进行复杂正则匹配的字符串,这样会根据你缩减数据规模有一个非常明显的效率提升,上边还是验证的比较简单的正则匹配情况,只有一个单字符“”,你可以试想如果正则表达式是这样:
$7!~/.jpg$/&&$7~/.[s]?html|.php|.xml|/$/&&($9==200||$9==304)&&$1!~/^103.108|^224.215|^127.0|^122.110.5/
我想你可以想象的出一个目标匹配字符串从500个字符缩减到50个字符的时候的巨大意义!
ps:另外详细的正则优化请看这个日期之后发的一篇博文。
3、再说一下shell的重定向和管道。这个条目我不会再举例子,只是说一下我个人的理解。
周所周知,很多程序或者语言都有一个比较突出的效率瓶颈就是IO,Shell也不例外(个人这么考虑)。所以建议尽可能的少用重定向来进行输入输出这样的操作或者创建临时文件来供后续使用,当然,如果必须这么干的时候那就这么干吧,我只是讲一个尽量的过程。
我们可以用Shell提供的管道来实现命令间数据的传递。如果进行连续的对数据进行过滤性命令的时候,尽量把一次性过滤较多的命令放在前边,这个原因都懂吧?减少数据传递规模。
最后我想说的连管道也尽量的少用的,虽然管道比正常的同定向IO快几个数量级的样子,但是那也是需要消耗额外的资源的,好好设计你的代码来减少这个开销吧。比如sort | uniq 命令,完全可以使用 sort -u 来实现。
4、再说一下Shell脚本程序的顺序执行。这块的优化取决于你的系统负载是否达到了极限,如果你的系统连命令的顺序执行负载都到了一个较高的线的话,你就没有必要进行Shell脚本程序的并行改造了。下边给出一个例子,如果你要模仿这个优化,请保证你的系统还能有负载空间。比如现在有这样一个程序:
supportdatacommand1
supportdatacommand2
supportdatacommand3
supportdatacommand4
supportdatacommand5
supportdatacommand6
need13datacommand
need24datacommand
need56datacommand
大意就是有6个提供数据的命令在前边,后面有3个需要数据的命令,第一个需要数据的命令需要数据13,第二个需要24,第三个需要56。但是正常情况下Shell会顺序的执行这些命令,从supportdatacommand1,一条一条执行到need56datacommand。这样的过程你看着是不是也很蛋疼?明明可以更好的做这一块的,蛋疼的程序可以这样改造:
代码如下:
supportdatacommand1 &
supportdatacommand2 &
supportdatacommand3 &
supportdatacommand4 &
supportdatacommand5 &
supportdatacommand6 &
#2012-02-22 ps:这里的循环判断后台命令是否执行完毕是有问题的,pidnum循#环减到最后也还是1不会得到0值,具体解决办法看附录,因为还有解释,就不在这#里添加和修改了。
while true
do
sleep 10s
pidnum=`jobs -p | wc -l`
if [ $pidnum -le 0 ]
then
echo "run over"
break
fi
done
need13datacommand &
need24datacommand &
need56datacommand &
wait
...
可以类似上边的改造。这样改造之后蛋疼之感就纾解的多了。但还是感觉不是很畅快,那好吧,我们可以再畅快一点(我是指程序。。。),可以类似这样:
代码如下:
for((i=0;i