shell에서 조건문 질문좀 드립니다..

rp2kmc의 이미지

네트워크 장비 Master/Backup 정합성 검사를 하기위해 2대의 노드에서 아래와 같은 결과물을 발췌하였습니다.
원래는 파일이 각각 저장되어있고 쓸데없는 문자열이 많지만 우선 아래와같이 간결하게 만들었습니다.

cat v_merge.txt

Data_K1(En) BKUP Data_K1(En) MSTR
Data_K2(En) MSTR Data_K2(En) BKUP
Data_K3(En) MSTR Data_K3(En) BKUP
Data_K4(En) BKUP Data_K4(En) MSTR
Data_K5(En) BKUP Data_K5(En) MSTR

위 결과를 얻은 명령은 아래와 같으며 아랫줄에 반복문과 조건식을 걸어 결과를 얻고싶은데 이제 막 문자열 가공만 터득한 터라 쉽지않아 조언을 구합니다.

#!/bin/sh
cat BD8806_BB1.txt | grep '(En)' | awk '{print $1" "$5}' >v1.txt
cat BD8806_BB2.txt | grep '(En)' | awk '{print $1" "$5}' >v2.txt
paste v1.txt v2.txt >v_merge.txt

위 결과물에서 5라인이 있는데 각 라인별로 MSTR / BKUP 또는 BKUP / MSTR 로 잘 구성되어있습니다.
MSTR 와 BKUP 의 순서에 상관없이 라인별로 하나씩만 들어있다면 "Good" 이라는 문자열을 출력하고싶습니다.
그 외에는 "Bad"로 출력하고싶습니다.
어떤 형태로든 구현이 가능한 코드 조언좀 부탁드립니다.
감사합니다.

나빌레라의 이미지

꼭 shell script로 만들어야 하는게 아니면 파이썬으로는 대충 아래처럼 하면 됩니다.

sample = [
"Data_K1(En) BKUP Data_K1(En) MSTR",
"Data_K2(En) MSTR Data_K2(En) BKUP",
"Data_K3(En) MSTR Data_K3(En) BKUP",
"Data_K4(En) BKUP Data_K4(En) MSTR",
"Data_K5(En) MSTR Data_K5(En) MSTR",
"Data_K5(En) BKUP Data_K5(En) MSTR"
]
 
import re
for s in sample:
    mlist = re.findall('BKUP|MSTR', s)
    print("Good" if mlist.count('BKUP') == 1 and mlist.count('MSTR') == 1 else "Bad")

----------------------
얇은 사 하이얀 고깔은 고이 접어서 나빌레라

rp2kmc의 이미지

아직 파이썬을 해보진 않았지만 동일한 작업이 필요할 경우 참고해서 활용하겠습니다
감사합니다(_ _)

ymir의 이미지

$ cat > in.txt
Data_K1(En) BKUP Data_K1(En) MSTR
Data_K2(En) MSTR Data_K2(En) BKUP
Data_K3(En) MSTR Data_K3(En) BKUP
Data_K4(En) BKUP Data_K4(En) MSTR
Data_K5(En) BKUP Data_K5(En) MSTR
^C
$ cat in.txt | cut -d' ' -f1,2 > a.txt
$ cat in.txt | cut -d' ' -f3,4 > b.txt
$ join a.txt b.txt
Data_K1(En) BKUP MSTR
Data_K2(En) MSTR BKUP
Data_K3(En) MSTR BKUP
Data_K4(En) BKUP MSTR
Data_K5(En) BKUP MSTR
$ join a.txt b.txt | sed -r -e 's/BKUP MSTR|MSTR BKUP/Good/g' -e 's/MSTR MSTR|BKUP BKUP/Bad/g'
Data_K1(En) Good
Data_K2(En) Good
Data_K3(En) Good
Data_K4(En) Good
Data_K5(En) Good

되면 한다! / feel no sorrow, feel no pain, feel no hurt, there's nothing gained.. only love will then remain.. 『 Mizz 』

rp2kmc의 이미지

우선 제가 가진 파일이 자꾸 결과가 다르게 나와 확인해보니 위에 복붙해 올린게 사실 파일 두개를 paste한거라 가운데 공백이 스페이스바가 아닌 탭이였네요.
일단 컷이라는 명령을 awk 대신 사용해서 -d는 스페이스바를 구분자로 적용하고 -f는 필드를 정의한다고 이해했는데 제가 이해한것이 맞나요..?
그리고 join이라는 명령은 동일한 문자열을 하나만 출력하는듯 한데 이것도 찾아보니 옵션이 어마어마하네요..
우선 답변주신 명령어로 활용해보겠습니다.
아래에 good bed같은 경우는 꼭 MSTR, BKUP만 있는것이 아니라 간혹 INIT이나 DOWN 상태도 있어 첫번째 마스터 백업이나 백업 마스터 순이 아니면 무조건 bed로 표기하고싶습니다.
그리고 5라인에 대해 전부 표시도 필요하긴 하지만 최종 목적은 저기 5개중 하나라도 bed가 있다면 해당 파일의 결과가 bed로 찍히게 하고싶은데 이건 반복문이 필요할것같은데 어떤걸 사용하면될까요?

ymir의 이미지

cut 을 이해하셨다면, v1.txt 과 v2.txt 를 paste 한 것을 원래대로 나눈거라는 걸 아셨을 겁니다.
paste 하는 대신 join 을 써서, Data_Kx 와 상태값 두 개의 형태로 바꾼거죠.
join 은 두 개의 파일에서, 첫번째 필드를 기준으로 값이 같을 경우에 한 해, 나머지 필드들을 하나로 합쳐주는 명령입니다.
(-j, -1, -2 옵션으로 필드 변경 가능)

$ cat a.txt
Data_K1(En) BKUP
Data_K2(En) MSTR
Data_K3(En) MSTR
Data_K4(En) BKUP
Data_K5(En) BKUP
$ cat b.txt
Data_K1(En) MSTR
Data_K2(En) INIT
Data_K3(En) BKUP
Data_K4(En) DOWN
Data_K5(En) MSTR
$ join a.txt b.txt
Data_K1(En) BKUP MSTR
Data_K2(En) MSTR INIT
Data_K3(En) MSTR BKUP
Data_K4(En) BKUP DOWN
Data_K5(En) BKUP MSTR
$ join a.txt b.txt | sed -r -e 's/MSTR BKUP|BKUP MSTR/Good/g' | \
> while read -r node status; do [ "$status" != "Good" ] && status=Bad; echo "$node $status"; done
Data_K1(En) Good
Data_K2(En) Bad
Data_K3(En) Good
Data_K4(En) Bad
Data_K5(En) Good

되면 한다! / feel no sorrow, feel no pain, feel no hurt, there's nothing gained.. only love will then remain.. 『 Mizz 』

rp2kmc의 이미지

우선 친절한 답변 감사드립니다.
위 코드에서 가장 아래부분의 결과가 나오는 부분은
join a.txt b.txt | sed -r -e 's/MSTR BKUP|BKUP MSTR/Good/g' 여기까지만 하면 나오는 것을 확인하였습니다
뒤에 붙여주신 | \와 아래에 반복문을 shell 프롬프트에서 실행하면 마지막 출력물 처럼 나오는데
이걸 .sh파일로 만들어서 돌려보면 단순히 Bad 라는 출력만 나옵니다.

===============================================================
root@DESKTOP-V5FDCE3:/etc/ansible# cat v1.txt
Data_K1(En) BKUP
Data_K2(En) BKUP
Data_K3(En) BKUP
Data_K4(En) BKUP
Data_K5(En) BKUP
root@DESKTOP-V5FDCE3:/etc/ansible# cat v2.txt
Data_K1(En) MSTR
Data_K2(En) MSTR
Data_K3(En) MSTR
Data_K4(En) MSTR
Data_K5(En) MSTR
root@DESKTOP-V5FDCE3:/etc/ansible#
===============================================================
코드는 아래와 같습니다.
===============================================================
#!/bin/sh

#raw data에서 (En)이 포함된 모든 라인을 불러와 해당 라인의 1번,5번 필드만 따로 저장
cat BD8806_BB1.txt | grep '(En)' | awk '{print $1" "$5}' >v1.txt
cat BD8806_BB2.txt | grep '(En)' | awk '{print $1" "$5}' >v2.txt

#위 awk 부분을 아래 cut 명령어로 바꾸어 쓸수 있음(-d:구분자 선택, -f:필드 선택)
#cat v1.txt | cut -d' ' -f1,2 > a.txt
#cat v2.txt | cut -d' ' -f3,4 > b.txt

#join 추가옵션 없을 경우 두 파일의 첫번째 필드가 같으면 하나로 출력하고 뒷 필드는 순차적으로 합침
#sed -r:특수문자 사용가능 -e: ??? MSTR BKUP or BKUP MSTR 순의 문자열을 Good으로 치환(모든 라인에)
join v1.txt v2.txt | sed -r -e 's/MSTR BKUP|BKUP MSTR/Good/g' | \

#반복문: 위 결과물에서 1라인씩 읽어들임(첫번째 필드는 node 두번째 필드는 status 라는 변수에 할당)
#두번째 필드가 Good과 같지 않으면 &&:다음을 실행(status를 Bad로 표기후 해당 노드와 상태를 출력후 완료)
> while read -r node status; do [ "$status" != "Good" ] && status=Bad; echo "$node $status"; done

#임시파일 삭제
rm v1.txt v2.txt
===============================================================
root@DESKTOP-V5FDCE3:/etc/ansible# sh vrrp.sh
Bad
root@DESKTOP-V5FDCE3:/etc/ansible#

현재 모든 노드가 정상적으로 MSTR/BKUP를 유지하고 있는데 Bad로 출력되는 이유를 모르겠습니다.
sh파일을 돌렸을때 내부 내용을 확인 후 전부 이중화 정합성에 부합하면 echo "Good Status" 하나라도 Bad값이 있다면 echo "Bad Status"를 출력하고싶습니다. 짜주신 코드에서 if를 이리저리 대입했는데 error만 출력되어서 다시 질문드립니다 ㅠㅠ

ex1)
$ sh vrrp.sh
Good Status

ex2)
$ sh vrrp.sh
Bad Status

아 그리고 도저히 구글링해서 못찾겠는 옵션이 있는데 sed -r -e 에서 -e가 무엇을 의미하나요?

ymir의 이미지

스크립트의 결과 값이 다른 이유는, 쉘에서 입력했을 때와 다른 명령을 썼기 때문입니다.
명령 뒤에 \ 를 붙이는 경우는, 명령어 입력이 아직 끝나지 않은 상태에서, 다음 라인에서 계속 이어서 입력할 때 씁니다.
이 경우에는 다음 라인의 프롬프트가 > 로 바뀝니다.
명령어 타이핑 할 때 입력했던 문자가 아닌데, 스크립트에서는 > 를 직접 입력하셨으니..
다른 결과가 나온 것입니다.

sed 에서 -e 는 sed 스크립트를 연속해서 여러 개 입력할 때 씁니다.
스크립트가 하나만 있을 때에는, -e 옵션은 없어도 되는데, 여러 개 입력할 때에는 스크립트 마다 -e 를 붙여줘야 합니다.
linux 서버에 man page 가 설치되어 있지 않다면, google 에서 man sed 라고 검색해도 man page 를 보여줍니다.

read 에서 변수를 node status 와 같이 여러 개 입력한 경우..
문자열에서 변수 하나당 필드 하나씩 차례대로 assign 하는 것은 맞는데..
마지막 변수에 한해서는, 나머지 모든 필드의 문자열을 assign 합니다.

되면 한다! / feel no sorrow, feel no pain, feel no hurt, there's nothing gained.. only love will then remain.. 『 Mizz 』

rp2kmc의 이미지

덕분에 여러가지 사실을 알게되었습니다(_ _)
아래와 같이 원하던 결과도 얻게되었구요
raw data의 값을 이리저리 바꾸어봐도 정상적인 값이 출력이되네요
주말인데도 친절히 답변해주셔서 진심으로 감사드립니다.
좋은 주말 되세요^_^
====================================================
#!/bin/sh

#raw data에서 (En)이 포함된 모든 라인을 불러와 해당 라인의 1번,5번 필드만 따로 저장
cat BD8806_BB1.txt | grep '(En)' | awk '{print $1" "$5}' >v1.txt
cat BD8806_BB2.txt | grep '(En)' | awk '{print $1" "$5}' >v2.txt

join v1.txt v2.txt | sed -r -e 's/MSTR BKUP|BKUP MSTR/Good/g' | \
while read -r node status;
do
[ "$status" != "Good" ] && status=Bad;
echo "$status";
done >v_merge.txt

if [ `grep "Bad" v_merge.txt` ]
then echo "Bad Status"
else echo "Good Status"
fi
rm v1.txt v2.txt v_merge.txt
====================================================
root@DESKTOP-V5FDCE3:/etc/ansible# sh vrrp.sh
Good Status
root@DESKTOP-V5FDCE3:/etc/ansible#

댓글 달기

Filtered HTML

  • 텍스트에 BBCode 태그를 사용할 수 있습니다. URL은 자동으로 링크 됩니다.
  • 사용할 수 있는 HTML 태그: <p><div><span><br><a><em><strong><del><ins><b><i><u><s><pre><code><cite><blockquote><ul><ol><li><dl><dt><dd><table><tr><td><th><thead><tbody><h1><h2><h3><h4><h5><h6><img><embed><object><param><hr>
  • 다음 태그를 이용하여 소스 코드 구문 강조를 할 수 있습니다: <code>, <blockcode>, <apache>, <applescript>, <autoconf>, <awk>, <bash>, <c>, <cpp>, <css>, <diff>, <drupal5>, <drupal6>, <gdb>, <html>, <html5>, <java>, <javascript>, <ldif>, <lua>, <make>, <mysql>, <perl>, <perl6>, <php>, <pgsql>, <proftpd>, <python>, <reg>, <spec>, <ruby>. 지원하는 태그 형식: <foo>, [foo].
  • web 주소와/이메일 주소를 클릭할 수 있는 링크로 자동으로 바꿉니다.

BBCode

  • 텍스트에 BBCode 태그를 사용할 수 있습니다. URL은 자동으로 링크 됩니다.
  • 다음 태그를 이용하여 소스 코드 구문 강조를 할 수 있습니다: <code>, <blockcode>, <apache>, <applescript>, <autoconf>, <awk>, <bash>, <c>, <cpp>, <css>, <diff>, <drupal5>, <drupal6>, <gdb>, <html>, <html5>, <java>, <javascript>, <ldif>, <lua>, <make>, <mysql>, <perl>, <perl6>, <php>, <pgsql>, <proftpd>, <python>, <reg>, <spec>, <ruby>. 지원하는 태그 형식: <foo>, [foo].
  • 사용할 수 있는 HTML 태그: <p><div><span><br><a><em><strong><del><ins><b><i><u><s><pre><code><cite><blockquote><ul><ol><li><dl><dt><dd><table><tr><td><th><thead><tbody><h1><h2><h3><h4><h5><h6><img><embed><object><param>
  • web 주소와/이메일 주소를 클릭할 수 있는 링크로 자동으로 바꿉니다.

Textile

  • 다음 태그를 이용하여 소스 코드 구문 강조를 할 수 있습니다: <code>, <blockcode>, <apache>, <applescript>, <autoconf>, <awk>, <bash>, <c>, <cpp>, <css>, <diff>, <drupal5>, <drupal6>, <gdb>, <html>, <html5>, <java>, <javascript>, <ldif>, <lua>, <make>, <mysql>, <perl>, <perl6>, <php>, <pgsql>, <proftpd>, <python>, <reg>, <spec>, <ruby>. 지원하는 태그 형식: <foo>, [foo].
  • You can use Textile markup to format text.
  • 사용할 수 있는 HTML 태그: <p><div><span><br><a><em><strong><del><ins><b><i><u><s><pre><code><cite><blockquote><ul><ol><li><dl><dt><dd><table><tr><td><th><thead><tbody><h1><h2><h3><h4><h5><h6><img><embed><object><param><hr>

Markdown

  • 다음 태그를 이용하여 소스 코드 구문 강조를 할 수 있습니다: <code>, <blockcode>, <apache>, <applescript>, <autoconf>, <awk>, <bash>, <c>, <cpp>, <css>, <diff>, <drupal5>, <drupal6>, <gdb>, <html>, <html5>, <java>, <javascript>, <ldif>, <lua>, <make>, <mysql>, <perl>, <perl6>, <php>, <pgsql>, <proftpd>, <python>, <reg>, <spec>, <ruby>. 지원하는 태그 형식: <foo>, [foo].
  • Quick Tips:
    • Two or more spaces at a line's end = Line break
    • Double returns = Paragraph
    • *Single asterisks* or _single underscores_ = Emphasis
    • **Double** or __double__ = Strong
    • This is [a link](http://the.link.example.com "The optional title text")
    For complete details on the Markdown syntax, see the Markdown documentation and Markdown Extra documentation for tables, footnotes, and more.
  • web 주소와/이메일 주소를 클릭할 수 있는 링크로 자동으로 바꿉니다.
  • 사용할 수 있는 HTML 태그: <p><div><span><br><a><em><strong><del><ins><b><i><u><s><pre><code><cite><blockquote><ul><ol><li><dl><dt><dd><table><tr><td><th><thead><tbody><h1><h2><h3><h4><h5><h6><img><embed><object><param><hr>

Plain text

  • HTML 태그를 사용할 수 없습니다.
  • web 주소와/이메일 주소를 클릭할 수 있는 링크로 자동으로 바꿉니다.
  • 줄과 단락은 자동으로 분리됩니다.
댓글 첨부 파일
이 댓글에 이미지나 파일을 업로드 합니다.
파일 크기는 8 MB보다 작아야 합니다.
허용할 파일 형식: txt pdf doc xls gif jpg jpeg mp3 png rar zip.
CAPTCHA
이것은 자동으로 스팸을 올리는 것을 막기 위해서 제공됩니다.