Shell 脚本根据工作目录运行不同。

Shell 脚本根据工作目录运行不同。

我有一个根据当前工作目录以不同方式运行的脚本。基本上,它处理 .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}`
  1. 取变量的值PARAMETERSFILE
  2. 分裂空白处的值 — 如果该值仅包含“普通”字符,则结果为单个单词。
  3. 履行文件名扩展又名通读每个单词。如果变量的值仅包含“普通”字符,这仍然会产生单个单词。
  4. cat在指定文件上运行。
  5. 读取 的输出cat,因为这是一个命令替换
  6. 分裂空白处的命令输出。这次要分割的字符串包含许多换行符和一些空格;结果单词是[help], backupdir="Backup, Home, Directory, ", user="MySQL, Database, Username", …
  7. 履行文件名扩展又名通读每个单词。

这次,某些单词包含通配符,因此它们将被解释为全局模式。如果模式与任何文件都不匹配,则保持原样。如果该模式至少匹配一个文件,则该模式将被匹配文件列表替换。

像这样的字符串[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.

相关内容