bash 파일 내에 sed 명령어를 넣었는데, crontab 으로 실행했을 때 먹통이 되는 경우

예) a.sh

sed -i 's/find/repl/g' a.txt

이 경우는 a.txt 파일의 인코딩이 UTF-8 이고, crontab 실행 환경은 인코딩이 ko_KR.eucKR 인 등 서로의 인코딩이 맞지 않아 발생하는 문제임.

bash 내 인코딩 설정을 추가하면 됨.

예) a.sh (UTF-8 파일인 경우)

export LANG=ko_KR.UTF-8
sed -i 's/find/repl/g' a.txt


이렇게 하면 실행환경의 인코딩이 변경되어 정상 동작

출처 : https://tod2.tistory.com/175


1. 아파치 accesslog 중 특정 도메인을 추출한 파일 (domain.com.txt)의 해외 접속 기록만 확인

cat domain.com.txt | awk '$1 != "KR" {print $0}' 
(1번째 필드가 mod_geoip에 의해 출력되어야함, 로그포맷 변경 및 GeoIP와 GeoIP-devel 설치 필수)


쉘스크닙트를 작성하다 보면 특정 명령의 성공 유무가 궁금합니다.

이것은 해당 Process의 return 값하고 관계가 있을 수 있는데
C 프로그램의 main() 함수에서의 return 값 하고도 관계가 있습니다.
혹은 python 에서의 sys.exit(9) 같은 것과도 동일합니다.

모두 동일한데 0 이 리턴되면 정상이고 0이 리턴되지 않으면
오류로 간주합니다.

예를 들어

ls /etc | grep hosts

라는 명령을 실행하면

$ ls /etc | grep hosts
hosts
hosts.allow
hosts.deny


와 같은 결과가 나오고

$ echo $?
0

와 같이 이전 실행명령의 리턴값 ($?) 을 찍어보면 0 으로써 성공했다는 것이 나옵니다.

ls /etc 에 파일이나 폴더 목록을 보면서 hosts 라는 것이 있는 가를 grep 해본 결과입니다.

이제 host 대신 h_ost 라는 것을 대신 해 보면,

$ ls /etc | grep h_osts
$ echo $?
1


와 같이 0 이 아닌 값이 나옵니다.

이것을 기본적인 shell 스크립트로 만들어 본다면,

#!/bin/sh
ls /etc | grep h_osts
if [ $? -eq 0 ];then
    echo "CMD OK!"
else
    echo "CMD Failure!"
    exit 9
fi
echo "After CMD OK!"

위와 같이 만들 수 있습니다.

그런데 더 간단하게 보이는 방법으로서
명령을 실행하고 나서 쉘의 && || 논리 연산자를 이용하는 방법이 있습니다.

ls /etc | grep h_osts && echo "CMD OK!" || echo "CMD Failure!"

와 같이

CMD && 성공인경우의명령 || 실패인 경우의명령

과 같이 한줄로 표현 가능합니다. 물론 가독성을 위하여

ls /etc | grep h_osts \
    && echo "CMD OK!" \
    || echo "CMD Failure!"; exit 9
echo "After CMD OK!"

와 같이 줄 수 있습니다. (처음에는 적어도 그렇게 생각했지요) 

이것은 sh (bash 도 동일)의 논리 연산자의 실행 최적화와 관계 있는데요,

조건식 && 결과1 || 결과2

와 같은 구문이 있다고 하였을 때
조건식이 True 이면 && 다음 구문까지 확인하여 마저 True인가를 확인하지만 이미 True이기 때문에 && 다음의 결과1은 실행시키지만, || 다음의 결과2 구문은 실행시키지 않습니다.
조건식이 False 이면 그 반대로 || 다음의 결과2 구문만 실행합니다.

그런데 위의 명령을 수행하면 성공 하던 안하던 간에 무조건 exit 9으로 종료를 해 버렸습니다.


생각해보니 
명령1 && 명령2 || 명령3
이 하나의 명령이고 그것에 이어 (';') exit 9 명령이 수행되기 때문입니다.

여기서는 위의 명령3을 exit 9 까지 하나로 묶어 처리해야 합니다.

결론은,

ls /etc | grep h_osts \
    && echo "CMD OK!" \
    || echo "CMD Failure!"; exit 9; }
echo "After CMD OK!"

와 같이 해 주면 되는 것이었습니다.

어느 분께는 도움이 되셨기를...

[출처] http://egloos.zum.com/mcchae/v/11221790



그냥 echo 명령만 사용하면 자동으로 줄바꿈이 되는데, 전에 출력한 문자열을 지우고  새 문자열을 겹쳐 쓰고 싶다면 -n 옵션과 -e 옵션을 사용하자.

-n 옵션은 줄바꿈을 하지 않는 것이고, -e 옵션은 리턴(\r), 탭(\t) 등을 사용할 수 있게 해 주는 옵션이다.

echo "abc\tdef"
abc\tdef
echo -e "abc\tdef"
abc    def

전에 출력한 문자열을 지우고 그 자리에 새로운 문자열을 출력하려면, 첫번째 문자열을 출력할 때 -n 옵션으로 줄바꿈을 억제한 후에 다음 문자열을 출력할 때 -e 옵션으로 리턴(\r)을 출력해서 프롬프트를 줄 시작점으로 보내주면 된다. 아래의 예시를 참고하자.

echo -n "this is the first."
sleep 3
echo -e "\rthis is the 2nd.   "

첫번째 문자열 출력후 3초후에 두번째 문자열을 같은 줄에 겹쳐 쓰게 된다.

두번째 문자열이 첫번째보다 짧다면 이전 출력 뒷부분이 남을 것이므로 뒤쪽에 공백(space)을 충분히 주자.

shell script에서 진행 상황을 표시해 주고 싶을 때 요긴하게 사용할 수 있다.

아래는 위의 내용을 응용한 쉘스크립트 예제파일이다.

processing.sh


[출처] http://bahndal.egloos.com/406163



Linux Shell Script 에서 

한 줄 주석은 해당 라인의 앞에 #만 적으면 된다.

여러 줄 주석은 :<<'END' 부터 END 까지로 가능하다.

# 한 줄 주석

:<<'END'
여러줄
주석
END


#!/bin/bash                                                   #!/bin/bash

string='www.sysadm.kr';                                     string='www.sysadm.kr';


if [[ $string == *"sysadm"* ]]                            if [[ $string =~ .*sysadm.* ]]
then                                                           then
  echo "It's there!";                       또는              echo "True"
else                                                            else
echo "There is no String!"                                   echo "False"
fi                                                               fi



grep -A n pattern datafile
grep -B n pattern datafile

grep -C n pattern datafile

을 사용하면 된다.


n 은 0과 자연수 (1,2,3,4....n)


aa.txt 내용

apple
orange
banana
mango


-A 옵션은 match된 line의 다음 n line을 추가로 출력하여 준다.  (After)

    ex) grep -A 2 orange aa.txt -> orange부터 2라인 아래까지 출력 (orange부터 mango 까지 출력된다.)


-B 옵션은 match 된 line의 전 n line을 추가로 출력하여 준다. (Before)

    ex) grep -B 2 banana aa.txt -> banana부터 2라인 위까지 출력 (banana부터 apple 까지 출력된다.)


-C 옵션은 match 된 line의 이전&다음 n line을 추가로 출력하여 준다. (Before & After)

    ex) grep -C1 banana aa.txt -> banana부터 위아래로 1라인씩 추가로 출력하여 준다.

        (orange부터 mango까지 출력된다.)

    또는 grep -A1 -B1 banana aa.txt 로 하여도 결과는 동일하다.



shc-3.8.9.tgz


 

"shc" 는 스크립트 파일을 바이너리로 바꿔 주는 역할을 합니다.
php encoder 같은 역할을 한다고 보면 됩니다.

예전엔 중요한 소스 같은 경우, php로 스크림트 파일 위치를 열어서 특정 디렉터리에 위치해 놓고 컴파일하여 사용했는데,
"shc"를 사용하니 더욱 강력(?)하고 손 쉽게 인코딩하더군요.

역시 아는 것이 힘입니다.

쉘 스크립트도 역시 중요한 "root" 패스워드 정보, "DB" 정보 등 공유되거나 유출되면 안 되는 파일들이 존재합니다.

이럴 때 정말 유용하게 사용될 수 있으니, 아직까지 모르셨던 분들 아래 문서 참고하셔서 도움되시길 바랍니다.

좋은 날, 기쁜 날 되시길 빕니다.


-------------------------------------------------------
1. 다운로드  
-------------------------------------------------------
(1) 공식
    http://www.datsi.fi.upm.es/~frosal/ 

(2) rootman 사이트
    http://www.rootman.co.kr/NFS/Util/shc-3.8.3.tgz 


-------------------------------------------------------
2. 설치
-------------------------------------------------------
 [root@ns1 local]# tar xvfz shc-3.8.3.tgz
 shc-3.8.3/CHANGES
 shc-3.8.3/Copying
 shc-3.8.3/Makefile
 shc-3.8.3/match
 shc-3.8.3/pru.sh
 shc-3.8.3/shc.1
 shc-3.8.3/shc.c
 shc-3.8.3/shc.html
 shc-3.8.3/shc.README
 shc-3.8.3/test.bash
 shc-3.8.3/test.csh
 
 [root@ns1 shc-3.8.3]# make install
 ***     Installing shc and shc.1 on /usr/local
 ***     ¿Do you want to continue? y
 install -c -s shc /usr/local/bin/
 install -c -m 644 shc.1 /usr/local/man/man1/


"shc" 파일은 /usr/local/bin/ 디렉터리에 설치됩니다.


-------------------------------------------------------
3. 테스트
-------------------------------------------------------
(1) 파일 생성 (__EOF___ 까지 쉘 상태에서 긁어다가 붙이시면 됩니다.)
cat > /root/tmp/script.sh    << __EOF__
#!/bin/sh
#------------------------------
# this file is not encrypted
#------------------------------
echo "I love Duane's articles and will send him a donation via PayPal."
exit 0;
__EOF__


(2) 명령행 실행
  [root@ns1 tmp]# shc -f /root/tmp/script.sh
  "script.sh.x"라는 바이너리 파일이 생성된다.


(3) 생성된 스크립트 수행
  [root@ns1 tmp]# ./script.sh.x
  I love Duane's articles and will send him a donation via PayPal.


-------------------------------------------------------
4. 특이한 기능
-------------------------------------------------------
[root@ns1 tmp]# shc -e 09/10/2004 -m "Dude it is too late to run this script." -f script.sh
[root@ns1 tmp]# ./script.sh.x
./script.sh.x: has expired!
Dude it is too late to run this script.

- 쉘 스크립트에 대한 만료일을 지정하여 실행할 수 있습니다.
- 지정된 날짜 이후는 실행되지 아니합니다.
- 위 예는 "2004년 10월 9일"을 스크립트 만료일로 지정하여 만료 후에는 "Dude it is too late to run this script."라는
 메시지를 출력하라고 지정한 내용입니다.


-------------------------------------------------------
5. 참고사항
-------------------------------------------------------
- "shc" 명령어는 스크립트에 대한 C 소스 코드를 생성합니다.
- binary로 파일이 생성되므로 "./파일명" 형태로 실행하여야 합니다.
- 생성된 스크립트 파일은 이름을 변경해도 무관합니다.


-------------------------------------------------------
6. 기본 실행 옵션 설명
-------------------------------------------------------
(1) -e date
    만료일을 지정합니다. (dd/mm/yyyy format)

(2) -m message
    만기 시 메시지를 출력합니다.

(3) -f script_name
    컴파일할 스크립트 파일을 지정합니다. (자신의 시스템에서만 실행됨)

 

(4) shc -v -r -T -f myscript

    -T (trace)옵션을 주어야 다른 시스템에서도 실행이 된다.

 

출처 : http://www.mapoo.kr

[쉘 프로그래밍을 위한 sed 활용 예제 정리]

1. 특정 패턴 아래 라인 삭제 또는 추가

sed -i '/apple.*/{n;d}' abc.txt  // apple패턴아래 1줄 삭제

[결과] cat abc.txt
apple
banana

sed -i 's,\(apple.*\),\1\ngrape,g' abc.txt  // apple패턴아래 grape 추가

[결과] cat abc.txt
apple
grape
ornage
banana

[원본]abc.txt 의 내용

apple
orange
banana


2. 개행문자 (newline) 이 2개 연속으로 있을 때를 이를 1개로 변경하는 명령

sed -i '/^$/N;/^\n$/D' filename

filename 의 내용중 newline 이 2개 연속으로 있을때 이를 1개로 치환하며  -i 옵션은 변경된 내용을 출력하지 않고 filename 에 저장


3. sed 명령어에 변수사용

sed "s/abc/$dma/g" 와 같이 큰따옴표(") 안에 변수를 사용하면 된다.
sed 's/abc/$dma/g' 명령어는 abc 문자를 $dma 라는 문자로 바꾸라는 뜻이다.

즉, 작은따음표의 경우에는 $dma를 변수 dma로 인식하지 않고 문자열 $dma로 인식한다. 


4. 특정패턴 위/아래 에 내용 추가

sed "/찾을패턴/i추가할패턴" 파일명  (상단에 추가)
sed "/찾을패턴/a추가할패턴" 파일명 (하단에 추가)


5. 특정 라인 맨 앞/뒤 내용 추가

sed "행번호s/^/문자열/" 파일명 (라인 맨 앞 추가)
sed "행번호s/$/문자열/" 파일명 (라인 맨 뒤 추가)