King of Stock

[shell] if문에서 문자열 비교가 안될때 본문

IT 기술

[shell] if문에서 문자열 비교가 안될때

king of stock 2019. 12. 5. 10:21

shell script에서 문자열을 비교할때 주로 사용하는 단순한 형태가 if문을 이용하는 것이다.
그런데 가끔 문자열에 이상한 문자(여기서 예를 드는 것은 \r)가 문자열 내부에 들어가 있어서 내가 원하는 비교를 할 수가 없는 상황이 발생하기도 한다.

본 글에서는 위에서 언급한 상황에서 디버깅을 어떻게 하는지에 대해서 간단하게 글을 써보고자 한다.
내가 겪은 일을 기반으로 하나의 예를 들어보겠다. 최근에 인터넷에 있는 특정 파일을 백그라운드 프로세스 상태로 다운로드를 처리하고 shell script 처리 과정에서 이 백그라운드 처리가 완료가 되었는지 기다리고 다음 shell script 로직을 진행하려고 코드를 구현 했었다.

백그라운드 다운로드 처리가 완료 되었는지 검증하는 로직에서 다음과 같이 상태 및 파일의 사이즈를 검증하도록 구현했다. 아래 코드는 예시를 위해서 간단하게 만든 잘(?) 돌아가는 shell script 이다.

#!/bin/bash 
CHROME_FILENAME="googlechrome.dmg"

# URL 기준 파일 사이즈를 HTTP 헤더에서 추출(예상 결과: 83405572)
get_remote_file_size() {
  local attr="Content-Length: "
  local header=$(curl -sI https://dl.google.com/chrome/mac/stable/GGRO/${CHROME_FILENAME} | grep -i "${attr}")
  local keywords="content-length: "
  echo "${header}"$i | sed -e "s/${keywords}//g"
}

# 특정 파일을 백그라운드로 다운로드
download_from_remote() {
  nohup curl https://dl.google.com/chrome/mac/stable/GGRO/${CHROME_FILENAME} -o ${CHROME_FILENAME} 1>/dev/null 2>&1 &
}

# 파일 사이즈 10초마다 10회 검사
check_filesize() {

  local file_size="${1}"
  local target_file="${2}"
  local current_counter=0
  local limit_count=10

  while [ ${current_counter} -lt ${limit_count} ]; do
    sleep 10
    local current_size=$(wc -c "${target_file}" | awk '{print $1}')
    if [ "${current_size}" = "${file_size}" ]; then
      return 0
    fi

    current_counter=`expr ${current_counter} + 1`
    echo "The counter is increased ${current_counter}"
  done

  return 1
}

chrome_size=$(get_remote_file_size)
echo "The chrome file size is ${chrome_size}"
download_from_remote
bg_pid=${!}
echo "Downloading background process: ${bg_pid}"

if [ -f ${CHROME_FILENAME} ]; then
  echo "the ${CHROME_FILENAME} is exist."
  check_filesize "${chrome_size}" "${CHROME_FILENAME}"
fi

위에 shell script를 실행하면 다음과 같은 과정을 거치고 shell script가 종료된다.

  1. URL에서 파일 사이즈를 획득
  2. 크롬 인스톨 파일을 백그라운드로 다운로드
  3. 파일이 존재하는지 검사
  4. (파일이 존재할때) 1회 10초를 기다리고 10회 실행되는 동안 1번 사이즈와 현재 파일 사이즈를 문자열 비교

아래는 실행한 결과이다. 내용을 보면 counter 변수가 계속 증가되며 10회까지 변화되고 종료가 된다. 즉 파일 사이즈를 문자열로 바꿔 비교하는 구문이 계속 거짓으로 나왔다는 의미이다.

$ ./test.sh
chrome_size: 83405572
background process: 8098
the googlechrome.dmg is exist.
The counter increased 1
The counter increased 2
The counter increased 3
The counter increased 4
The counter increased 5
The counter increased 6
The counter increased 7
The counter increased 8
The counter increased 9
The counter increased 10

shell script 내부에 echo 사용해서 출력을 하면 다음과 같다. 2개의 변수는 동일한 값이 출력되는 것으로 나온다. 이런 상황에서 사용 할 수 있는 shell script 커맨드가 존재한다.

$ ./test.sh
The chrome file size is 83405572
Downloading background process: 8424
the googlechrome.dmg is exist.
remote  size 83405572
current size 83405572
The counter is increased 1
remote  size 83405572
current size 83405572
The counter is increased 2
^C

다음과 같은 커맨드를 이용하면 문자열 내부의 escape 문자들까지 눈으로 확인을 할 수 있다.

echo "어떠한 문자" | od -bc;

이 커맨드를 통해서 위에 shell script 내용에 적용을 해보았다.

# ... 중략 ...
local current_size=$(wc -c "${target_file}" | awk '{print $1}')
echo "${file_size}" | od -bc
echo "${current_size}" | od -bc
# ... 중략 ...

그리고 다시 실행을 해보면 \r 문자가 들어가 있는 것을 확인할 수 있다.

$ ./test.sh
The chrome file size is 83405572
Downloading background process: 8546
the googlechrome.dmg is exist.
0000000   070 063 064 060 065 065 067 062 015 012
           8   3   4   0   5   5   7   2  \r  \n
0000012
0000000   070 063 064 060 065 065 067 062 012
           8   3   4   0   5   5   7   2  \n
0000011
The counter is increased 1
^C

결국 원격 파일 사이즈 결과 문자열에 tr -d '\r' 추가해서 해결을 했다. 너무 힘들었다. ㅋ(짜증) 아래는 위에 내용을 모두 적용한 test.sh shell script 내용이다.

#!/bin/bash 
CHROME_FILENAME="googlechrome.dmg"

# URL 기준 파일 사이즈를 HTTP 헤더에서 추출(예상 결과: 83405572)
get_remote_file_size() {
  local attr="Content-Length: "
  local header=$(curl -sI https://dl.google.com/chrome/mac/stable/GGRO/${CHROME_FILENAME} | grep -i "${attr}")
  local keywords="content-length: "
  echo "${header}"$i | sed -e "s/${keywords}//g" | tr -d '\r'
}

# 특정 파일을 백그라운드로 다운로드
download_from_remote() {
  nohup curl https://dl.google.com/chrome/mac/stable/GGRO/${CHROME_FILENAME} -o ${CHROME_FILENAME} 1>/dev/null 2>&1 &
}

# 파일 사이즈 10초마다 10회 검사
check_filesize() {

  local file_size="${1}"
  local target_file="${2}"
  local current_counter=0
  local limit_count=10

  while [ ${current_counter} -lt ${limit_count} ]; do
    sleep 10
    local current_size=$(wc -c "${target_file}" | awk '{print $1}')
    echo "${file_size}" | od -bc
    echo "${current_size}" | od -bc
    if [ "${current_size}" = "${file_size}" ]; then
      return 0
    fi

    current_counter=`expr ${current_counter} + 1`
    echo "The counter is increased ${current_counter}"
  done

  return 1
}

chrome_size=$(get_remote_file_size)
echo "The chrome file size is ${chrome_size}"
download_from_remote
bg_pid=${!}
echo "Downloading background process: ${bg_pid}"

sleep 1
if [ -f ${CHROME_FILENAME} ]; then
  echo "the ${CHROME_FILENAME} is exist."
  check_filesize "${chrome_size}" "${CHROME_FILENAME}"
fi

'IT 기술' 카테고리의 다른 글

VSCode diff 툴  (0) 2020.08.25
[DNS] ubuntu server 18.04 DNS 서버 구성해보기  (0) 2019.12.21
[Kubernetes] StatefulSet podAntiAffinity  (0) 2019.08.03
[test] TestRestTemplate  (0) 2019.07.07
[swagger2] Whitelabel Error Page  (0) 2019.07.06
Comments