現在の作業ディレクトリによって異なる実行スクリプトがあります。デフォルトでは、.iniファイルを処理し、ここからパラメータを取得してmysqlバックアップを実行します。
スクリプトは root ユーザーとして実行されます。
作業ディレクトリを/rootとして使用して実行するとき。エラーで終了します。 .iniファイルパラメータはスクリプトには反映されません。
cd /を実行してから実行すると正常に動作します。
失敗しそうな機能です。
get_param()
{
for line in `cat ${PARAMETERSFILE}`
do
if [ "${ISFOUND}" != "true" -a "`echo ${line} | grep ${STAG} | grep -v grep | wc -l`" == "1" ]
then
ISFOUND="true"
fi
if [ "${ISFOUND}" == "true" -a "`echo ${line} | grep ${ETAG} | grep -v grep | wc -l`" == "1" ]
then
ISFOUND="false"
fi
if [ "${ISFOUND}" == "true" -a "`echo ${line} | grep ${STAG} | grep -v grep | wc -l`" != "1" ]
then
key="`echo ${line} | sed 's/=/ /' | awk '{print $1}'`"
val="`echo ${line} | sed 's/=/ /' | awk '{print $2}'`"
cmd="${key}=\"${val}\""
eval ${cmd}
fi
done
}
いくつかの変数は次のとおりです。
STAG="\[backup\]"
ETAG="\/backup\]"
ISFOUND="false"
iniファイルは次のとおりです
[help]
backupdir="Backup Home Directory "
user="MySQL Database Username"
password="MySQL Database Password"
retentioPeriodMinutes="Retention Period of Backup (e.g. 1440= 1 day)"
memory="Dedicated RAM (Mbyte)"
[/help]
[backup]
backupdir=/opt/backupdb
user="root"
password="xyz"
[/backup]
[restore]
backupdir=/opt/backupdb
user="root"
password="xyz"
memory="1024"
[/restore]
[houseKeeping]
backupdir=/opt/backupdb
retentioPeriodMinutes=10080
[/houseKeeping]
以下は、sh -xvを使用して実行したときの出力です。現在のディレクトリが/ rootの場合、パイプは正しく機能しないようです。
+ for line in '`cat ${PARAMETERSFILE}`'
echo ${line} | grep ${STAG} | grep -v grep | wc -l
++ grep '\[backup\]'
++ grep -v grep
++ wc -l
+ '[' false '!=' true -a 0 == 1 ']'
echo ${line} | grep ${ETAG} | grep -v grep | wc -l
++ grep '\/backup\]'
++ echo '[help]'
++ grep -v grep
++ wc -l
+ '[' false == true -a 0 == 1 ']'
echo ${line} | grep ${STAG} | grep -v grep | wc -l
++ grep -v grep
++ grep '\[backup\]'
++ echo '[help]'
++ wc -l
これは、作業ディレクトリが/の場合と同じ出力です。
+ for line in '`cat ${PARAMETERSFILE}`'
echo ${line} | grep ${STAG} | grep -v grep | wc -l
++ grep '\[backup\]'
++ grep -v grep
++ echo '[help]'
+ '[' false '!=' true -a 0 == 1 ']'
echo ${line} | grep ${ETAG} | grep -v grep | wc -l
++ grep '\/backup\]'
++ grep -v grep
++ wc -l
++ echo '[help]'
+ '[' false == true -a 0 == 1 ']'
echo ${line} | grep ${STAG} | grep -v grep | wc -l
++ echo '[help]'
++ grep -v grep
++ grep '\[backup\]'
++ wc -l
答え1
この問題を説明できるバグが1つ以上見つかりました。まだあなたのスクリプトを詳細に確認していません。この行の機能を確認してください。
for line in `cat ${PARAMETERSFILE}`
- 変数の値を取得します
PARAMETERSFILE
。 - 分ける空白値 - 値に「一般」文字のみが含まれている場合、結果は単一の単語です。
- やるファイル名拡張子別名すべての単語を読んでください。変数値に「一般」文字のみが含まれていても、単一の単語が生成されます。
cat
指定されたファイルで実行します。- 出力を読んでください
cat
。コマンドの置き換え。 - 分ける余白へのコマンド出力。今回は、分割する文字列に多くの改行文字とわずかなスペースが含まれています。結果の単語は
[help]
、、、、、、、、、… backupdir="Backup
Home
Directory
"
user="MySQL
Database
Username"
- やるファイル名拡張子別名すべての単語を読んでください。
今回は一部の単語にワイルドカード文字が含まれており、グローバルパターンとして解釈されます。パターンがどのファイルとも一致しない場合は、そのままにしてください。パターンが 1 つ以上のファイルと一致する場合、パターンは一致するファイルのリストに置き換えられます。
このような文字列は、単一の文字ファイル名を一致させることができる4つの可能性(、、、、)を持つグローバル[help]
パターンです。したがって、その名前のファイルが含まれていないディレクトリでスクリプトを実行すると、単語は変更されません。現在のディレクトリにthenというファイルが含まれている場合。h
e
l
p
[help]
h
[help]
h
for line in …
入力を複数行に分割しないでください。最も簡単な方法は
while IFS= read -r line; do
…
done <"$PARAMETERSFILE"
IFS= read -r line
改行を除く特殊文字なしで1行だけ読みます。先行スペースと末尾のスペースを削除するには、削除しますIFS=
。バックスラッシュが行の連続として機能するようにするには、削除します(つまり、行末のバックスラッシュは次の改行を無視します)-r
。