현재 작업 디렉토리에 따라 다르게 실행되는 스크립트가 있습니다. 기본적으로 .ini 파일을 처리하고 여기에서 매개변수를 가져와서 mysql 백업을 실행합니다.
스크립트는 루트 사용자로 실행됩니다.
작업 디렉토리를 /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]
이 있는 전역 패턴입니다 . 따라서 해당 이름을 가진 파일이 포함되지 않은 디렉터리에서 스크립트를 실행하면 단어는 변경되지 않습니다. 현재 디렉토리에 then이라는 파일이 포함되어 있으면 .h
e
l
p
[help]
h
[help]
h
for line in …
입력을 여러 줄로 나누지 마십시오. 가장 간단한 방법은
while IFS= read -r line; do
…
done <"$PARAMETERSFILE"
IFS= read -r line
줄 바꿈을 제외한 특수 문자 없이 한 줄만 읽습니다. 선행 및 후행 공백을 제거하려면 제거하십시오 IFS=
. 백슬래시가 줄 연속 역할을 하도록 하려면 제거하십시오(즉, 줄 끝의 백슬래시는 다음 개행을 무시합니다) -r
.