2013-03-13 86 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将等于阵列