2010-11-04 45 views
0

我编写了这个脚本来查找$ WWWUSER具有写权限的所有文件/目录。起初,我将其余的匹配项存储在一个临时文件中。我新的必须有一种不使用文件的方式,所以这是我的“解决方案”。它可以工作,但速度很慢。有小费吗?如何优化bash脚本? (查找文件,忽略白名单,报告其余)

更新: 在包含大约7K目录和30K文件(〜8K whitelistings)脚本大约需要15分钟的目录结构...(ext3文件系统,UW320 SCSI硬盘)。

#!/usr/bin/env bash 
# Checks the webroot for files owned by www daemon and 
# writable at the same time. This is only needed by some files 
# So we'll check with a whitelist 

WWWROOT=/var/www 
WWWUSER=www-data 
WHITELIST=(/wp-content/uploads 
/wp-content/cache 
/sitemap.xml 
) 
OLDIFS=$IFS 
IFS=$'\n' 

LIST=($(find $WWWROOT -perm /u+w -user $WWWUSER -o -perm /g+w -group $WWWUSER)) 
IFS=$OLDIFS 

arraycount=-1 
whitelist_matches=0 

for matchedentry in "${LIST[@]}"; do 
     arraycount=$(($arraycount+1)) 

     for whitelistedentry in "${WHITELIST[@]}"; do 
       if [ $(echo $matchedentry | grep -c "$whitelistedentry") -gt 0 ]; then 
         unset LIST[$arraycount] 
         whitelist_matches=$(($whitelist_matches+1)) 
       fi 
     done 
LISTCOUNT=${#LIST[@]} 
done 

if [ $(echo $LISTCOUNT) -gt 0 ]; then 
     for item in "${LIST[@]}"; do 
       echo -e "$item\r" 
     done 
     echo "$LISTCOUNT items are writable by '$WWWUSER' ($whitelist_matches whitelisted)." 
else 
     echo "No writable items found ($whitelist_matches whitelisted)." 
fi 
+0

是否有可能使用任何外部应用程序来运行该程序Perl的?对于白名单引用,它可以通过使用散列来缩短并加快速度。使用不同的Shebang,它可以运行相同。 – 0xCAFEBABE 2010-11-04 10:59:13

+0

这是可能的,但不是所期望的。但我会检查TME的想法,然后研究如何实施你的想法。谢谢! – weeheavy 2010-11-04 11:21:45

回答

1

(我没有方便的设置来测试这个,但它应该工作...)

#!/usr/bin/env bash 
# Checks the webroot for files owned by www daemon and 
# writable at the same time. This is only needed by some files 
# So we'll check with a whitelist 

WWWROOT=/var/www 
WWWUSER=www-data 
WHITELIST="(/wp-content/uploads|/wp-content/cache|/sitemap.xml)" 

listcount=0 
whitelist_matches=0 

while IFS="" read -r matchedentry; do 
    if [[ "$matchedentry" =~ $WHITELIST ]]; then 
     ((whitelist_matches++)) 
    else 
     echo -e "$matchedentry\r" 
     ((listcount++)) 
    fi 
done < <(find "$WWWROOT" -perm /u+w -user $WWWUSER -o -perm /g+w -group $WWWUSER) 

if (($listcount > 0)); then 
        echo "$listcount items are writable by '$WWWUSER' ($whitelist_matches whitelisted)." 
else 
        echo "No writable items found ($whitelist_matches whitelisted)." 
fi 

编辑:我已经纳入对数学丹尼斯·威廉姆森的建议;同时,这里的建设从数组开始白名单模式的方式:

WHITELIST_ARRAY=(/wp-content/uploads 
/wp-content/cache 
/sitemap.xml 
) 

WHITELIST="" 
for entry in "${WHITELIST_ARRAY[@]}"; do 
    WHITELIST+="|$entry" 
done 
WHITELIST="(${WHITELIST#|})" # this removes the stray "|" from the front, and adds parens 

EDIT2:Sorpigal的关于排除新工艺评论让我思考 - 我怀疑大多数的加速在这个版本来自没有运行〜40每个扫描文件调用grep,并且删除数组操作只有一点点,但是在我看来,如果你不需要最后的总数,你可以删除main while循环,并用下面的代码替换它:

find "$WWWROOT" -perm /u+w -user $WWWUSER -o -perm /g+w -group $WWWUSER | grep -v "$WHITELIST" 

...确实运行grep,但只有一次(并通过t运行整个文件列表帽子单个实例),并且一旦开始,grep将能够比bash循环更快地扫描文件列表...

+0

哈,你发布的代码几乎和我的作品一样。 +1和我的删除。下次我会记得不要在subhell管道上绊倒。 – Sorpigal 2010-11-04 12:19:53

+1

另外,我认为这里需要说明的是,优化这个过程是尽可能减少子壳和执行者的过程。 – Sorpigal 2010-11-04 12:22:44

+0

这非常棒,执行时间缩短到4秒!非常感谢*每个人*! – weeheavy 2010-11-04 12:37:07

1

还有另一种可能性。如果($ word =〜$ pattern) $ pattern可能是 “^^ bash regex操作符(版本3及更高版本)将任何找到的单词快速地匹配到列表,则可以将白名单更改为正则表达式模式。 (whitelistentry1 | whitelistentry2 | whitelistentry3 | ...)$”。

+0

不知道这是可能的与bash,我会看看它。谢谢。 – weeheavy 2010-11-04 11:22:01