2013-03-13 119 views
0

我遇到了以下腳本的問題。由於我對BASH缺乏瞭解,我不能100%確定如何創建一個循環,它使用「for」來計算數組中變量的數量並循環遍歷每個變量。基本上我想要做的是讓腳本計算變量$ sqldumps中的變量數量,然後爲每個變量運行一個MySQL轉儲(也將它們記錄到數據庫中)。腳本的長版登載在底部,但這裏是低於短版:BASH問題,爲FOR循環計數數組中的變量

#! /usr/bin/env bash 
echo -ne '\033]0;World of Clucky - Backup\007' 
BINDIR="$(dirname "$(readlink -fn "$0")")" 
cd "$BINDIR" 
sqldumps=("lwc" "bans" "frisnuk_permissions" "jail" "imonies" "GriefP" "permissions" "showcase" "simpleclans") 
#Copy MySQL Databases 
echo "[`date '+%H:%M'`] Starting MySQL Backup" >> /home/clucky/MinecraftServers/backup.log 
for i in ${#sqldumps[*]} 
    do 
     echo "  ${sqldumps[i]}" >> /home/clucky/MinecraftServers/backup.log; 
     /opt/lampp/bin/mysqldump -u'root' -p'CENSORED' --skip-lock-tables ${sqldumps[i]} > /home/clucky/MinecraftServers/.backups/$timedate/MySQL/${sqldumps[i]}.sql; 
    done 
echo "  forum"; 
/opt/lampp/bin/mysqldump -u'root' -p'CENSORED' forum >> /home/clucky/MinecraftServers/.backups/$timedate/MySQL/forum.sql; 
echo "[`date '+%H:%M'`] MySQL Backup Complete" >> /home/clucky/MinecraftServers/backup.log 

,我有問題與特定的路線是:

for i in ${#sqldumps[*]} 

我假設我爲此使用了錯誤的語法,所以如果任何人都可以給我正確的語法,那將不勝感激。謝謝!

#! /usr/bin/env bash 
echo -ne '\033]0;World of Clucky - Backup\007' 
BINDIR="$(dirname "$(readlink -fn "$0")")" 
cd "$BINDIR" 
timedate=`date '+%m.%d.%Y-%H:%M'` 
sqldumps=("lwc" "bans" "frisnuk_permissions" "jail" "imonies" "GriefP" "permissions" "showcase" "simpleclans") 
echo "-------------- `date '+%d-%B-%Y %H:%M'` --------------" >> /home/clucky/MinecraftServers/backup.log 
echo "[`date '+%H:%M'`] Starting Minecraft Backup" >> /home/clucky/MinecraftServers/backup.log 
mkdir -p /home/clucky/MinecraftServers/.backups/$timedate 
mkdir -p /home/clucky/MinecraftServers/.backups/$timedate/MySQL 
nice --adjustment=19 tar -zcpf /home/clucky/MinecraftServers/.backups/$timedate/Minecraft.tar.gz \ 
    --directory /home/clucky/MinecraftServers/ \ 
    --exclude=SkyBlockkit \ 
    --exclude=Tekkit \ 
    --exclude=Vanilla \ 
    --exclude=test \ 
    --exclude=Zflocco_LP \ 
    --exclude=Mortuus/plugins/dynmap/web --exclude=Mortuus/plugins/AutoSaveWorld/backups --exclude Mortuus/CraftBukkitVersion --exclude=Mortuus/orebfuscator_cache --exclude=Mortuus/plugins/#Removed --exclude=Mortuus/server.log \ 
    --exclude=Frisnuk/plugins/dynmap/web --exclude=Frisnuk/plugins/AutoSaveWorld/backups --exclude Frisnuk/CraftBukkitVersion --exclude=Frisnuk/orebfuscator_cache --exclude=Frisnuk/plugins/#Removed --exclude=Frisnuk/plugins/#AwaitingUpdate --exclude=Frisnuk/server.log --exclude=Frisnuk/Suwako_Moriya100 --exclude=Frisnuk/Uk_Shadow --exclude=Frisnuk/Whiteghost99 --exclude=Frisnuk/greenrangermatt \ 
    --exclude=dailybackup.log \ 
    --exclude=.backups \ 
    --exclude=backup.log \ 
    --exclude=backups.log \ 
    --exclude=backupscript.sh \ 
    --exclude=dailybackup.sh \ 
    --exclude=.keptbackups . 
echo "[`date '+%H:%M'`] Minecraft Backup Complete" >> /home/clucky/MinecraftServers/backup.log 
#Purge files 3 days old 
echo "[`date '+%H:%M'`] Purging Old Backups" >> /home/clucky/MinecraftServers/backup.log 
find /home/clucky/MinecraftServers/.backups* -mmin +4320 -exec rm --recursive {} \; 
echo "[`date '+%H:%M'`] Purging Complete" >> /home/clucky/MinecraftServers/backup.log 
#Copy MySQL Databases 
echo "[`date '+%H:%M'`] Starting MySQL Backup" >> /home/clucky/MinecraftServers/backup.log 
for i in ${#sqldumps[*]} 
    do 
     echo "  ${sqldumps[i]}" >> /home/clucky/MinecraftServers/backup.log; 
     /opt/lampp/bin/mysqldump -u'root' -p'CENSORED' --skip-lock-tables ${sqldumps[i]} > /home/clucky/MinecraftServers/.backups/$timedate/MySQL/${sqldumps[i]}.sql; 
    done 
echo "  forum"; 
/opt/lampp/bin/mysqldump -u'root' -p'CENSORED' forum >> /home/clucky/MinecraftServers/.backups/$timedate/MySQL/forum.sql; 
echo "[`date '+%H:%M'`] MySQL Backup Complete" >> /home/clucky/MinecraftServers/backup.log 
echo "[`date '+%H:%M'`] Daily Backup Complete" >> /home/clucky/MinecraftServers/backup.log 
#Read back file size 
filesize=$(ls -lah /home/clucky/MinecraftServers/.backups/$timedate | awk '{ print $5}') 
echo "  Total Compression Size: $filesize\n" >> /home/clucky/MinecraftServers/backup.log 

謝謝您的協助!

+0

你需要知道的數組中的變量數或可你只需要使用陣列「地圖」方法的名額? – 2013-03-13 23:16:17

+0

真的,我真的不知道。我只需要一種方法讓腳本遍歷數組$ sqldumps中的所有變量併爲每個變量運行一次MySQL轉儲。 – Clucky 2013-03-13 23:25:51

回答

2

${#varname[*]}返回數組的大小語法,但你使用for語法要給予元素的列表。所以,無論是你想要的:

for elem in "${varname[@]}"; do 
    ... something with ${elem} ... 
done 

for ((i = 0; i < ${#varname[@]}; i++)); do 
    ... something with ${varname[$i]} ... 
done 

請注意,我用@代替*作爲一般是針對包含空格的(即使它可能不是嚴格必要的元素一個很好的預防這個案例)。

+0

工作很棒!謝謝!我嘗試了第二個,它完全按照我需要的那樣工作。另外,感謝關​​於'*'和'@'的小技巧,因爲我在想這個區別是什麼。 :) – Clucky 2013-03-13 23:37:20

2

不索引陣列上,只是使用的值:

for value in "${sqldumps[@]}"; do echo $value; done 
+0

我確實需要變量'i'每次增加1,對吧?那麼我會如何指定呢? – Clucky 2013-03-13 23:33:43

+0

@JesseAaronBellas:用這種形式,你根本不需要'i'。你唯一需要的是獲取數組的第i個元素,這個表單直接給你提供了元素。只需在循環中用'$ value'替換'$ {sqldumps [i]}'並設置好。 – 2013-03-14 00:44:47

0

我冒昧地重新組織腳本,使其更具可讀性。

#!/usr/bin/env bash 

# Script starts here. 
main() { 
    backup_dir=~clucky/MinecraftServers 
    dbs=(lwc bans frisnuk_permissions jail imonies GriefP permissions showcase simpleclans forum) 

    echo -ne '\033]0;World of Clucky - Backup\007' 

    log 'Starting MySQL Backup' 
    dump_dbs "${dbs[@]}" 
    log 'MySQL Backup Complete' 
} 

# Write a timestamped message to the log file. 
log() { 
    echo "[$(date '+%H:%M')] $*" >> "$backup_dir/backup.log" 
} 

# Dump each of the databases passed as an argument. The list of databases is "[email protected]". 
dump_dbs() { 
    for db in "[email protected]"; do 
     # Use --skip-lock-tables for every database except "forum". 
     local options=(--skip-lock-tables) 
     [[ $db = forum ]] && options=() 

     log "  $db" 
     /opt/lampp/bin/mysqldump -u root -p CENSORED "${options[@]}" "$db" \ 
      > "$backup_dir/.backups/$timedate/MySQL/$db.sql" 
    done 
} 

main "[email protected]" 

這裏有一些事情我做:

  1. 而不是遍歷數組索引,這樣的循環將遍歷直接在每個值:

    for value in "${array[@]}"; do ...; done 
    
  2. 使用~user來引用用戶的主目錄會更短。因爲用戶的主目錄不一定在/home以下,所以也更安全。

  3. 將代碼分解爲單獨的函數有助於消除一些冗餘,如重複寫入完整路徑到backup.log。 log()函數將時間戳消息行放在一個地方。

  4. forum表沒有得到--skip-lock-tables選項,所以我做了更明確的,這使得有可能擺脫重複mysqldump行。

  5. 我從他們不需要的地方刪除了引號。

0

$i將保持數組中的每個項目自增,直到它到達結尾。因此,您不必在for循環內每次需要時都參考陣列。我也是,不喜歡硬編碼echo,這是個人喜好,所以我換了printf

for i in ${#sqldumps[@]} 
    do 
    printf "  %s" "$i" >> /home/clucky/MinecraftServers/backup.log; 
    /opt/lampp/bin/mysqldump -u'root' -p'CENSORED' --skip-lock-tables $i > /home/clucky/MinecraftServers/.backups/$timedate/MySQL/${sqldumps[i]}.sql; 
done 

如果你只是想找到你可以使用的數組的大小。然後

​​3210

而且$Length將等於陣列