레이블이 쉘스크립트(bash)인 게시물을 표시합니다. 모든 게시물 표시
레이블이 쉘스크립트(bash)인 게시물을 표시합니다. 모든 게시물 표시

2021년 3월 29일 월요일

Java로 무한 loop 쉘스크립트 실행

 java에서 쉘스크립트를 실행하는 기능을 추가 했다.

문제는 자바 프로그램이 종료되면 쉘스크립트 역시 1~2초 후에 멈춰 버린다.

쉘스크립트는 while true로 무한루프로 실행이 되는 스크립트였다.


자바에서 실행 명렁어를 nohup, &, sh -c 등 이것 저것 다 해 보았지만 쉘스크립트는 멈췄다.

결국 찾은 방법은 두가지이다. 두가지 방법 다 정석적인 해결책은 아니고 trick으로 볼수 있는 방법이다.


하나는 중간 launch 스크립트를 두는 방식이다.

실제 내가 실행해야 할 스크립트가 target.sh 이면 launcher.sh를 둬서 자바에서는 launcher.sh를 실행하는 방법이다.

launcher.sh에는 아래와 같은 명령을 넣는다.


#/bin/sh

nohup ./target.sh 1> /dev/null 2>&1 &



다른 하나는 trap을 사용한 방법이다. 

trap 명령어는 특정 시그널이 들어올 때 어떤 일을 할 지 적용할 수 있다.


실제 적용한 방법은 두번째 방법으로 trap명령어를 통한 방법이다.

적용 방법은 아래와 같다.


trap "method_name" 0


0은 EXIT 인 경우 이다. 자바 프로세스 종료시 EXIT 시그널이 오는 데, 그 때 loop를 사용하는 method_name를 다시 한번 사용하게 하였다.

종료는 9(SIGKILL) 시그널을 발생시켜서 종료하므로 문제 없이 stop을 할 수 있다.

2021년 1월 27일 수요일

단락 연산자(short-circuit operator)

 리눅스에서 명령어를 연속 해서 사용 할 때가 있다.

보통 || 와 &&을 사용한다. 이를 단락 연산자(short-circuit operator)라고 한다.

첫번째 명령어를 실행하고 곧이어 두번째 명령어를 실행하는 역할이다.


예제는 다음과 같다.

[root@localhost ~]# true || echo 'ok'
[root@localhost ~]# false || echo ok
ok
[root@localhost ~]#

||는 앞의 명령어 성공하면 뒤의 echo 'ok'는 실행하지 않는다.
앞의 명령이 실패하면 뒤의 echo 'ok' 명령를 실행한다.

&&은 ||과 반대이다. 앞의 명령이 성공하면 뒤의 명령을 실행한다.
앞의 명령이 실패하면 뒤의 명령을 실행하지 않는다.

[root@localhost ~]# true && echo 'ok'
ok
[root@localhost ~]# false && echo 'ok'
[root@localhost ~]#

앞 명령어와 상관없이 실행하고자 할 때는 ;를 쓴다.
[root@localhost ~]# echo '1ok'; echo '2ok'
1ok
2ok
[root@localhost ~]#

2017년 11월 21일 화요일

공격 아이피 iptable 등록 스크립트.

mail log를 점검하다 보니, 지속적으로 접근시도하는 부분이 보인다.

보안장비를 사용하면 간단하게 막으련만... 여의치 않아 스크립트를 작성하였다.
#/bin/bash


help()
{
echo ""
echo "/var/log/maillog is default"
echo "iptable apply is not default"
echo "banCount 100 is default"
echo "-a : iptable applied"
echo "-f : maillog FILE PATH"
echo "-c : ban count"
echo ""
echo "Usae : $0 -a -c 100 -f /var/log/maillog "
exit 0
}

ignoreIPs=("111.222.333.444" "111.111.111.111")
maillog="/var/log/maillog"
banCount=100
fw=false

# 옵션이름 뒤에 :이 붙은 것은 값을 필요로 함을 의미합니다.
while getopts ac:f: opt
do
case $opt in
a)
fw=true
;;
c)
banCount=$OPTARG
;;
f)
maillog=$OPTARG
;;
*)
help
exit 0
;;
esac
done


banIPs=`grep -E 'user not found|password fail' ${maillog} | awk -F: '{print $NF}' | sort | uniq -dc | awk '{if ($1 > '"${banCount}"') print $NF}'`

for banIP in $banIPs
do
for ignoreIP in ${ignoreIPs[@]}
do
if [ $ignoreIP == $banIP ]
then
# echo "ignore IP: ${ignoreIP}"
# echo "ban IP : $banIP"
break
fi
done

echo "ban IP : $banIP ,whois : $(geoiplookup $banIP)"
if [ $fw = true ] ; then
iptables -A INPUT -s ${banIP}/24 -j DROP
fi

done


if [ $fw = true ] ; then
#remove duplicate iptables rules
#http://www.krazyworks.com/remove-duplicate-iptables-rules/
/sbin/service iptables save
/sbin/iptables-save | awk '!x[$0]++' > /tmp/iptables.conf
/sbin/iptables -F
/sbin/iptables-restore < /tmp/iptables.conf
/sbin/service iptables save
/sbin/service iptables restart
if [ -f /tmp/iptables.conf ] ; then /bin/rm -f /tmp/iptables.conf ; fi
fi

qmail 큐(queue) 체크 스크립트.

계정의 패스워드가 노출되었거나, 사용자의 pc가 해킹 당했을 경우
해당 계정을 통해서 스팸 메일 발송이 자주 일어난다.

이렇게 되면 큐가 1000개는 기본으로 넘어가게 되어 정상적인 메일도
같이 안나게 된다.

정상적인 메일서버면 큐개수가 많아야 20~30개이므로
큐가 100개를 넘어가면 경고 메일을 보내도록 하였다.

아래 스크립트는 큐메일 용도이다.
#!/bin/sh
# Send an email when there are more then 1000 messages in the mail queue
# This is counted by the amount of lines in the qmail-qread output, so it's an indication...

show=$1
qread="/var/qmail/bin/qmail-qread"
qreadIDs=`/var/qmail/bin/qmail-qread | awk '{print $6}' | sed 's/#//' | grep -v '^$' | uniq`
len=`$qread | wc -l`
SUBJECT="WARNING: There are $len messages in the mail queue!----Country Check Version"
EMAIL="your@mail.com"
EMAILMESSAGE="/tmp/emailmessage.txt"
echo "" > $EMAILMESSAGE
chmod 777 $EMAILMESSAGE


if [ $len -gt 100 ]; then

for id in $qreadIDs
do
case "$id" in
"0.0.0.0"|"127.0.0.1"|"8.8.8.8")
continue;;
*)
#find /var/qmail/queue/mess/ -name 1449183 | xargs cat | grep mysolution-remoteip | awk '{print $2}' | xargs geoiplookup
queueFile=`find /var/qmail/queue/mess/ -name $id`
IP=`cat $queueFile | grep mysolution-remoteip | awk '{print $2}'`
# FROM=`cat $queueFile | grep From:`
# Subject=`cat $queueFile | grep Subject:`
countryChk=`geoiplookup $IP`
receiveChk=`cat $queueFile | grep Received:`

echo "Queue ID : $id --------------" >> $EMAILMESSAGE
echo "$IP : $countryChk" >> $EMAILMESSAGE
echo $FROM >> $EMAILMESSAGE
echo $Subject >> $EMAILMESSAGE
echo "$receiveChk" >> $EMAILMESSAGE
echo "-----------------------------" >> $EMAILMESSAGE
echo "" >> $EMAILMESSAGE

if [ 1 -eq $# ]; then

if [ $show = "show" ]; then
cat $EMAILMESSAGE
fi
fi
esac
done

MESSAGE=$(cat $EMAILMESSAGE)
# send an email using /bin/mail
#mail -s "$SUBJECT" "$EMAIL" < $EMAILMESSAGE
printf "To: ${EMAIL}\nSubject: ${SUBJECT}\n\n $MESSAGE" | /var/qmail/bin/qmail-inject
rm -rf $EMAILMESSAGE

fi

2016년 12월 15일 목요일

mysql(mariadb) 테이블별 mysqldump 백업

디비별 디렉토리를 만들고, 테이블별 .sql 파일을 만든다.
[root@localhost cron.daily]# vim sqlBackup.sh 
#!/bin/bash

_DB_PASS='password'
_BACKUP_DIR='/backup/sqlBackup/'

find $_BACKUP_DIR* -mtime +7 -exec rm -fr {} \; > /dev/null 2>&1

db_list=`echo "show databases;" | mysql -N -uroot -p${_DB_PASS}`
eval `date "+day=%d; month=%m; year=%Y"`

INSTD="$_BACKUP_DIR/sql-backup-$year-$month-$day"
mkdir -p $INSTD

for db in $db_list; do
if [ ! -d $INSTD/$db ]
then
mkdir $INSTD/$db
fi
table_list=`echo "show tables" | mysql -N -uroot -p${_DB_PASS} $db`
for table in $table_list; do
mysqldump -uroot -p${_DB_PASS} --lock-all-table --opt --quick --quote-names $db $table > $INSTD/$db/${table}.sql
done
done

2016년 10월 12일 수요일

vpopmail(pop3) brute force 공격 차단

qmail vpopmail 을 쓰고 있다.

서버 점검 중 pop3로 접속시도를 하는 로그를 발견했다.

없는 아이디로 계속 시도하는 것과 계정은 있지만 패스워드를 계속 틀리게 입력하는 유형 2가지.
Oct 11 11:27:54 mail vpopmail[27836]: vchkpw-pop3: vpopmail user not found admin12@domain.com:109.104.203.62

Oct 11 15:02:11 mail vpopmail[15277]: vchkpw-pop3: password fail (pass: 'e603f6c507b3993651f0439553584c50') acount@domain.com:110.70.15.59

한두개가 아니라 같은 아이피가 계정만 바꿔서 계속 시도하고 있다.
fail2ban으로 vpopmail 차단을설정하면 좋은데, 실 운영서버라 fail2ban 설치하기가 쉽지 않다.

그래서 스크립트 작성.
#/bin/bash


help()
{
echo ""
echo "/var/log/maillog is default"
echo "iptable apply is not default"
echo "banCount 100 is default"
echo "-a : iptable applied"
echo "-f : maillog FILE PATH"
echo "-c : ban count"
echo ""
echo "Usae : $0 -a -c 100 -f /var/log/maillog "
exit 0
}


ignoreIPs=("222.222.222.222" "111.111.111.111")
maillog="/var/log/maillog"
banCount=100
fw=false


while getopts ac:f: opt
do
case $opt in
a)
fw=true
;;
c)
banCount=$OPTARG
;;
f)
maillog=$OPTARG
;;
*)
help
exit 0
;;
esac
done


banIPs=`grep -E 'user not found|password fail' ${maillog} | awk -F: '{print $NF}' | sort | uniq -dc | awk '{if ($1 > '"${banCount}"') print $NF}'`

for banIP in $banIPs
do
for ignoreIP in ${ignoreIPs[@]}
do
if [ $ignoreIP == $banIP ]
then
# echo "ignore IP: ${ignoreIP}"
# echo "ban IP : $banIP"
break
fi
done

echo "ban IP : $banIP ,whois : $(geoiplookup $banIP)"
if [ $fw = true ] ; then
iptables -A INPUT -s ${banIP}/24 -j DROP
fi

done


if [ $fw = true ] ; then
#remove duplicate iptables rules
#http://www.krazyworks.com/remove-duplicate-iptables-rules/
/sbin/service iptables save
/sbin/iptables-save | awk '!x[$0]++' > /tmp/iptables.conf
/sbin/iptables -F
/sbin/iptables-restore < /tmp/iptables.conf
/sbin/service iptables save
/sbin/service iptables restart
if [ -f /tmp/iptables.conf ] ; then /bin/rm -f /tmp/iptables.conf ; fi
fi


 

1. banCount 는 같은 IP가 해당 값이상일 경우만 가져온다.
실제사용자가 실패할 경우도 있기 때문에 100정도면 적당한 것 같다.

2. ignoreIPs는 차단하지 않을 IP를 적어준다.

3. iptable에 적용하는 데, 중복으로 계속 적용된다.
마지막 부분이 중복을 없애고 다시 설정하는 부분이다.

maillog 파일의 생성을 살펴보면 매일 오전 4시 마다 rotate 되고 있다
cron으로 4시 30분 부터 실행되게끔 걸어주면 되겠다.

2015년 8월 11일 화요일

리눅스 netstat 현재 접속 된 나라 확인.

#!/bin/bash

kisa_key="111111111111111111111";


IPLIST=`netstat -ant |grep "tcp" | awk '{print $5}' | cut -d: -f1 | sort | uniq`

for ip in $IPLIST
do
case "$ip" in
"0.0.0.0"|"127.0.0.1"|"8.8.8.8")
continue;;
*)
return_tmp_xml=`curl -s "http://whois.kisa.or.kr/openapi/ipascc.jsp?key=$kisa_key&query=$ip&answer=xml"`
countryCode=$(grep -oP "(?<=<countryCode>)[^<]+" <<< "$return_tmp_xml")
echo $ip : $countryCode
esac
done

예전에 위와 같이 KISA WHOIS 를 가지고 현재 접속된 나라를 찾았었는데,

geoiplookup 란 명령어가 있었다.

 

geoiplookup 명령어를 사용하려면 YUM 설치 하면 됨.

yum install GeoIP GeoIP-data

 

아래 처럼 하면 KISA KEY 받을 필요도 없고 좋다.
다만 몇몇개 IP는 'IP Address not found' 가 나온다.
#!/bin/bash



IPLIST=`netstat -ant |grep "tcp" | awk '{print $5}' | cut -d: -f1 | sort | uniq`

for ip in $IPLIST
do
case "$ip" in
"0.0.0.0"|"127.0.0.1"|"8.8.8.8")
continue;;
*)
geoiplookup $ip
esac
done

 

 

count 기능을 추가. 해당 아이피가 몇개가 접속해 있는 지 파악. (최종)
#!/bin/bash

#v2
#netstat -ant |grep "tcp" | awk '{print $5}' | cut -d: -f1 | grep -v "^$" | grep -v "0.0.0.0" | sort | uniq -c
netstat -ant |grep "tcp" | awk '{print $5}' | cut -d: -f1 | grep -v "^$" | grep -v "0.0.0.0" | grep -v "127.0.0.1" | sort | uniq -c > output.txt
while read -r line; do
count=$(echo $line | cut -f1 -d " ");
ip=$(echo $line | cut -f2 -d " ");
echo "count: $count, $ip : $(geoiplookup $ip)";
done < output.txt;
rm -rf output.txt

[root@mail foreignIp]# sh netstatIpCountryV2.sh 
count: 1, 108.168.211.204 : GeoIP Country Edition: IP Address not found
count: 1, 109.66.88.75 : GeoIP Country Edition: IP Address not found
count: 1, 112.173.207.169 : GeoIP Country Edition: IP Address not found
count: 3, 112.175.145.4 : GeoIP Country Edition: IP Address not found
count: 3, 112.221.136.253 : GeoIP Country Edition: IP Address not found
count: 1, 113.172.120.40 : GeoIP Country Edition: VN, Vietnam
...

 

참고

2014년 8월 19일 화요일

pid 값으로 강제 종료 스크립트.

service mysqld stop으로 mysql이 죽지를 않는다.

pkill mysqld 도 안 먹는다.

killall mysqld 도 안 먹는 다.

kill -9 pid 로는 먹는다.

근데 전부 다 죽여줘야 한다.

스크립트를 찾았다. 역시 있었다.
#!/bin/bash

[ -z "$1" ] && echo "Usage : Input Process .......... Please [scriptFileName ProcessName]" && exit

process_id=`ps -ax | grep "$1" | grep -vw "grep" | grep -vw $$ | awk '{print $1}'`

if [ -z "$process_id" ];then
echo "+-------------------------------------------------------------+"
echo "Not Found Process (입력하신 프로세스를 찾지 못했습니다.) ...... Done"
echo "+-------------------------------------------------------------+"
exit
else
process_id_number=`ps -ax | grep "$1" | grep -vw "grep" | grep -vw $$ | awk '{print $1}'`

for i in ${process_id_number} ;do
kill -9 $i &> /dev/null
printf "%-40s %-s\n" "$i PID Killed" "$(echo -ne "[ \\033[01;32m OK \\033[0m ]")"
done
sleep 2;
echo "+-------------------------------------------------------------+"
echo "Process Kill OK (프로세스가 강제적으로 종료 되었습니다.) ...... Done"
echo "+-------------------------------------------------------------+"
fi

출처

2014년 8월 13일 수요일

apache 2.0.x 버젼 startssl 자동.

apache 2.2.x 버젼 이상이 아닌경우 ssl 적용 아파치 실행은
./apachectl startssl

위처럼 startssl 로 실행해야 ssl 이 적용된 아파치가 실행된다.



그냥 start 만으로 ssl 이 실행되도록 스크립트를 변경하자.
vim /usr/bin/apachectl

...
case $ARGV in
start)
    $HTTPD -k start -DSSL
    ERROR=$?
    ;;
stop|restart|graceful)
    $HTTPD -k $ARGV
    ERROR=$?
    ;;
startssl|sslstart|start-SSL)
    $HTTPD -k start -DSSL
    ERROR=$?
    ;;
configtest)
    $HTTPD -t
    ERROR=$?
...



start 인수가 들어오면 원래는 $HTTPD -k $ARGV를 실행 하게끔 되어 있지만,
따로 빼내어 $HTTPD -k start -DSSL 를 실행하도록 수정 하였다.

2014년 7월 8일 화요일

bash 스크립트 사용시 주의 사항

1.if 문을 쓸 때는 아래처럼 if 다음에 꼭 한칸을 띄워줘야 한다.
if [ $checkTmp = 'y' ]

에러 : syntax error near unexpected token `then'
1. 변수를 지정할때는 = 이전,다음에 빈칸이 있으면 안된다.
TotalMem=`free -m | grep Mem: | awk {'print $2'}`

에러 : command not found

2014년 1월 8일 수요일

리눅스 트래픽 체크(sulinux 툴)

#!/bin/bash
if [ "$1" == "" ] ; then
echo "사용법 : $0 장치명 [delay]"
echo "예) $0 eth0 3 "
exit 1
fi
if [ "$2" == "" ] ; then delay=3 ; else delay=$2 ; fi

echo "시간 : 수신(Kbit/Sec) / 송신(Kbit/Sec)"
while ( true ) ; do
rx1=`grep $1 /proc/net/dev | awk '{print $1}' | sed 's/.*://'`
tx1=`grep $1 /proc/net/dev | awk '{print $9}'`
sleep $delay
rx2=`grep $1 /proc/net/dev | awk '{print $1}' | sed 's/.*://'`
tx2=`grep $1 /proc/net/dev | awk '{print $9}'`

# 1024/8 == 128
rx3=$(((rx2-rx1)/128/delay))
tx3=$(((tx2-tx1)/128/delay))

echo "`date '+%k:%M:%S'` : $rx3 / $tx3"
done

2012년 8월 9일 목요일

tmp 해킹툴 삭제 스크립트

서버의 트래픽이 갑자기  100M이상 늘어나는 현상이 있었다.

서버체크를 해보니 /tmp 디렉토리에 숨김파일로 공격툴이 심어져 있고,

다른 쪽으로 공격을 하고 있었다.

일단 해당 프로세스를 죽인후 해당 파일을 삭제처리 하였다.

tmp 해킹에 대해서 검색하여, tmp 디렉토에서는 실행할  수 없게끔 설정하였다.

문제는 /tmp/.hack 이렇게 경로로 실행을 하면 실행 되지 않지만,

sh /tmp/.hack 이런 식으로 주면 실행이 가능하다.

해당 공격툴의 소유자가 nobody 인 걸로 봐서 웹을 통한 해킹인 것으로 보이는 데,

해당 문제는 다른 이유로 만질 수 있는 상태가 아니다.

tmpwatch를 이용해서 /tmp 디렉토리에서 해킹툴을 지속적으로 삭제해주도록 걸어 놨다.

몇일 간 문제가 없어 보였으나 ,  다시 트래픽이 쳐서 확인 해 보았다.

공격툴이 정상적으로 삭제 되어졌으나 문제는 메모리에 이미 로드 되어 실행이 되고 있는 상태인 것 같다.

프로세스를 확인 하면 [sh] <defunct> 이렇게 나오는 부분이 있는 데, 역시나 삭제된 해킹툴이다.

해서 /tmp 디렉토리에서 실행되는 프로그램은 죽여버리고, 삭제 시키는 스크립트를 만들었다.

----------------
#/bin/sh

while (( 1 ))
do

for f in `find /tmp/ -type f | grep -v "sess_*"`
do

if [ "$f" != "." ] && [ "$f" != ".." ] && [ "$f" != ".ICE-unix" ] && [ "$f" != ".font-unix" ]
then
if [ -e $f ]
then

#echo $f' is file'
lsof $f | sed '1d' | awk '{print $2}' | xargs kill -9
rm -rf $f
fi
fi

done
sleep 5
done

해당 프로그램을 실행하면 5초 마다 실행 되도록 작성 해 놓았다.

부하는 그리 크지 않는 듯 하나, 루프를 돌리기 싫다면, while 부분을 삭제하고 크론으로 등록하여 사용해도 좋을 듯하다.