0

次のスクリプトで問題が発生しました。BASHの知識が不足しているため、「for」を使用して配列内の変数の量をカウントし、各変数をループするループを作成する方法が100%わかりません。基本的に私がやりたいのは、スクリプトに変数$ sqldumps内の変数の量をカウントさせてから、それらごとにMySQLダンプを実行することです(データベースにログインします)。スクリプトの長いバージョンは下部に掲載されていますが、以下に短いバージョンがあります。

#! /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

ご協力いただきありがとうございます!

4

4 に答える 4

2

配列にインデックスを付けないでください。値を使用してください。

for value in "${sqldumps[@]}"; do echo $value; done
于 2013-03-13T23:24:03.703 に答える
2

構文${#varname[*]}は配列のサイズを返しますが、for使用する構文は要素のリストを与えたいと考えています。したがって、次のいずれかが必要です。

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

また

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

注意してください、@代わりに使用するのは*、通常、スペースを含む要素に対する優れた予防策であるためです (この場合、厳密には必要ではないかもしれませんが)。

于 2013-03-13T23:24:16.483 に答える
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 "$@".
dump_dbs() {
    for db in "$@"; 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 "$@"

ここに私がしたことのいくつかがあります:

  1. 配列インデックスを反復するのではなく、このようなループは各値を直接反復します。

    for value in "${array[@]}"; do ...; done
    
  2. ~userユーザーのホーム ディレクトリを参照するために使用する方が短いです。また、ユーザーのホーム ディレクトリが の下にあるとは限らないため、より安全/homeです。

  3. コードを個別の関数に分割すると、完全なパスをbackup.log繰り返し記述するなどの冗長性を排除するのに役立ちます。log() 関数は、タイムスタンプ付きのメッセージ行を 1 か所に配置します。

  4. テーブルにはオプションforumがないため、重複行--skip-lock-tablesを取り除くことができるように、より明示的にしました。mysqldump

  5. 必要のない場所から引用符を削除しました。

于 2013-03-13T23:26:49.290 に答える
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

配列のサイズを知りたい場合は、使用できます。

Length=${#sqldumps[@]}

そして$Length、配列内の場所の数に等しくなります

于 2013-03-13T23:44:39.427 に答える