Tomcat Clustering 시 물리적으로 하나의 서버에서 다수의 Tomcat을 실행할 경우에
해당 포트에 대해 방화벽을 오픈하지 않기 위해 mcastBindAddress="127.0.0.1" 옵션을 사용했다.
<Membership className="org.apache.catalina.tribes.membership.McastService"
      address="228.0.0.7"
      mcastBindAddress="127.0.0.1"
      port="4000"
      frequency="500"
      dropTime="3000"/>

<Receiver className="org.apache.catalina.tribes.transport.nio.NioReceiver"
      address="192.168.1.55"
      port="5001"
      selectorTimeout="100"
      maxThreads="6"/>


이럴 경우 아래와 같은 오류가 발생했다.
org.apache.catalina.tribes.ChannelException: java.io.IOException: Invalid argument; No faulty members identified.


요즘 생산되는 서버에는 기본적으로 IPv6에 대해 활성화가 되어 있는 경우가 많다.
즉, localhost에 대해 IPv4와 IPv6의 충돌로 발생한 경우다.

Tomcat 실행 옵션에 아래와 같은 Parameter를 추가하여 해결한다.

JAVA_OPTS="$JAVA_OPTS -Djava.net.preferIPv4Stack=true"


참고로, 내가 경험한 Tomcat Version은 7.0.29, 7.0.59 이다.

2014/05/27 15:23 2014/05/27 15:23

/bin/sh^M:bad interpreter

Dev 2014/02/25 15:22
Linux Server에 shell script를 실행하고자 할 경우 간혹 "/bin/sh^M:bad interpreter" 메시지 출력하며
실행이 되지 않는 경우가 있다.
보통 Windows OS 환경에서 파일을 생성 하여 서버에 올린 경우에 발생하는데
vi 에서 간단한 명령을 실행해 해결할 수 있다.

some shell script code line1..
some shell script code line2...

// 아래 명령어 입력
:set ff=unix   // Enter
:wq   // Enter




2014/02/25 15:22 2014/02/25 15:22
얼마전 CentOS 5.4에서 yum으로 update를 진행했다.
이후, system-config-network 명령을 실행하니
"UnicodeDecodeError: 'ascii' codec can't decode byte 0xec in position 0: ordinal not in range(128)"
이런 오류를 출력하며 실행이 안되었다.

python에서 utf-8 string을 읽으면서 발생된 에러인듯 싶은데
구글링을 이용해 해답을 얻을 수 있었다.

[@hostname]# vi /usr/share/system-config-network/netconf-tui.py
파일 상단 import sys 를 찾아 아랫줄에 아래와 같이 삽입
reload(sys)
sys.setdefaultencoding('utf-8')

2012/07/20 14:04 2012/07/20 14:04
JBoss AS는 오픈소스  미들웨어로 매우 유용하게 사용할 수 있다.
여러가지 자원들을 포함하고 있기 때문에 Java 기반의 프로젝트 수행에 무리가 없다.
하지만, 국내에는 JBoss AS 사용이 많지 않기 때문에 관련 자료가 부실하다.
그나마, 국내 커뮤니티로 JBoss User Group(http://cafe.naver.com/jbossug/)가 있지만
JBoss 6 보다는 JBoss 5.x 에 대한 내용이 많다.

얼마전 회사내 프로젝트를 수행 중 분석서버에서 이용할 수 있도록 하기 위해
로그 표준화 작업을 통해 EJB에서 로그를 남기도록 처리 할 일이 있었다.
JBoss 5.x까지는 로깅 프레임워크로 Log4j를 이용했지만, JBoss 6 부터는 자체 로깅 서비스를
이용해야만 될수 있도록 변경되었다. 그나마 다행인것은 Log4j도 미력하지만 이용할 수 있도록
지원이 된다는 것인데... 며칠동안 삽질을 했지만 안됐다.

결국, 많은 자료를 찾던중 해결책을 찾았다.

아래 절차에 따라 patch하면 정상적으로 사용할 수 있다.

1. 설치된 JBoss 6.0.0.Final 버전의 $JBOSS_HOME/server/$PROFILE(all, default..)의 deployers/jboss-logging.deployer/META-INF/logmanager-jboss-beans.xml 파일 내용중 (A)사항을 (B)사항으로 변경한다.
   (A) <bean name="JBossLogService" class="org.jboss.logmanager.LogService" mode="On Demand"/>
   (B) <bean name="JBossLogService" class="java.lang.Object" mode="On Demand"/>

  => (A) 사항을 (B)사항으로 변경했을 경우, boot.log에 다른 로그까지 계속 쌓이게 된다.
       그러므로, 적용하지 않는것이 좋겠다.

2. JBAS-8791-1.zip 파일의 압축을 해제하여 아래처럼 각각의 해당 디렉토리에 있는 파일을 덮어쓴다.
   JBAS-8791-1.zip : https://issues.jboss.org/secure/attachment/12340210/JBAS-8791-1.zip
   jboss-logmanager-log4j.jar -> $JBOSS_HOME/common/lib/
   jboss-logmanager.jar -> $JBOSS_HOME/lib/
   logging-service-metadata.jar -> $JBOSS_HOME/server/$PROFILE/deployers/jboss-logging.deployer/

3. log4j.jar파일들을 log4j-1.2.16.jar 파일로 모두 대체한다.
   log4j-1.2.16.jar download : http://logging.apache.org/log4j/1.2/download.html
   대상) (1) $JBOSS_HOME/client/log4j.jar -> 삭제 또는 jar확장자 대신 다른이름으로 변경, log4j-1.2.16.jar 복사
         (2) $JBOSS_HOME/common/lib/log4j.jar -> 삭제 또는 jar확장자 대신 다른이름으로 변경, log4j-1.2.16.jar 복사


아마도 이 내용은 다음번 JBoss AS 릴리즈에 반영이 될 것 같지만, 글을 쓰는 현재 시점에 JBoss AS 6.0.0 Final 버전에 대해서는 이렇게 Patch를 해야 할듯 하다.



2011/03/03 10:04 2011/03/03 10:04

CBD 산출물 예시

Dev 2010/07/13 13:53
Phase
Activity
Task
산출물
분석
요구 사항 정의 시스템 비전 정의 시스템 비전 정의서
도메인 모델링 도메인 명세서
용어집
현행 시스템 분석 현행 시스템 분석서
비즈니스 모델링 비즈니스 정의서
요구사항 명세 요구사항 명세서
아키텍처 정의 소프트웨어 아키텍처 정의 소프트웨어 아키텍처 정의서
시스템 아키텍처 정의 시스템 아키텍처 정의서
표준 지침 수립 표준 지침서
요구 사항 분석 유스케이스 모델링 유스케이스 명세서
사용자 인터페이스 프로토타이핑 사용자 인터페이스 정의서
클래스 모델링 클래스 명세서
테스트케이스 정의 테스트케이스 정의서
유즈케이스대클래스상관분석 유즈케이스대클래스상관도
설계
기본 설계 컴포넌트 식별 컴포넌트 목록
컴포넌트 아키텍처 정의서
재사용 컴포넌트 선정 재사용 컴포넌트 선정내역서
인터페이스 상호작용 정의 인터페이스 상호작용 명세서
컴포넌트 명세 인터페이스 명세서
컴포넌트 명세서
사용자 인터페이스 설계 사용자 인터페이스 설계서
데이터 모델링 데이터 설계서
클래스대엔티티상관 분석 클래스대엔티티상관도
상세 설계 컴포넌트 내부 설계 컴포넌트 설계서
컴포넌트 구현 설계 컴포넌트 구현 설계서
사용자 인터페이스 구현 설계 사용자 인터페이스 구현 설계서
데이터베이스 설계 데이터베이스 설계서
클래스대테이블상관분석 클래스대테이블상관도
구현 및
테스트
테스트 준비 테스트 계획 테스트 계획서
컴포넌트 테스트 설계 컴포넌트 테스트 설계서
구현 데이터베이스 구축 물리적 데이터베이스
컴포넌트 구현 및 테스트 컴포넌트 코드
컴포넌트 테스트 결과서
사용자 인터페이스 구현 사용자 인터페이스 코드
통합 테스트 통합 테스트 설계 통합 테스트 설계서
통합 테스트 수행 통합 테스트 결과서
시스템 테스트 시스템 테스트 설계 시스템 테스트 설계서
시스템 테스트 수행 시스템 테스트 결과서
지침서 작성 사용자 Manual 작성 사용자 Manual
운용자 지침서 작성 운용자 지침서
인도
시스템 설치 시스템 설치 계획 시스템 설치 계획서
시스템 설치 실시 시스템 설치보고서
인수 지원 인수 테스트 지원 인수 테스트 결과서
사용자 교육 사용자 교육 보고서


출처 : http://webdoors.tistory.com/650
2010/07/13 13:53 2010/07/13 13:53
Linux에서 IP Address를 확인하기 위해서는 보통 아래 명령어를 이용해 볼수 있다.
[user@localhost ~]$ /sbin/ifconfig -a
eth0      Link encap:Ethernet  HWaddr ....
중략 ....

lo        Link encap:Local Loopback ...
중략 ...


보통 Shell script로 IP를 확인해서 변수에 할당해야 할일이 간혹 있는데
아래 명령어를 이용하면 될것 같다.
[usr@localhost ~]$ /sbin/ifconfig eth0 | /bin/sed -n '/addr:/p' | /bin/awk '{print $2}' | /bin/sed 's/addr://g' | /bin/sed '/^$/d'


1) /sbin/ifconfig eth0  -  eth0 의 ethernet정보 확인
2) /bin/sed -n '/addr:/p'  -  1) 에서 출력된 정보 중 'addr:'문자가 있는 줄만 필터해서 출력
3) /bin/awk '{print $2}'  -  2)에서 출력된 정보 중 2번째 단어만 출력
3) /bin/sed 's/addr://g'  -  3)에서 출력된 정보 중 'addr:' 문자 제외 후 출력
4) /bin/sed '/^$/d'  - 4)에서 출력된 정보 중 빈줄 삭제



2010/05/10 11:49 2010/05/10 11:49
Tomcat을 JSVC로 구동 시 catalina.out 파일로 계속 로그가 쌓이게 된다.
이문제를 해결하기 위해 인터넷을 찾아본 결과 리눅스의 logrotate 명령을 이용해
쉽게 해결이 될 수 있었다.

먼저, logrotate 는 cron에 의해 구동되는데 설정파일의 위치는
/etc/logrotate.conf에 있으며
개개의 설정은 /etc/logrotate.d/ 디렉토리 안에서 정의된 파일을 처리하는 방식이다.

# 추가 생성
[root@host ~]# vi /etc/logrotate.d/tomcat
/usr/local/tomcat/logs/catalina.out {
        notifempty
        missingok
        rotate 30
        daily
        copytruncate
        dateext
        postrotate
                /bin/chown tomcat:tomcat /usr/local/tomcat/logs/catalina.out-*
        endscript
}
:wq
[root@host ~]#
# 실행 test
[root@host ~]# logrotate -f /etc/logrotate.d/tomcat
[root@host ~]# ls -l /usr/local/tomcat/logs


notifempty              -  log 파일의 내용이 비어 있는 경우 순환을 하지 않음.
missingok              -  만약 파일이 존재하지 않더라도 무시하고 진행
rotate count           -  rotate 순환주기를 설정할 수 있으며 곧 저장하고자 하는 파일의 개수를 의미
daily                     -  매일 logrotate를 실행
copytruncate          -  이 옵션을 쓰지 않으면 기존의 맨처음 로그가 생성된 파일에 계속해서 로그가 쌓이게 된다.
                                이러한 원인은 톰캣의 로그가 System.err 객체나 System.out을 사용하기 때문에
                                시스템의 raw디바이스로 출력이 되어 파이프를 타지 않기 때문이란다.
                                따라서 원래 로그를 다른이름으로 저장하고 새로운 catalina.out을 생성한다해도
                                실제 로그 스트림은 다른이름으로 지정된 원래 로그쪽으로 계속해서 쌓이게 된단다.
                                이걸 방지하기 위해 현재 로그내용을 복사하여 백업본으로 저장한후
                                원본 로그의 내용을 비우는 방식으로 저장해야 하도록 한다.
dateext                   -  날짜 형식을 붙여 로그 파일을 저장한다.
postrotate/endscript - logrotate를 실행한 후에 취하고자 하는 액션을 정의

2010/04/22 18:45 2010/04/22 18:45
Apache-Tomcat Native lib Install

source download : http://tomcat.apache.org/native-doc/index.html

rpm -qa|grep apr-devel

yum search apr-devel
yum install apr-devel

./configure --with-apr=/usr/bin/apr-1-config --with-java-home=/usr/local/jdk

make
make install

# installed dir => /usr/local/apr

cat "export LD_LIBRARY_PATH=\$LD_LIBRARY_PATH:/usr/local/apr/lib" >> /etc/profile
source /etc/profile

service tomcat restart


2010/04/05 16:38 2010/04/05 16:38
* Apache Tomcat 일반계정으로 구동하기
  - jsvc 이용(Tomcat ver 6.0.18)

Apache Tomcat 웹 사이트에서 Tomcat 5.5 / Tomcat 6.x binary 를 다운로드 받아
압축을 풀어보면 bin 디렉토리 안에 jsvc.tar.gz 파일이 존재한다.
jsvc.tar.gz을 압축풀고 컴파일 한다.

아래는 설치(명령어만) 과정이다.
[root@host ~]# cd /usr/local/tomcat/bin
[root@host ~]# tar zxf jsvc.tar.gz
[root@host ~]# cd jsvc-src
# 실행가능하도록 퍼미션 변경
[root@host ~]# chmod 755 ./configure
# compile전 옵션 설정
[root@host ~]# ./configure --with-java=/usr/local/jdk
# compile
[root@host ~]# make
# daemon file 복사
[root@host ~]# cp native/jsvc $CATALINA_HOME/bin
# daemon 실행 shell script 복사
[root@host ~]# cp native/Tomcat5.sh $CATALINA_HOME/bin
# shell script 환경 설정(path 설정, tomcat user)
[root@host ~]# vi $CATALINA_HOME/bin/Tomcat5.sh
# 기동
[root@host ~]# $CATALINA_HOME/bin/Tomcat5.sh start
# 종료
[root@host ~]# $CATALINA_HOME/bin/Tomcat5.sh stop


아래는 Tomcat5.sh 파일을 수정해 Redhat계열의 init.d에서 돌아가도록 만든 파일이다.
#!/bin/sh
# Comments to support chkconfig on RedHat Linux
# chkconfig: 2345 80 20
# description: Apache Tomcat on JSVC tool.

# Source function library.
. /etc/rc.d/init.d/functions

##############################################################################
#
#   Copyright 2004 The Apache Software Foundation.
#
#   Licensed under the Apache License, Version 2.0 (the "License");
#   you may not use this file except in compliance with the License.
#   You may obtain a copy of the License at
#
#       http://www.apache.org/licenses/LICENSE-2.0
#
#   Unless required by applicable law or agreed to in writing, software
#   distributed under the License is distributed on an "AS IS" BASIS,
#   WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
#   See the License for the specific language governing permissions and
#   limitations under the License.
##############################################################################
#
# Small shell script to show how to start/stop Tomcat using jsvc
# If you want to have Tomcat running on port 80 please modify the server.xml
# file:
#
#    <!-- Define a non-SSL HTTP/1.1 Connector on port 80 -->
#    <Connector className="org.apache.catalina.connector.http.HttpConnector"
#               port="80" minProcessors="5" maxProcessors="75"
#               enableLookups="true" redirectPort="8443"
#               acceptCount="10" debug="0" connectionTimeout="60000"/>
#
# That is for Tomcat-5.0.x (Apache Tomcat/5.0)
#
# Adapt the following lines to your configuration


JAVA_HOME=/usr/local/jdk
CATALINA_HOME=/usr/local/tomcat
DAEMON_HOME=/usr/local/tomcat
TOMCAT_USER=tomcat

# for multi instances adapt those lines.
TMP_DIR=/var/tmp
PID_FILE=/var/run/jsvc.pid
CATALINA_BASE=/usr/local/tomcat

CATALINA_OPTS="-Djava.library.path=/usr/local/apr/lib"
CLASSPATH=\
$JAVA_HOME/lib/tools.jar:\
$CATALINA_HOME/bin/commons-daemon.jar:\
$CATALINA_HOME/bin/bootstrap.jar

PROGNAME=`basename $0`
RETVAL=0

start()
{
    START_COMMAND="\
    $DAEMON_HOME/bin/jsvc \
    -user $TOMCAT_USER
    -home $JAVA_HOME
    -Dcatalina.home=$CATALINA_HOME \
    -Dcatalina.base=$CATALINA_BASE \
    -Djava.io.tmpdir=$TMP_DIR \
    -wait 10 \
    -pidfile $PID_FILE \
    -outfile $CATALINA_HOME/logs/catalina.out \
    -errfile '&1' \
    $CATALINA_OPTS \
    -cp $CLASSPATH \
    org.apache.catalina.startup.Bootstrap"
    #
    # To get a verbose JVM \
    #-verbos \
    # To get a debug of jsvc
    #-debub

    echo -n $"Starting $PROGNAME : "
    daemon $START_COMMAND
    RETVAL=$?
    [ $RETVAL -eq 0 ] && [ -f $PID_FILE ]
    echo
    return $RETVAL
}


stop()
{
    STOP_COMMAND="\
    $DAEMON_HOME/bin/jsvc \
    -stop \
    -pidfile $PID_FILE \
    org.apache.catalina.startup.Bootstrap"

    echo -n $"Stopping $PROGNAME : "
    killproc jsvc 
    RETVAL=$?
    echo
    return $RETVAL
}

restart()
{
    stop
    start
}


case "$1" in
  start)
    start
    ;;

  stop)
    stop 
    ;;

  status)
    status -p $PID_FILE jsvc
    ;;

  restart)
    restart
    ;;

  *)
    echo "Usage $PROGNAME start/stop"
    exit 1;;
esac

exit $?


2010/04/05 16:31 2010/04/05 16:31

SQL to Java code 변환

Dev 2010/03/30 15:53
얼마전, AcroEdit를 설치해 보니, 매크로 스크립트 기능 중 플러그인 식으로
라인단위로 코드로 감싸는 기능이 있어 편리하겠다는 생각이 들었다.
하지만, Java 관련 개발 작업 시 Eclipse를 주로 사용하는 사람에게
그 기능을 사용하기 위해 다시 AcroEdit를 실행하고 다시 스크립트를 실행하는게 왠지
불편했다.
이럴바에 간단하게 만들어보자라는 취지로 해 봤다.

DB 연동해서 개발을 하다 보면 툴에서 SQL을 테스트하고 작성 완료해서
실제 Java 코딩으로 옮겨야 할 경우 일일이 코드에 삽입을 하게 된다.
예를 들어,
String sql   = "select a, b, c, d";
         sql += "   from tablename";
         sql += " where a = b      ";
         sql += "     and c = '1234';

이런 식의 코드나 StringBuffer 클래스를 이용하는

StringBuffer sql = new StringBuffer();
sql.append("select a, b, c, d \n");
sql.append("   from tablename \n");
sql.append(" where a = b      \n");
sql.append("     and c = '1234' \n);

이런 코드를 생성하기 마련이다.
물론, iBATIS를 이용하는 경우도 많지만 iBATIS를 이용하지 않을 경우에
위와 같은 일은 참 번거로운 일이 될것이다.

차라리, 이클립스에 실행 가능한 자바 클래스를 하나 만들어서 필요할 때 마다
실행해서 복사 후 붙여넣기를 하면 좋겠다는 생각이다.

/**
* 복사한 SQL문을 Java에서 사용 가능하도록 Code로 변환한다.
* @author dawnst
* 2010.03.29
*/

public class Sql2Java
{
   public static void main(String[] args)
   {   
       Sql2Java sj = new Sql2Java();
       System.out.println(sj.sql2Java().toString());
   }

   /**
    * ClipBoard 에 있는 내용을 반환한다.
    * @return String
    */
   private String getClipBoard()
   {
       String ret = "";
      
       java.awt.datatransfer.Clipboard clipboard = java.awt.Toolkit.getDefaultToolkit().getSystemClipboard();
       java.awt.datatransfer.Transferable data = clipboard.getContents(this);
       try
       {
           ret = (String) data.getTransferData(java.awt.datatransfer.DataFlavor.stringFlavor);
       }
       catch (java.awt.datatransfer.UnsupportedFlavorException e)
       {
           e.printStackTrace();
       }
       catch (java.io.IOException e)
       {
           e.printStackTrace();
       }
      
       return ret;
   }
  
   /**
    * ClipBoard의 SQL문을 Java의 SQL문 형태로 변환해 반환한다.
    * @return StringBuffer
    */
   private StringBuffer sql2Java()
   {
       String clipBoard = getClipBoard();
       StringBuffer buffer = new StringBuffer();
      
       if(clipBoard != null && clipBoard.length() > 0)
       {
           String [] line = clipBoard.split("\n");
          
           // SQL문 Line의 문자수를 세어 가장 많은 문자수를 찾는다.
           int maxCharLength = 0;
           for(int i=0; i<line.length; i++)
           {
               if(maxCharLength < line[i].length())
               {
                   maxCharLength = line[i].length();
               }
           }
          
          
           for(int i=0; i<line.length; i++)
           {
               if(i==0)
               {
                   buffer.append("StringBuffer sql = new StringBuffer();\n");
                   buffer.append("sql.             append(\""+line[i]);
               }
               else
               {
                   buffer.append("sql.append(\"\\n\").append(\""+line[i]);

               }
              
               // 최대 SQL 문자수 보다 적은 Line은  최대 문자수 만큼 공백으로 자리수를 채운다.
               for(int j=0; j<maxCharLength - line[i].length(); j++)
               {
                   buffer.append(" ");
               }
              
               buffer.append("\");");
               buffer.append("\n");
           }
       }
      
       return buffer;
   }
}

사용 방법은
1. 이클립스에 프로젝트를 하나 만들던가, 아니면, 기존에 만들어진 프로젝트에 클래스 하나를 만들어 run에 등록한다.
2. SQL 툴에서 만들어지 SQL문을 복사(Ctl+c)한다
3. run에 등록된 내용을 실행한다.
4. 출력창에 출력된 Java SQL 코드를 복사해 개발하는데 붙여넣기 등, 이용한다.


실행 결과
StringBuffer sql = new StringBuffer();
sql.             append("select a, b, c, d");
sql.append("\n").append("  from tablename ");
sql.append("\n").append(" where a = b     ");
sql.append("\n").append("   and c = '1234'");

2010/03/30 15:53 2010/03/30 15:53