#Liberty

[WebSphere] Liberty Profile & Eclipse 연동 개발 환경 구축 가이드 (WDT 설치)

IBM WebSphere Liberty Profile(WLP)을 로컬 개발 환경인 Eclipse에 연동하여 애플리케이션 개발, 배포, 디버깅 환경을 구축하는 절차를 정리합니다. IBM WebSphere Developer Tools(WDT) 플러그인 설치 및 서버 런타임 구성 과정을 포함합니다.

Test Environment

  • OS: Windows 10
  • IDE: Eclipse IDE for Enterprise Java Developers (2020-06 이상 권장)
  • Middleware: WebSphere Liberty Profile (Kernel or Core)

1. 사전 준비 (Prerequisites)

Liberty 개발 환경을 구축하기 위해서는 Java SDK와 Eclipse가 미리 설치되어 있어야 합니다.

  • JDK: 1.8 이상 설치 및 환경 변수(JAVA_HOME) 설정.
  • Eclipse: 'Eclipse IDE for Enterprise Java and Web Developers' 패키지 사용 권장.

2. WebSphere Developer Tools (WDT) 플러그인 설치

Eclipse에서 Liberty 서버를 제어하기 위해서는 전용 플러그인을 설치해야 합니다.

설치 절차

  1. Eclipse 메뉴에서 Help > Eclipse Marketplace...를 선택합니다.
  2. 검색창에 IBM Liberty 또는 WebSphere Developer Tools를 입력합니다.
  3. "IBM Liberty Developer Tools" 항목을 찾아 Install 버튼을 클릭합니다.
  4. 라이선스 동의 후 설치를 진행하며, 완료 후 Eclipse를 재시작합니다.

3. Liberty 런타임(Runtime) 등록

이미 설치된 Liberty Core를 Eclipse에 등록하거나, Eclipse를 통해 새로 다운로드할 수 있습니다.

서버 등록 과정

  1. Servers 뷰에서 우클릭 > New > Server 선택.
  2. 서버 타입에서 IBM > WebSphere Liberty 선택.
  3. Server's host namelocalhost, Server name은 식별 가능한 이름 입력.
  4. Runtime Environment 설정 단계:
    • 기존 설치된 경우: 'Choose an existing installation' 선택 후 Liberty 설치 경로(wlp 폴더) 지정.
    • 새로 설치할 경우: 'Install from an archive or a repository' 선택 후 원하는 버전 다운로드.
  5. Finish를 클릭하여 설정을 완료합니다.

4. 서버 구동 및 애플리케이션 배포

설정이 완료되면 Eclipse 내에서 서버를 제어할 수 있습니다.

서버 제어

  • Start: Servers 뷰에서 서버 우클릭 > Start (또는 Debug).
  • Console 확인: CWWKF0011I: The server defaultServer is ready to run a smarter planet. 메시지가 뜨면 정상 구동된 것입니다.

프로젝트 배포

  1. Dynamic Web Project 생성.
  2. 프로젝트 우클릭 > Run As > Run on Server.
  3. 등록한 Liberty 서버를 선택하고 Finish.
  4. server.xml에 애플리케이션 구성이 자동으로 추가되며 배포가 진행됩니다.

5. 참고 영상 (Reference Video)

실제 설치 및 구동 과정에 대한 데모 영상입니다.


Next Step:
개발 환경 구축이 완료되었다면, server.xml 파일의 <featureManager> 섹션을 수정하여 필요한 기능(JSP, Servlet, JDBC 등)을 활성화하는 방법을 학습해 보십시오.

Open Stream →
#tomcat

[Tomcat] Windows 환경 Apache Tomcat 9 설치 및 디렉토리 구조 완벽 가이드

Windows 10 환경에서 Java 기반 웹 애플리케이션 서버인 Apache Tomcat 9을 설치하는 과정을 정리합니다. JDK 설치 확인부터 다운로드, 압축 해제, 그리고 주요 디렉토리(bin, conf, logs)의 역할과 구동 테스트까지 다룹니다.

0. 사전 준비 (Prerequisites)

Tomcat은 Java로 구동되므로 JDK(Java Development Kit)가 필수입니다. 설치 전 반드시 Java 환경 변수가 설정되어 있는지 확인해야 합니다.

Java 설치 확인

:: CMD 창에서 확인
java -version
javac -version
Check Point: 버전 정보가 출력되지 않는다면 JDK를 먼저 설치하고, 시스템 환경 변수(JAVA_HOME, PATH)를 설정해야 합니다. Tomcat은 실행 시 JAVA_HOME을 참조합니다.

1. 다운로드 및 설치 (Download & Install)

설치형(Installer)보다는 압축형(Zip)을 사용하는 것이 디렉토리 관리가 용이하고, 여러 버전을 동시에 관리하기 좋습니다.

다운로드

  • 공식 사이트: http://tomcat.apache.org/
  • 버전 선택: Tomcat 9 (Latest Stable) > Binary Distributions > Core: zip (64-bit/32-bit Windows)

설치 (압축 해제)

다운로드한 Zip 파일을 원하는 경로에 압축 해제하는 것만으로 설치는 끝납니다.

  • 설치 경로 예시: E:\APP\WAS\TOMCAT9

2. 주요 디렉토리 구조 (Directory Structure)

압축을 해제하면 다음과 같은 폴더 구조를 볼 수 있습니다. 각 폴더의 역할을 이해하는 것이 WAS 운영의 첫걸음입니다.

디렉토리 역할 및 주요 파일
/bin 서버 실행 및 종료 스크립트가 위치합니다.
- startup.bat: 서버 시작 (Windows)
- shutdown.bat: 서버 중지 (Windows)
- catalina.bat: 실행 환경 변수 및 옵션 설정
/conf 서버 전체 설정 파일이 위치합니다.
- server.xml: 포트(8080, 8009), 엔진 설정
- web.xml: 세션 타임아웃, MIME 타입 등 공통 설정
/lib Tomcat 구동에 필요한 라이브러리(Jar) 저장소 (JDBC 드라이버 등 포함)
/logs 서버 로그가 저장됩니다.
- catalina.yyyy-mm-dd.log: 엔진 로그
- localhost_access_log: 접속 로그
/webapps 웹 애플리케이션(WAR 파일)을 배포하는 기본 경로입니다.

3. 구동 및 검증 (Start & Verify)

설치가 제대로 되었는지 서버를 켜서 확인합니다.

서버 구동

:: bin 디렉토리로 이동
cd E:\APP\WAS\TOMCAT9\bin

:: 실행 스크립트 동작
startup.bat

새로운 CMD 창이 뜨면서 로그가 올라가고, 마지막에 Server startup in [xxx] ms 메시지가 보이면 구동 성공입니다.

접속 테스트

브라우저를 열고 http://localhost:8080 에 접속합니다. 고양이 그림이 있는 Tomcat 기본 페이지가 뜬다면 정상적으로 설치된 것입니다.


Next Step:
기본 설치가 완료되었습니다. 다음 포스팅에서는 server.xml을 수정하여 HTTP 포트를 변경하거나, 인코딩 설정을 추가하는 Tomcat 기본 설정 튜닝에 대해 알아보겠습니다.

Open Stream →
#IBM HTTPServer

[IHS] SSL/TLS 보안 강화: Protocol 비활성화 및 Cipher Suite 화이트리스트 설정

IBM HTTP Server(IHS)는 Apache 기반이지만, SSL 모듈은 별도의 mod_ibm_ssl을 사용합니다. 따라서 커뮤니티 Apache(mod_ssl)와 프로토콜 설정 문법이 상이합니다. 두 서버 간의 설정 차이를 비교하고, IHS v8.5 환경에서의 보안 강화 설정을 정리합니다.

[Image of SSL TLS handshake process]

1. Apache vs IHS 설정 차이점 (Comparison)

두 웹 서버는 SSL/TLS 핸드쉐이크를 처리하는 엔진과 모듈이 다르기 때문에, httpd.conf에 작성하는 지시어(Directive)가 다릅니다. 마이그레이션이나 운영 시 혼동하지 않도록 주의해야 합니다.

구분 Apache HTTP Server (Community) IBM HTTP Server (IHS)
사용 모듈 mod_ssl (OpenSSL 기반) mod_ibm_ssl (IBM GSKit 기반)
프로토콜 설정 SSLProtocol (한 줄로 제어) SSLProtocolDisable
SSLProtocolEnable (개별 제어)
Cipher 설정 SSLCipherSuite SSLCipherSpec

설정 문법 비교 예시

Apache (mod_ssl)

# 모든 프로토콜에서 SSLv2, SSLv3 제외
SSLProtocol all -SSLv2 -SSLv3

# Cipher Suite 설정 (OpenSSL 명명규칙 사용)
SSLCipherSuite HIGH:MEDIUM:!aNULL:!MD5

IHS (mod_ibm_ssl)

# 개별적으로 활성/비활성 지정
SSLProtocolDisable SSLv2
SSLProtocolDisable SSLv3
SSLProtocolEnable TLSv12

# Cipher Spec 설정 (Long Name 사용, 초기화 후 추가 방식 권장)
SSLCipherSpec ALL NONE
SSLCipherSpec ALL +TLS_RSA_WITH_AES_128_CBC_SHA

2. IHS 보안 설정 가이드 (Configuration)

IHS v8.5 이상 환경에서 취약한 프로토콜을 차단하고 안전한 Cipher만 허용하는 설정입니다.

LoadModule ibm_ssl_module modules/mod_ibm_ssl.so
Listen 443

# IP 기반 가상 호스트 활성화 (IHS 8.5 이하 필수)
NameVirtualHost *:443

<VirtualHost *:443>
    ServerName www.example.com
    DocumentRoot /app/EAR/SSL
    
    # SSL 엔진 활성화
    SSLEnable
    
    # 1. 취약 프로토콜 명시적 비활성화
    # (TLS 1.0, 1.1도 보안 정책에 따라 차단 고려)
    SSLProtocolDisable SSLv2
    SSLProtocolDisable SSLv3
    SSLProtocolDisable TLSv10
    SSLProtocolDisable TLSv11
    
    # 2. 안전한 프로토콜 활성화
    SSLProtocolEnable TLSv12
    
    # 3. Cipher Suite 화이트리스트 설정
    # 중요: 'ALL NONE'으로 기존 설정 초기화
    SSLCipherSpec ALL NONE
    
    # Forward Secrecy(PFS)를 지원하는 ECDHE 계열 우선 배치
    SSLCipherSpec ALL +TLS_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256 +TLS_ECDHE_ECDSA_WITH_AES_256_GCM_SHA384
    SSLCipherSpec ALL +TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256 +TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384
    
    # 호환성을 위한 RSA/AES 계열 추가
    SSLCipherSpec ALL +TLS_RSA_WITH_AES_256_CBC_SHA +TLS_RSA_WITH_AES_128_CBC_SHA
</VirtualHost>

KeyFile /SW/web/HTTPServer/key/key.kdb
SSLDisable

3. 설정 검증 (Verification)

설정 적용 후 IHS를 재기동하기 전, 명령어를 통해 적용된 Cipher 목록을 확인합니다.

적용된 Cipher 확인

cd [IHS_HOME]/bin
./apachectl -t -D DUMP_SSL_CONFIG

접속 테스트 (nmap)

외부에서 스캔하여 취약한 프로토콜(SSLv3 등)이 노출되지 않는지 교차 검증합니다.

nmap --script ssl-enum-ciphers -p 443 [Target_IP]

Next Step:
IHS 9.0 (Apache 2.4 기반)으로 업그레이드할 경우, SSLProtocol 지시어를 Apache 스타일로 사용할 수 있게 되지만, 기존 IHS 설정과의 호환성을 위해 IBM 문서를 반드시 참조하시기 바랍니다.

Open Stream →
#apache

[Apache/IHS] IP 접속 및 미등록 도메인 요청 차단 설정 (Default VirtualHost)

Apache(IHS) 웹 서버에서 도메인명이 아닌 IP 주소로 접속하거나, ServerName에 정의되지 않은 요청이 들어올 경우 이를 차단하거나 에러 페이지를 보여주는 방법을 정리합니다. 가장 먼저 로딩되는 Dummy VirtualHost를 활용하는 것이 핵심입니다.

0. 배경 지식 (Context)

Apache는 클라이언트 요청의 Host 헤더와 일치하는 ServerName(또는 ServerAlias)을 찾지 못할 경우, 설정 파일에서 가장 먼저 정의된 VirtualHost를 기본값(Default)으로 사용하여 요청을 처리합니다.

이 원리를 이용하여, 최상단에 아무런 ServerName을 갖지 않는(혹은 더미 값을 가진) VirtualHost를 배치하고 403 Forbidden 등을 반환하게 하면, 지정된 도메인 외의 모든 접근을 차단할 수 있습니다.

Test Environment

  • OS: CentOS 7.2
  • Web Server: IBM HTTPServer v8.5 (Apache 2.2 Base)

1. httpd.conf 설정 (VirtualHost 구성)

핵심은 순서입니다. 차단용(Dummy) 설정을 정상 서비스 설정보다 반드시 위쪽에 작성해야 합니다.

1) 기본 설정 및 포트 리슨

Listen 80
Listen 4958

# Apache 2.2 / IHS 8.5 이하 필수 (IP 기반 가상호스트 활성화)
NameVirtualHost *:80
NameVirtualHost *:4958

2) 차단용 Dummy VirtualHost (최상단 배치)

이 블록에는 ServerName을 지정하지 않거나 의미 없는 값을 넣습니다. 이곳으로 들어오는 요청은 모두 에러 메시지를 반환합니다.

# [80 포트] 미등록 도메인/IP 접속 차단
<VirtualHost *:80>
    DocumentRoot /app/was/htdocs
    
    # 접근 거부 메시지 설정 (보안상 상세 정보 숨김 권장)
    ErrorDocument 403 "Forbidden: Access is denied."
    ErrorDocument 404 "Not Found."
    ErrorDocument 500 "Internal Server Error."
    
    # 모든 요청에 대해 403 Forbidden 강제 반환 (mod_rewrite 사용 시)
    # RewriteEngine On
    # RewriteRule .* - [R=403,L]
    
    # 또는 디렉토리 접근 권한 제어
    <Directory "/app/was/htdocs">
        Order allow,deny
        Deny from all
    </Directory>
</VirtualHost>

# [4958 포트] 미등록 도메인/IP 접속 차단
<VirtualHost *:4958>
    DocumentRoot /app/was/htdocs
    ErrorDocument 403 "Forbidden: Access is denied."
    # ... (상동)
</VirtualHost>

3) 실제 서비스 VirtualHost

정상적인 도메인(ServerName)을 가진 요청만 처리하는 블록입니다. Proxy 설정을 포함합니다.

# Reverse Proxy 사용 시 Open Relay 방지
ProxyRequests Off

# [80 포트] 정상 서비스
<VirtualHost *:80>
    ServerName test.apache.com
    
    # WAS 또는 백엔드 서버로 프록시
    ProxyPass / http://172.31.98.155/ Keepalive=on
    ProxyPassReverse / http://172.31.98.155/
    
    # Host 헤더 유지 (WAS가 도메인을 인식하도록 함)
    ProxyPreserveHost On
    
    ErrorLog /app/was/HTTPServer/logs/test_proxy_error.log
    CustomLog /app/was/HTTPServer/logs/test_proxy_access.log combined
</VirtualHost>

# [4958 포트] 정상 서비스
<VirtualHost *:4958>
    ServerName test.httpserver.com
    
    ProxyPass / http://172.31.98.209/ Keepalive=on
    ProxyPassReverse / http://172.31.98.209/
    ProxyPreserveHost On
    
    ErrorLog /app/was/HTTPServer/logs/http_proxy_error.log
    CustomLog /app/was/HTTPServer/logs/http_proxy_access.log combined
</VirtualHost>
Tip: ProxyPreserveHost On 옵션은 클라이언트가 요청한 도메인 정보(Host Header)를 백엔드 서버(WAS)까지 그대로 전달합니다. WAS에서 가상 호스트를 구분해야 한다면 필수 옵션입니다.

2. 검증 (Verification)

설정 적용 후 웹 서버를 재기동하고 curl을 이용하여 테스트합니다.

1) 정상 도메인 접속 테스트

# 정상 응답(200 OK)이 와야 함
curl -v -H "Host: test.apache.com" http://localhost:80/

2) IP 접속 및 미등록 도메인 테스트

# 1. IP로 직접 요청 -> 403 또는 설정한 에러 메시지 출력되어야 함
curl -v http://localhost:80/

# 2. 엉뚱한 도메인 요청 -> 403 출력되어야 함
curl -v -H "Host: unknown.com" http://localhost:80/

Next Step:
Apache 2.4 (IHS 9.0 이상)를 사용 중이라면, NameVirtualHost 지시어는 더 이상 필요하지 않으므로 삭제하고, 접근 제어 구문을 Require all denied 등으로 변경해야 합니다.

Open Stream →
#command

[Linux] CentOS 7 호스트네임(Hostname) 영구 변경 및 필수 후속 조치 (hostnamectl)

CentOS 7 및 systemd 기반 리눅스 시스템에서 hostnamectl 명령어를 사용하여 호스트네임을 영구적으로 변경하는 방법을 정리합니다. 변경 후 쉘 프롬프트에 즉시 반영하는 방법과 /etc/hosts 파일 수정의 중요성을 포함합니다.

0. 배경 지식 (Context)

호스트네임은 네트워크 상에서 서버를 식별하는 이름입니다. 과거에는 /etc/sysconfig/network 파일을 수정하고 재부팅해야 했으나, CentOS 7부터는 hostnamectl 명령어를 통해 재부팅 없이 즉시 설정을 영구 반영할 수 있습니다.

Test Environment

  • OS: CentOS 7.2
  • System: systemd based

1. 호스트네임 변경 (hostnamectl)

hostnamectl 명령은 커널 호스트네임 설정과 /etc/hostname 파일 수정을 동시에 수행합니다.

현재 상태 확인

hostnamectl status

변경 명령어

# 구문: hostnamectl set-hostname [새로운_이름]
hostnamectl set-hostname web-server-01

2. 변경 사항 확인 및 적용 (Verification)

명령어 실행 즉시 시스템 설정은 변경되지만, 현재 로그인된 터미널의 프롬프트(Shell Prompt)에는 반영되지 않을 수 있습니다.

변경 확인

# 1. 설정값 확인
hostname

# 2. 상세 확인
hostnamectl status

터미널 프롬프트 갱신

로그아웃 후 다시 로그인(Reconnect)하면 프롬프트가 변경됩니다. 재접속 없이 바로 확인하려면 아래 명령어를 사용하세요.

# 현재 쉘 세션 갱신
exec bash

결과: [root@old-name ~]# 에서 [root@web-server-01 ~]# 로 변경됨.


3. 필수 후속 조치: /etc/hosts 수정

호스트네임을 변경했다면, 서버 자신이 자신의 이름을 찾아갈 수 있도록 로컬 DNS 설정 파일인 /etc/hosts도 반드시 수정해야 합니다. 이를 누락하면 sudo 명령어 실행이 느려지거나 일부 애플리케이션 기동 시 에러가 발생할 수 있습니다.

파일 수정

vi /etc/hosts

수정 내용

기존 호스트네임이 적힌 부분을 새로운 이름으로 변경하거나 추가합니다.

127.0.0.1   localhost localhost.localdomain localhost4 localhost4.localdomain4
::1         localhost localhost.localdomain localhost6 localhost6.localdomain6

# 변경된 호스트네임 추가 (자신의 IP 또는 Loopback에 매핑)
127.0.0.1   web-server-01
Tip: 클러스터링(Cluster) 환경이나 WAS(WebSphere, JBoss) 환경에서는 127.0.0.1 대신 실제 서버의 공인 IP(또는 사설 IP)에 호스트네임을 매핑하는 것이 좋습니다.
Open Stream →
#IBM HTTPServer

[IBM HTTPServer] SSL/TLS 암호화 슈트(Cipher Suite) 확인 및 점검 방법 (DUMP_SSL_CIPHERS)

IBM HTTP Server(IHS)에서 현재 적용된 SSL/TLS 프로토콜 버전과 지원하는 암호화 슈트(Cipher Suite) 목록을 확인하는 방법을 정리합니다. apachectl의 진단 옵션을 통해 서버에 설정된 보안 수준을 점검할 수 있습니다.

0. 배경 지식 (Context)

보안 취약점 점검 시 "SSLv3나 RC4 같은 약한 암호화 알고리즘을 비활성화하라"는 권고를 자주 받습니다. 조치를 취하기 전에, 현재 웹 서버가 어떤 알고리즘을 허용하고 있는지 정확히 파악하는 것이 우선입니다.

Test Environment

  • OS: CentOS 7.2
  • Web Server: IBM HTTPServer v8.5.0.0

1. Cipher Suite 확인 명령어

IHS는 apachectl 실행 스크립트에 -t(문법 검사) 옵션과 함께 -D DUMP_SSL_CIPHERS 정의를 추가하여, 현재 설정된 SSL 구성을 출력하는 기능을 제공합니다.

명령어 실행

cd [IHS_HOME]/bin

# SSL Cipher 설정 덤프
./apachectl -t -D DUMP_SSL_CIPHERS

결과 출력 예시 (Default 상태)

별도의 보안 설정(Hardening)이 되어 있지 않다면, 아래와 같이 IHS 버전의 기본값(Default)들이 출력됩니다.

SSL default cipher lists:
SSL protocol SSLV2, FIPS off, defaults = (None)
SSL protocol SSLV3, FIPS off, defaults = TLS_RSA_WITH_AES_128_CBC_SHA(2F), ...
SSL protocol TLSv10, FIPS off, defaults = TLS_RSA_WITH_AES_128_CBC_SHA(2F), ...
SSL protocol TLSv11, FIPS off, defaults = TLS_RSA_WITH_AES_128_CBC_SHA(2F), ...
SSL protocol TLSv12, FIPS off, defaults = TLS_RSA_WITH_AES_128_GCM_SHA256(9C), ...
Syntax OK
해석 주의 (Analysis):
위 출력 결과에 SSLV3 항목이 보인다면, 현재 서버는 보안에 취약한 SSLv3 프로토콜 통신을 허용하고 있다는 뜻입니다. 보안 강화를 위해 비활성화가 필요합니다.

2. 외부 도구를 이용한 교차 검증 (Verification)

서버 내부 설정뿐만 아니라, 외부에서 실제로 접속을 시도하여 어떤 Cipher가 노출되는지 확인하는 것이 가장 정확합니다.

1) nmap 사용 (Linux)

nmap의 스크립트 엔진을 사용하여 지원하는 Cipher 목록을 조회합니다.

nmap --script ssl-enum-ciphers -p 443 [서버IP]

2) OpenSSL 사용

특정 프로토콜로 접속이 되는지 테스트합니다.

# SSLv3 접속 시도 (접속 실패해야 안전함)
openssl s_client -connect [서버IP]:443 -ssl3

3. 보안 설정 강화 (Next Step)

취약한 프로토콜과 Cipher를 확인했다면, httpd.conf 파일에서 이를 차단해야 합니다.

설정 예시 (httpd.conf)

IHS에서는 SSLCipherSpec 지시어를 사용하여 특정 Cipher를 허용하거나 차단합니다.

<VirtualHost *:443>
    SSLEnable
    
    # 1. 취약한 프로토콜 비활성화 (TLS 1.2만 허용 권장)
    SSLProtocolDisable SSLv2 SSLv3 TLSv10 TLSv11
    SSLProtocolEnable TLSv12

    # 2. 강력한 Cipher Suite만 허용 (예시)
    # 128비트 미만 차단, RC4/MD5 차단
    SSLCipherSpec TLS_RSA_WITH_AES_128_CBC_SHA
    SSLCipherSpec TLS_RSA_WITH_AES_256_CBC_SHA
    # 필요에 따라 추가...
</VirtualHost>

4. 참고 자료 (References)

Open Stream →
#JBoss

[JBoss EAP 6] 커스텀 기동/정지 스크립트 작성 가이드 (Config 분리 및 JVM 튜닝)

JBoss EAP 6 Standalone 모드의 운영 효율성을 높이기 위해, JVM 옵션과 환경 변수를 별도의 설정 파일(Config Shell)로 분리하고 이를 로드하여 서버를 제어(Start/Stop/Status)하는 커스텀 쉘 스크립트 작성법을 공유합니다.

Test Environment

  • OS: CentOS 7.2
  • Middleware: JBoss EAP 6.4

1. 스크립트 구조 및 전략

유지보수성과 확장성을 위해 스크립트를 두 개의 파일로 분리합니다.

  1. Config Script (config1.sh): JVM 옵션, 경로, IP, 포트 등 변수 정의.
  2. Control Script (jboss_ctl.sh): Config를 로드하여 실제 프로세스를 제어하는 로직.

2. 설정 스크립트 (config1.sh)

서버 인스턴스별 고유한 설정을 이곳에 정의합니다. JAVA_OPTS를 통해 메모리 및 GC 로그 설정을 상세하게 튜닝할 수 있습니다.

#!/bin/sh
DATE=`date +%Y%m%d%H%M%S`

##### 1. Basic Configuration #####
export JBOSS_HOME=/SW/was/JBoss
export SERVER_HOME=/SW/was/JBoss/TEST/TESTServer11
export LOG_PATH=/app/logs/was
export NODE_NAME=TESTServer11
export CONFIG_FILE=standalone-ha.xml

# Network & Port Offset
export SERVER_IP=10.252.16.25
export PORT_OFFSET=750
export MGMT_ADDR=$SERVER_IP

# Controller Port Calculation (Base 9999 + Offset)
let CONTROLLER_PORT=9999+$PORT_OFFSET
export CONTROLLER_PORT

# Admin User (Shutdown용)
export USER=admin

##### 2. JVM Options (Memory & GC) #####
# Heap Memory
export JAVA_OPTS="-server -Xms1024m -Xmx2048m -XX:MaxPermSize=256m"

# GC Logging
export JAVA_OPTS=" $JAVA_OPTS -verbose:gc -XX:+PrintGCTimeStamps -XX:+PrintGCDetails "
export JAVA_OPTS=" $JAVA_OPTS -Xloggc:$LOG_PATH/log/gclog/gc_$DATE.log "

# GC Algorithm (ParallelGC)
export JAVA_OPTS=" $JAVA_OPTS -XX:+UseParallelGC -XX:+ExplicitGCInvokesConcurrent"

# Heap Dump on OOM
export JAVA_OPTS=" $JAVA_OPTS -XX:-HeapDumpOnOutOfMemoryError "
export JAVA_OPTS=" $JAVA_OPTS -XX:HeapDumpPath=$LOG_PATH/heap/$NODE_NAME "

##### 3. System Properties (-D options) #####
export JAVA_OPTS=" $JAVA_OPTS -Djava.net.preferIPv4Stack=true"
export JAVA_OPTS=" $JAVA_OPTS -Dorg.jboss.resolver.warning=true"
export JAVA_OPTS=" $JAVA_OPTS -Djava.awt.headless=true"
export JAVA_OPTS=" $JAVA_OPTS -DjvmRoute=$NODE_NAME"

# JBoss Path & Binding
export JAVA_OPTS=" $JAVA_OPTS -Djboss.server.base.dir=$SERVER_HOME"
export JAVA_OPTS=" $JAVA_OPTS -Djboss.server.log.dir=$LOG_PATH/$NODE_NAME"
export JAVA_OPTS=" $JAVA_OPTS -Djboss.socket.binding.port-offset=$PORT_OFFSET"
export JAVA_OPTS=" $JAVA_OPTS -Djboss.node.name=$NODE_NAME"
export JAVA_OPTS=" $JAVA_OPTS -Djboss.bind.address.management=$MGMT_ADDR"
export JAVA_OPTS=" $JAVA_OPTS -Djboss.bind.address=$SERVER_IP"

# Clustering (Multicast)
export JAVA_OPTS=" $JAVA_OPTS -Djboss.default.jgroups.stack=tcp"
# export JAVA_OPTS=" $JAVA_OPTS -Djboss.default.multicast.address=230.1.0.1"

echo "Configuration Loaded: $NODE_NAME"

3. 제어 스크립트 (jboss_ctl.sh)

실제 기동 및 정지를 담당하는 메인 스크립트입니다. ./config/config1.sh를 로드하여 변수들을 가져옵니다.

#!/bin/sh

# Config 파일 로드 (경로 주의)
. ./config/config1.sh

start(){
    # 프로세스 중복 실행 방지
    PID=`ps -ef | grep java | grep "jboss.node.name=$NODE_NAME " | awk '{print $2}'`
    
    if [ "x$PID" != "x" ]; then
        echo "###############################################"
        echo "ERROR: JBoss SERVER ($NODE_NAME) is already RUNNING (PID=$PID)"
        echo "###############################################"
        exit 1
    fi

    echo "#######################"
    echo "   Starting JBoss EAP  "
    echo "#######################"
    
    # nohup으로 백그라운드 실행, 로그 리다이렉션
    nohup $JBOSS_HOME/bin/standalone.sh --server-config=$CONFIG_FILE >> $LOG_PATH/console.log 2>&1 &

    echo "Starting... Wait for checking status..."
    sleep 5
    status
}

stop(){
    echo "#######################"
    echo "    Stopping JBoss     "
    echo "#######################"
    
    # 보안을 위해 패스워드는 입력받도록 처리 (자동화 시 변수로 대체 가능)
    echo -n "Enter Controller Password: "
    read -s PASSWORD
    echo ""

    # CLI를 이용한 안전한 종료 (Graceful Shutdown)
    $JBOSS_HOME/bin/jboss-cli.sh --connect --controller=$SERVER_IP:$CONTROLLER_PORT --command=:shutdown --user=$USER --password=$PASSWORD
}

status() {
    # 포트 리슨 상태로 구동 여부 확인
    _up=`netstat -an | grep $CONTROLLER_PORT | grep LISTEN | wc -l`
    
    if [ "$_up" -ne 0 ]; then
        PID=`ps -ef | grep java | grep "jboss.node.name=$NODE_NAME " | awk '{print $2}'`
        echo "###############################################"
        echo " JBoss Server is RUNNING !! "
        echo " Node: $NODE_NAME (PID: $PID)"
        echo " Port: $CONTROLLER_PORT (Management)"
        echo "###############################################"
    else
        echo "##################################"
        echo " JBoss Server is STOPPED !! "
        echo " Node: $NODE_NAME "
        echo "##################################"
    fi
}

# 파라미터 처리
case "$1" in
  start)
    start
    ;;
  stop)
    stop
    ;;
  status)
    status
    ;;
  restart)
    stop
    sleep 5
    start
    ;;
  *)
    echo "Usage: $0 {start|stop|status|restart}"
    exit 1
esac
exit 0

4. 사용 방법 및 주의사항

사용법

# 실행 권한 부여
chmod +x jboss_ctl.sh

# 기동
./jboss_ctl.sh start

# 상태 확인
./jboss_ctl.sh status

# 정지 (패스워드 입력 필요)
./jboss_ctl.sh stop
Tip: config1.sh 파일 내의 PORT_OFFSET 변수를 활용하면, 하나의 물리 서버에서 포트 충돌 없이 여러 개의 인스턴스를 띄울 수 있습니다. (예: 0, 100, 200...)
Open Stream →
#Linux

[Linux/Java] High CPU 트러블슈팅: OS 스레드와 Java 스레드 매핑 분석 가이드

Java 프로세스(JVM)가 고부하 상태일 때, CPU를 점유하고 있는 범인(특정 스레드)을 찾아내는 방법을 정리합니다. OS 명령어(ps, top)로 문제의 스레드 ID(TID)를 식별하고, 이를 16진수로 변환하여 Java Thread Dump와 매핑하는 과정을 다룹니다.

Test Environment

  • OS: RedHat Linux (CentOS 호환)
  • Target: Java Process (WebSphere/Tomcat 등)

1. 프로세스 및 스레드 식별 (Identify Usage)

먼저 CPU를 많이 사용하는 Java 프로세스의 PID(Process ID)를 찾고, 그 내부에서 실제로 리소스를 소모하는 스레드(LWP, Light Weight Process)를 식별해야 합니다.

전체 프로세스 확인

# Java 프로세스 PID 확인
ps -ef | grep java

스레드별 CPU 점유율 확인 (top)

-H 옵션을 사용하여 프로세스 내부의 스레드 단위로 리소스를 모니터링합니다.

# PID가 12345인 경우
top -H -p 12345

출력 화면에서 PID(실제로는 TID/LWP) 컬럼과 %CPU 컬럼을 확인하여 가장 상단에 있는 번호를 기록합니다.

스레드별 CPU 점유율 확인 (ps)

ps 명령어를 통해서도 스레드 정보를 확인할 수 있습니다. -lmT 옵션이나 -L 옵션을 사용합니다.

# LWP(Light Weight Process) 확인
ps -lmT [PID]

# 또는 커스텀 포맷 사용
ps -eLo pid,lwp,pcpu,comm | grep [PID]

2. 스레드 ID 변환 (Decimal to Hex)

OS에서 확인한 스레드 ID는 10진수(Decimal)이지만, Java Thread Dump 파일(Javacore 등)에서는 스레드 ID가 16진수(Hexadecimal)로 기록됩니다. 따라서 매핑을 위해 변환 과정이 필요합니다.

변환 예시

  • OS TID: 9091 (10진수)
  • Hex TID: 0x2383 (16진수)

변환 명령어

# 쉘에서 바로 변환하기 (예: 9091 -> 2383)
printf '%x\n' 9091

3. 스레드 덤프 생성 및 분석 (Thread Dump)

현재 JVM의 상태를 스냅샷으로 남기기 위해 스레드 덤프를 생성합니다.

덤프 생성 (Kill -3)

kill -3 시그널은 프로세스를 종료하지 않고 표준 출력(stdout)이나 로그 파일로 스레드 정보를 출력합니다.

kill -3 [PID]
  • IBM JDK (WebSphere): javacore.YYYYMMDD.HHMMSS.pid.txt 파일 생성
  • Oracle/Open JDK: catalina.out 또는 지정된 로그 파일에 출력

로그 매핑 분석

생성된 덤프 파일에서 앞서 변환한 16진수 값(예: 0x2383)을 검색합니다. IBM JDK의 경우 nid(Native ID) 또는 native_thread_id 항목과 매칭됩니다.

/* Javacore 예시 */
"WebContainer : 5" (TID:0x12345600, sys_thread_t:0x789abc00, state:R, native ID:0x2383) prio=5
    at com.example.MyClass.infiniteLoop(MyClass.java:45)
    at ...

분석 포인트:

  1. 16진수 ID로 검색하여 해당 스레드를 찾습니다.
  2. 해당 스레드의 상태(Runnable, Waiting 등)를 확인합니다.
  3. Stack Trace를 통해 현재 어떤 코드(메소드)가 실행 중인지 파악하여 병목 지점을 수정합니다.

Next Step:
주기적인 모니터링이 필요하다면 top -Hjstack을 결합한 쉘 스크립트를 작성하여, CPU 임계치 초과 시 자동으로 덤프를 남기도록 자동화해 보십시오.

Open Stream →
#JBoss

[JBoss EAP 6] CLI 기반 패치 적용(Apply) 및 롤백(Rollback) 완벽 가이드

JBoss EAP 6 환경에서 Management CLI(jboss-cli)를 사용하여 보안 패치나 버그 픽스를 적용(Apply)하고, 문제 발생 시 이전 상태로 되돌리는 롤백(Rollback) 절차를 정리합니다. 패치 이력 관리와 설정 초기화 옵션에 대한 이해가 필수적입니다.

0. 배경 지식 (Context)

JBoss EAP 6의 패치 시스템은 누적(Cumulative) 방식과 단일(One-off) 방식으로 나뉩니다. 패치를 적용하면 내부적으로 .installation 디렉토리에 변경 내역이 저장되며, 이를 통해 언제든 이전 시점으로 복원할 수 있습니다.

Test Environment

  • OS: Windows 10 (Linux 명령어 포함)
  • Middleware: JBoss EAP 6.4
  • Patch File: jboss-eap-6.4.19-patch.zip

1. 패치 적용 (Patch Apply)

패치 파일을 다운로드한 후, JBoss가 가동된 상태(또는 Embed 모드)에서 CLI를 통해 적용합니다.

명령어 구문

# 기본 구문
patch apply [패치파일_경로]

OS별 실행 예시

Linux

$JBOSS_HOME/bin/jboss-cli.sh --connect
[standalone@localhost:9999 /] patch apply /was/img/fix/jboss-eap-6.4.19-patch.zip

Windows

%JBOSS_HOME%\bin\jboss-cli.bat --connect
[standalone@localhost:9999 /] patch apply F:\app\was\jboss-eap-6.4.19-patch.zip
Note: 패치 적용 후에는 변경된 모듈을 로드하기 위해 반드시 서버를 재기동(Restart)해야 합니다.

2. 패치 이력 확인 (Verification)

패치가 정상적으로 적용되었는지, 혹은 롤백을 위해 돌아갈 시점(ID)을 확인해야 합니다.

CLI에서 확인

# 패치 정보 조회
[standalone@localhost:9999 /] patch history

# 상세 정보 조회
[standalone@localhost:9999 /] patch info

파일 시스템에서 확인

JBoss 설치 경로 내의 숨김 폴더를 통해서도 확인 가능합니다.

  • 경로: {JBoss_HOME}/.installation/patches

3. 패치 롤백 (Patch Rollback)

패치 적용 후 애플리케이션에 문제가 생겼다면 즉시 이전 상태로 되돌려야 합니다.

사전 준비: Patch ID 확인

롤백할 대상 ID를 알아야 합니다. patch history 명령어로 가장 최근에 적용된 패치 ID를 확인하십시오.

롤백 명령어

# 구문
patch rollback --patch-id=[PATCH_ID] --reset-configuration=[TRUE|FALSE]

핵심 옵션 설명 (--reset-configuration)

  • TRUE (권장): 패치 적용 시 변경되었던 설정 파일(standalone.xml 등)도 패치 이전 상태로 되돌립니다.
  • FALSE: 설정 파일은 현 상태를 유지하고 모듈(Jar)만 롤백합니다. 설정 충돌로 인해 서버 기동이 실패할 수 있으므로 주의해야 합니다.

실행 예시

# 설정까지 완벽하게 이전으로 복구
[standalone@localhost:9999 /] patch rollback --patch-id=CP19 --reset-configuration=true

4. 관리 콘솔(GUI)을 이용한 방법

CLI 사용이 어렵다면 웹 관리 콘솔에서도 동일한 작업을 수행할 수 있습니다.

  1. 접속: http://localhost:9990/console
  2. 메뉴: 상단 Patching 탭 선택
  3. 작업: 패치 마법사를 통해 파일 업로드 및 적용 (롤백 기능 포함)
JBoss Management Console Patching Screen

[그림] JBoss 관리 콘솔의 패치 관리 화면


Next Step:
패치 작업 전에는 만약을 대비해 standalone 또는 domain 디렉토리 전체를 압축하여 별도로 백업해두는 것을 강력히 권장합니다.

Open Stream →
#WebSphere

[WebSphere] 디렉토리 리스팅(Directory Listing) 제거 및 보안 설정 (directoryBrowsingEnabled)

웹 서버가 특정 디렉토리 내의 파일 목록을 브라우저에 노출하는 '디렉토리 리스팅' 취약점을 해결하기 위한 WebSphere 설정 가이드입니다. 애플리케이션 레벨(xml) 수정 방식과 관리 콘솔(Admin Console)을 통한 전역 설정 방식을 다룹니다.

0. 배경 및 원인 (Context)

디렉토리 리스팅이 활성화되어 있으면 공격자가 서버의 디렉토리 구조와 파일 목록(백업 파일, 소스 코드 등)을 파악할 수 있어 2차 공격의 빌미가 됩니다.

WebSphere는 정적 파일 처리를 위한 fileServingEnabled 속성과 목록 노출을 위한 directoryBrowsingEnabled 속성을 가지고 있으며, 이를 적절히 제어해야 합니다.

Test Environment

  • OS: CentOS 7.2
  • Web Server: IBM HTTPServer v8.5.0.0
  • WAS: WebSphere Application Server v8.5

1. Method A: 애플리케이션 설정 파일 수정

개별 애플리케이션 단위로 설정을 적용할 때 사용합니다. WAR/EAR 파일 내부의 IBM 확장 설정 파일을 직접 수정합니다.

설정 파일 대상

  • WAS v7.0 이상: ibm-web-ext.xml
  • WAS v6.1 이하: ibm-web-ext.xmi (Legacy)

설정 내용 (ibm-web-ext.xml)

enable-directory-browsing 속성을 false로 명시합니다.

<?xml version="1.0" encoding="UTF-8"?>
<web-ext
    xmlns="http://websphere.ibm.com/xml/ns/javaee/web-ext/1.0"
    xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
    xsi:schemaLocation="http://websphere.ibm.com/xml/ns/javaee/web-ext/1.0 http://websphere.ibm.com/xml/ns/javaee/web-ext/1.0/web-ext.xsd">

    <!-- 정적 파일 서빙 활성화 (이미지, HTML 등) -->
    <enable-file-serving value="true"/>
    
    <!-- 핵심: 디렉토리 리스팅 비활성화 -->
    <enable-directory-browsing value="false"/>

</web-ext>

2. Method B: 웹 컨테이너(Web Container) 전역 설정

WAS 관리 콘솔에서 서버 단위로 속성을 추가하여 제어하는 방식입니다. 애플리케이션을 재배포하지 않고 설정을 변경할 수 있어 운영 환경에서 선호됩니다.

설정 경로

서버(Servers) > 서버 유형(Server Types) > WebSphere application servers > [서버명] > 웹 컨테이너 설정(Web Container Settings) > 웹 컨테이너(Web container) > 사용자 정의 특성(Custom properties)

주요 속성 값

아래 속성을 새로 작성(New)하여 추가합니다.

이름 (Name) 값 (Value) 설명
directoryBrowsingEnabled false 디렉토리 목록 조회 기능을 비활성화합니다. (보안 필수)
fileServingEnabled true WAS가 정적 파일(html, img 등)을 처리할지 여부입니다. (false 설정 시 정적 파일 처리가 불가할 수 있음)
참고: fileServingEnabledfalse로 설정하면 디렉토리 리스팅도 차단되지만, WAS가 이미지나 CSS 같은 정적 리소스를 전혀 제공하지 않게 되므로 주의가 필요합니다. 일반적으로는 directoryBrowsingEnabledfalse로 설정합니다.

3. 검증 (Verification)

  1. 설정 적용 후 WAS 인스턴스를 재기동합니다.
  2. 브라우저에서 index.html이 없는 디렉토리 경로(예: http://domain/images/)로 접속합니다.
  3. 403 Forbidden 에러가 발생하면 보안 설정이 정상적으로 적용된 것입니다.
Open Stream →