提高性能

问题描述:

这是我们用于监控服务器上坐骑的状态bash脚本中间的片段:提高性能

OIFS=$IFS 
IFS=$'\n' 
for mount in $mounts; do 
     mountcount=$(($mountcount+1)) 
     dev=`echo $mount | awk {'print $1'};` 
     dir=`echo $mount | awk {'print $2'};` 
     opts=`echo $mount | awk {'print $4'};` 
     state=`echo $opts | cut -d ',' -f 1` 
     if [ "$state" = "ro" ]; then 
       crit="true" 
       break 
     fi 
done 
IFS=$IFS 

$坐骑将有内容类似于:

rootfs/rootfs rw 0 0 
none /sys sysfs rw,nosuid,nodev,noexec,relatime 0 0 
none /proc proc rw,nosuid,nodev,noexec,relatime 0 0 
none /dev devtmpfs rw,relatime,size=1028136k,nr_inodes=218146,mode=755 0 0 
none /dev/pts devpts rw,nosuid,noexec,relatime,gid=5,mode=620,ptmxmode=000 0 0 
fusectl /sys/fs/fuse/connections fusectl rw,relatime 0 0 
/dev/disk/by-uuid/f2337686-ec8d-429a-9002-592c564ddbf3/ext3 rw,relatime,errors=remount-ro,barrier=0,data=ordered 0 0 
none /sys/kernel/debug debugfs rw,relatime 0 0 
none /sys/kernel/security securityfs rw,relatime 0 0 
none /dev/shm tmpfs rw,nosuid,nodev,relatime 0 0 
none /var/run tmpfs rw,nosuid,relatime,mode=755 0 0 
none /var/lock tmpfs rw,nosuid,nodev,noexec,relatime 0 0 

正如你应该能够看到,我解析到每一行拆分出它是寻找被安装只读安装部件。从功能上来说,这种方式非常好,但问题是我们正在100台服务器上运行这个服务器,目前它需要一秒钟(有时)才能通过上述循环运行上述数据。

我相信这个问题是由于等待执行awkcut,因为它们是外部程序,所以我想知道是否有更高效的方法可以实现相同的功能。我在bash上不够精通,无法知道可以帮助解决这个问题的内部功能,或者足够精通awk来完成这一切。

我的感觉是awk的三个电话和一个cut的电话都可以在awk的一行中实现。任何帮助非常感谢!

编辑

变量开发,DIR和mountcount在脚本中建立输出以后使用。

编辑

我已经改变了脚本如下:(所有回波的都在那里作为测试)

mountcount=0 

OIFS=$IFS 
IFS=$'\n' 
for mount in $mounts; do 
    mountcount=$(($mountcount+1)) 
    echo $mount 
    echo $mount | read dev dir fs opts 
    echo $dev 
    echo $dir 
    echo $fs 
    echo $opts 
    state=`echo $opts | cut -d ',' -f 1` 
    if [ "$state" = "ro" ]; then 
     crit="true" 
     break 
    fi 
done 
IFS=$OIFS 

这使我有以下几点:

rootfs/rootfs rw 0 0 




fusectl /sys/fs/fuse/connections fusectl rw,relatime 0 0 




/dev/disk/by-uuid/1be5b3ae-8239-4177-9af6-22ad0afa662a/ext3 rw,relatime,errors=remount-ro,data=ordered 0 0 




/dev/disk/by-uuid/1be5b3ae-8239-4177-9af6-22ad0afa662a /dev/.static/dev ext3 rw,relatime,errors=remount-ro,data=ordered 0 0 




devpts /dev/pts devpts rw,relatime 0 0 




securityfs /sys/kernel/security securityfs rw,relatime 0 0 

因此read不能像预期的那样工作。

这可能会为你工作:

OIFS=$IFS; IFS=$'\n'; ma=($mounts); IFS=$OIFS 
mountcount=0 
for mount in "${ma[@]}"; do 
    ((mountcount++)) 
    fa=($mount) 
    dev=${fa[0]} 
    dir=${fa[1]} 
    opts=${fa[3]} 
    state=${fa[3]/,*} 
    if [ "$state" = "ro" ]; then 
      crit="true" 
      break 
    fi 
done 
+0

+1不需要外部程序,应该可以提供显着的性能改进。 – 2012-01-13 14:35:19

可能像

read dev dir fs opts <<<"$mount" 

对于初学者?

或者整个事情看起来非常像

read dev dir fs opts <<<"$(grep ' ro,' <<<"$mounts"|head -n 1)" 

这将让你的临界线,如果有一个(也许对grep的更复杂的表达式将是很好)。在这种情况下,不算数。

P.S.在最后一行IFS=$IFS我相信你的意思是IFS=$OIFS

+0

我刚刚尝试了你的第一个建议,查看更新代码/输出的问题。 – SimonJGreen 2012-01-13 10:21:36

+0

oops,当然,你需要设置'IFS'来读取。像'echo $ mount | IFS = $ OIFS读dev dev dir fs opts'。 – 2012-01-13 10:24:51

+2

'... | read'将不起作用,因为'read'在子shell中执行(请参见[BashFAQ#024](http://mywiki.wooledge.org/BashFAQ/024))。你可以使用'read dev dir fs opts 2012-01-13 16:17:55

反转逻辑怎么样?一次运行awk 3次,cut一次,将结果存储到数组$devs, $dirs, $optses, $states。然后,在for ((i=0; i<max; i++))循环中,获得${devs[i]}等等,然后完成它们的工作。

+0

你能举个例子吗?我从来没有使用bash数组。 – SimonJGreen 2012-01-13 10:42:56

+0

当然:'devs =($(echo“$ mounts”| awk'{print $ 1};'))' – choroba 2012-01-13 13:12:01

也许你缩写脚本在这里,而且有更多的比我可以看到。但是,为什么你不只是做

echo "$mounts" | grep -w 'ro' 

得到所有只读挂载的列表,或者,如果你想只是第一个,

echo "$mounts" | grep -w 'ro' | head -1 

您仍然可以使用awk处理这个输出,但awk将少得多,所以它应该运行得更快。

'ro'和-w一起对任务来说应该是唯一的,但是如果你得到误报,你可以使用egrep更精细的模式。