作者:home_king 实现把文件并行拷贝到多个路径下的功能。 知识点: 1. 使用了"协同程序",是拷贝进程并行化 2. 使用eval来实现变量的"间接扩充" 3. 使用awk的关联数组来剔除"文件当前路径"以及"重复路径",以避免拷贝并行化可能引起的"系统颠簸"甚至"拷贝错误" 4. 使用了stat获取目录inode,以判定路径的唯一性(不同的路径名可能指向同一个物理路径,如~, /root, /root/Desktop/../,又如~user, /home/user)
代码: #!/bin/sh # # mcp---Multiple copy with Co-Process # checkargs(){ if [ $# -eq 0 ];then echo 'No arguments supplied!' return 1 fi cpfile=$1 if [ ! -f $cpfile ]; then echo 'Invaild file to copy!' return 1 fi shift for tmparg in "$@"; do if [ ! -d $tmparg ];then echo "There's at least one invalid directory" return 1 fi done argnums=($(echo $(stat -Lc %i $@) | awk -v inum=$(stat -c %i $PWD) '{for(i=1;i<=NF;i++){if($i == inum)continue;ldirs[$i]=i}} END{for(item in ldirs){print ldirs[item]}}')) }
checkargs $@ [ $? -eq 0 ] || exit 1 shift
echo "Destination:" for arg in "${argnums[@]}"; do eval echo '$'$arg eval cp -f $cpfile '$'$arg & done wait echo "" echo 'All done!'
就这个例子,我们来对比一下并行化与非并行化的效率: 该脚本:
代码: [root@home root]# time ./mcp-1.0 perl1 /tmp ~home_king /home/home_king/ ~ /root Destination: /home/home_king/ /tmp
All done!
real 0m0.110s user 0m0.010s sys 0m0.050s
该脚本的普通拷贝(非并行化)版本(去除&以及wait):
代码: [root@home root]# time ./scp perl1 /tmp ~home_king /home/home_king/ ~ /root Destination: /home/home_king/ /tmp
All done!
real 0m0.099s user 0m0.010s sys 0m0.040s
可见,在单CPU的机器上,"协同程序"带来的效率提升较小,甚至会降低原有的效率!
引用《Learning the Bash shell》的一段话来结尾:
粗略地说,可以以三种方式总结一个进程使用系统资源地特性:是否为CPU密集型的(即进行频繁的CPU计算),I/O密集型的(进行频繁的写磁盘操作)或交互式的(需要用户交互)。 --------quote-START---------- 对两个或多个不同种类的进程,进程越多同时运行它们就越有好处。例如,在和一个长的,I/O操作频繁的数据库查询同时运行时,一个数值统计计算的作业会很有效率。 另一方面,如果两个进程以类似方式使用资源,则同时运行它们比按次序运行它们效率差一些。原因是在该条件下,操作系统经常需要按时间片抢夺资源。 例如,如果两个进程都进行频繁的磁盘操作,操作系统会进入一个模式,在两个竞争的进程之间会不断地来回切换对磁盘的控制权。系统进行切换操作的时间至少会和它处理进程本身操作的时间一样长。该现象称为系统颠簸(thrashing),最严重时,会使系统处于一个虚拟停顿状态。系统颠簸是一个常见问题,系统管理员和操作系统设计者会花费很多时间试图使其最小化。 ---------quote-END----------- |