2010-11-04 18 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