我有一个根据当前工作目录以不同方式运行的脚本。基本上,它处理 .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
我发现至少有一个错误可以解释这个问题。我还没有详细审查你的剧本。看看这一行的作用:
for line in `cat ${PARAMETERSFILE}`
- 取变量的值
PARAMETERSFILE
。 - 分裂空白处的值 — 如果该值仅包含“普通”字符,则结果为单个单词。
- 履行文件名扩展又名通读每个单词。如果变量的值仅包含“普通”字符,这仍然会产生单个单词。
cat
在指定文件上运行。- 读取 的输出
cat
,因为这是一个命令替换。 - 分裂空白处的命令输出。这次要分割的字符串包含许多换行符和一些空格;结果单词是
[help]
,backupdir="Backup
,Home
,Directory
,"
,user="MySQL
,Database
,Username"
, … - 履行文件名扩展又名通读每个单词。
这次,某些单词包含通配符,因此它们将被解释为全局模式。如果模式与任何文件都不匹配,则保持原样。如果该模式至少匹配一个文件,则该模式将被匹配文件列表替换。
像这样的字符串[help]
是一种全局模式,有四种可能匹配单字符文件名:h
, e
, l
, p
.因此,如果您在不包含任何这些名称的文件的目录中运行脚本,则该单词保持不变,但如果当前目录包含名为then[help]
的文件,则会被替换为.h
[help]
h
for line in …
不将输入分割成行。最简单的方法是
while IFS= read -r line; do
…
done <"$PARAMETERSFILE"
IFS= read -r line
只读取一行,除了换行符之外没有特殊字符。如果要去除前导和尾随空格,请删除IFS=
.如果您希望允许反斜杠充当行继续符(即行尾的反斜杠会忽略后面的换行符),请删除-r
.