출처 : NETWORK TIMES 

NDMP 프로토콜로 백업 용이
NAS G/W 활용한 랜 프리 백업 유용
D2D 백업 원격지 복제 등 NAS 기반 데이터 보호 방안 시선집중


오늘날 대부분의 전산 업무는 온라인 중심으로 변화됐으며, 24×365 시스템의 구축을 요구하고 있다. 또 하나는 이와 같이 만들어진 전산 환경에 대해 여러 가지 자연, 인위적인 재해로부터 보호받기 위해 미러링 솔루션으로 원격지 복제 시스템을 운용한다. 이것은 과거와 달리 시설투자에 2배 이상의 비용이 들어가는 것을 의미하고, 관리도 그만큼 복잡해지는 것을 뜻한다. 이처럼 점점 복잡해지는 IT 환경을 어떻게 하면 쉽게 관리할 수 있을까 하는 것이 풀어야할 숙제다. 이 글에서는 NAS를 통한 DR 구성에 대해 살펴보자.
이용상 한국IBM 스토리지 사업본부 부장·yongsang@kr.ibm.com


요즘은 홈쇼핑에서도 NAS(Network Attached Storage)를 팔고 있다. 기업용이 아닌 개인용 네트워크 스토리지가 그것이다. 150GB, 300GB 등 개인이 사용하는 용량치고는 제법 크다. 과거 몇 년 전에는 소규모 기업이나 그룹에서 사용하는 만큼의 용량을 개인용으로 사용하고 있는 것이다. IT 기술의 발전으로 고성능, 고용량의 스토리지를 훨씬 저렴한 가격으로 구입이 가능한 세상이 됐다.
90년대에 NC(Network Computing)가 등장하면서 네트워크 스토리지가 각광을 받을 것으로 예상했지만 바로 유행을 타지는 못했다. 그러다가 90년 후반에 접어들면서 NAS가 등장하게 됐는데. NAS는 용어 자체에서 느낄 수 있는 것처럼 네크워크 상에 스토리지를 접속해서 여러 사용자가 데이터를 고속으로 공유할 수 있게 하는 네트워크를 이용한 저장방식이다. 스토리지를 서버에 직접 붙여 운영하는 DAS(Direct Attached Storage)보다 한 단계 진보된 스토리지라고 보면 맞을 것 같다.


NAS의 등장 배경
현시점에서 NAS를 언급하는 것은 약간 지나간 얘기를 하는 것 같지만 오늘날 IT 환경이 SAN(Storage Area Network)을 통한 서버와 스토리지의 통합을 하고 있는 것이 한참인 시점에서 놓고 보았을 때, 그 중간 과정쯤 된다고 보면 될 것 같다.
NAS가 나오게된 배경을 살펴보면 지금 인터넷망의 근간인 TCP/IP(Transmission Control Protocol/Internet Protocol)의 발전에 따른 산출물 중 하나라고 볼 수 있다. TCP/IP는 美 국방성의 전산망인(ARPAT)에서 개발된 프로토콜 중의 하나다. 1983년 ARPAT를 TCP/IP로 대체했고, 현재의 오픈 운영 체계인 유닉스에서 TCP/IP를 기본으로 채택하게 됨에 따라 급속도로 발전하고 보급됐다.
통신 기술의 발전으로 최근에는 기가비트가 지원되는 NAS 제품들이 출시돼 파이버 채널(100MB)을 이용하는 SAN과 시장에서 경합을 벌이고 있다. 그러나 TCP/IP를 프로토콜로 사용하는 이더넷 상에서의 데이터 이동은 트래픽이 몰릴 경우 병목현상(Bottleneck) 등의 문제가 있어, SAN과의 경합에서 불리한 위치에 있다고 볼 수 있다. 실제로 고객은 해당 기업의 규모, 투자 비용 등을 고려해 IT 환경을 NAS와 SAN으로 이원화시켜 가져가는 경우가 많다.



DAS-NAS-SAN
과거에는 개인용 PC건 기업용 대형 호스트건 스토리지를 직접 서버에 붙여 운영하는 것이 대부분이었다. 이와 같이 스토리지와 서버간에 SCSI(Small Computer System Interface: 주변기기를 붙이기 위한 직렬 표준 인터페이스) , FC(Fiber Channel: 광전송 방식), ESCON(Enterprise System CONnection: IBM의 메인프레임용 인터페이스) 등의 매개체를 통해 붙여 사용한 것이 DAS 방식이다.
그러나 DAS 방식은 스토리지가 붙어있는 해당 서버에서만 붙어 있는 스토리지를 사용할 수 있는 제약점이 있었다. 그러다가 이더넷의 발달로 TCP/IP 네트워크상에 고속의 I/O 처리가 가능한 NAS를 붙여 사용할 수 있게 됐다. NAS는 이더넷 상에 손쉽게 붙일 수 있다는 것이 장점이고, 단점으로는 파일 단위로 I/O를 하므로 블록 단위로 I/O를 하는 SAN에 비해서는 성능이 떨어질 수밖에 없다. 그리고 이더넷 상에 많은 클라이언트와 서버가 물려 있을 경우 동일한 네트워크를 이용해 데이터가 왔다갔다해야 하므로 I/O 트래픽이 심한 경우 네트워크의 병목현상이 발생해 성능의 저하를 가져올 수 있다.
이것을 해소하기 위해 기가비트가 지원되는 NAS 제품들이 나와있기는 하지만 근본적인 치유책이 될 수는 없다. 이러한 문제들을 보완하기 위한 솔루션인 SAN은 고속의 스위치를 이용 서버, 스토리지간에 FC를 이용한 고속 통신을 보장함으로서 이더넷을 데이터 통신의 경로로 사용하고 있는 NAS와는 달리 병목 현상이 생기는 것을 방지할 수 있다. 또 한편 스토리지 풀(Pool) 구성이 가능해 서버 사이에 SAN 네트워크에 연결돼 있는 모든 스토리지를 공유해 사용할 수 있다는 장점이 있다. 요즈음에는 이러한 SAN을 통해 스토리지를 통합해 복잡한 IT환경을 단편화해 나가는 것이 추세다.

iSCSI
iSCSI(internet Small Computer Systems Interface)는 스토리지와 IP 네트워크를 통합하기 위한 프로토콜이라고 이해하면 쉽다. 즉 IP 네트워크상에서 SCSI 커맨드 상태로 블록 단위로 I/O를 일으키기 때문에, 마치 DAS와 같은 형태로 스토리지를 네트워크에 붙여서 사용하는 것이라고 볼 수 있다. iSCSI는 전송 매체가 SCSI 형태로 날아다니므로 컨버전(conversion) 작업이 따로 필요하지 않아 NAS 방식의 스토리지에 비해 속도가 빠르다. 그리고 SAN과의 인터페이스가 가능해 IP와 SAN간의 통신을 할 수 있는 환경을 제공함으로서 운용의 폭을 넓힐 수 있는 장점이 있다.

NAS vs. NAS 게이트웨이
NAS와 NAS 게이트웨이간의 차이는 <그림 1>에서와 같이 NAS에 들어있는 스토리지와 컨트롤러 대신에 SAN과의 인터페이스를 제공한다는 것이다. 그러므로 이더넷에 붙여서 NAS로서의 서비스를 클라이언트 쪽에 해주면서도 실제 스토리지는 SAN을 통해 공급받은 스토리지 풀(Pool)에서 제공받을 수 있는 이점이 있다.
그리고 확장성 면에서도 NAS는 스토리지 공간이 필요할 때마다 NAS를 계속 붙여서 확장을 해야 하지만, NAS 게이트웨이에서는 SAN 스토리지 풀에서 필요할 때마다 언제든지 스토리지 공간을 공급받을 수 있다. 최근 추세는 점차 NAS에서 NAS 게이트웨이로 바뀌어 가고 있으며, 이를 통해 IP와 SAN간에 통합을 시도한다.
<그림 2>는 NAS 어플라이언스의 구성도로, NAS 스토리지 공간을 확장하기 위해서는 NAS를 계속 늘려가야 하는 구조다. 반면 <그림 3>은 NAS 게이트웨이 구성도로, SAN 스토리지 풀을 바라볼 수 있어 스토리지의 증설이 필요할 때 NAS 자체의 스토리지를 확장하는 것이 아니라, SAN 스토리지 풀에 디스크들을 추가한 후 NAS 게이트웨이에 할당해 주면 된다. 따라서 스토리지 확장성이 좋고 IP와 SAN간에 통신을 해 줌으로서 IP와 SAN의 통합을 이뤄낼 수 있다.


NAS를 통한 DR 방안
지금까지는 NAS의 기본 개념과 다른 솔루션과의 차이점 등을 알아봤다. 그럼 이제부터 본격적으로 NAS를 통한 DR(Disaster Recovery) 솔루션에 대해 살펴보자. 오늘날 대부분의 전산 업무는 온라인 중심으로 변화됐으며, 24×365 시스템의 구축을 요구하고 있다.
또 하나는 이와 같이 만들어진 전산 환경에 대해 여러 가지 자연, 인위적인 재해로부터 보호받기 위해 미러링(Mi-rroring) 솔루션으로 원격지 복제 시스템을 운용한다. 이것은 과거와는 달리 시설투자에 2배 이상의 비용이 들어가는 것을 의미하고, 관리도 그만큼 복잡해지는 것을 뜻한다. 이처럼 점점 복잡해지는 IT 환경을 어떻게 하면 쉽게 관리할 수 있을까 하는 것이 풀어야할 숙제다.

NDMP 백업의 한계와 대안
NDMP(Network Data Management Protocol)는 많은 NAS 벤더들이 백업/복구를 위해 만든 프로토콜이다. 대부분의 NAS 어플라이언스 속에 들어 있는 운영체계가 백업/복구 등의 기능을 포함하고 있지 않기 때문이다. 이러한 스토리지 관리 기능을 추가로 기능 부여한 것이 NDMP이다.
네트워크어플라이언스나 EMC는 이러한 기능을 이용해 백업을 받고 있다. 그러나 IBM의 경우 NAS 제품 자체가 파워 칩(Power Chip)을 장착한 AIX 5L운영 체제를 사용하고, 그 자체에 백업/복구 등의 기능을 가진 TSM(IBM Tivoli Sotrage Manager)의 에이전트 모듈을 포함하고 있어 굳이 NDMP가 필요하지 않다.
TSM 에이전트는 TSM을 사용하고 있는 기존의 랜 또는 SAN 네트워크에서 쉽게 사용될 수 있고, 베리타스 또는 레가토와 같은 벤더에서 AIX 5L에서 가동되는 소프트웨어 클라이언트나 에이전트가 있다면 이것을 바로 IBM의 NAS에서 돌릴 수 있는 장점이 있다.
그래서 호환성과 이식성을 따져 봤을 때는 NDMP보다는 AIX 5L과 같은 오픈 운영 체제를 갖고 있는 NAS 제품이 사용자에게 유연성(Flexibility)을 더 쉽게 보장해 준다고 볼 수 있다.

NAS 게이트웨이와 랜 프리 백업
NAS 게이트웨이가 갖고 있는 기능 중 하나가 랜 프리 백업(LAN Free Backup)이다. 기존의 DAS 방식에서 데이터 백업을 받기 위해서는 DAS 스토리지로부터 서버를 거쳐 이더넷을 통해 데이터가 저장소로 가야 한다. 이는 이더넷 상에 병목현상이 심하게 걸릴 수 있는데, 이러한 문제점을 보완하기 위해 나온 방식이 바로 랜 프리 백업이다. 랜 프리 백업의 이점은 다음과 같다.

1. 스토리지 자원 사용률을 향상시킬 수 있다.
2. 랜 트래픽을 줄일 수 있다.
3. 백업 윈도를 보다 자유롭게 운영할 수 있다.
4. 스케쥴링과 정책에 의한 관리를 할 수 있다.
5. 저성능의 랜 네트워크 환경에서는 더 좋은 백업 성능의 진가를 발휘할 수 있다.

이제 NAS 게이트웨이를 이용한 랜 프리 백업의 구조를 살펴보자. <그림 4>에서 동작원리를 살펴보면(TSM을 사용한 경우임),

1. TSM 클라이언트(NAS 게이트웨이)는 TSM 서버에게 백업을 하겠다고 통보한다.
2. TSM 클라이언트는 디스크로부터 데이터를 요구한다.
3. TSM 클라이언트는 백업할 데이터를 가져온다.
4. TSM 클라이언트는 가져온 데이터를 바로 테이프 장치로 보낸다.
5. TSM 클라이언트는 메타 데이터(데이터 변경에 대한 정보가 들어있는)를 TSM 서버에게 알려 준다.

이와 같은 과정을 거쳐 SAN 스토리지 풀에 들어있는 저장소로 랜 프리 백업이 이뤄진다. 여기에서 알 수 있는 사실은 데이터의 흐름이 랜을 거치지 않고 SAN 네트워크 상에서 이동해 디스크에서 테이프로 바로 이동한다는 것이다.


NAS 게이트웨이를 통한 스토리지간 IP 미러링 솔루션
NAS 게이트웨이와 SVC(IBM SAN Volume Controller)를 같이 사용하면, 이기종 스토리지간에도 NAS 게이트웨이의 볼륨을 사용할 수 있다. 오늘날의 IT 환경은 특정 벤더의 제품에 묶이는 것을 꺼려한다. 그러다 보니 여러 벤더의 스토리지가 SAN에 묶여 운용되는 것이 현실이다.
그러나 이런 경우 여러 벤더의 스토리지가 묶이다 보니 운영상의 복잡함이나 통합에 있어 어려움이 있다. NAS 게이트웨이를 통한 스토리지간 IP 미러링 구성은 이와 같은 복잡한 환경을 쉽게 만들 수 있는 장점이 있다. 그리고 NAS에서 제공되는 미러링 솔루션으로, 추가 비용 없이 이기종 스토리지간의 데이터 보관이 가능한 것이 특징이다.

NAS 게이트웨이를 이용한 미러링 오버 IP
NAS를 통한 원격지 복제는 대부분의 스토리지 벤더가 엔터프라이즈급에서 구현하고 있는 솔루션과 유사하다고 보면 된다. IBM의 PPRC, EMC의 SRDF, HDS의 트루카피 등이 그러한 솔루션이다. 이러한 DR 솔루션은 대략 동기(SYNC)와 비동기(ASYNC) 방식으로 나뉘는데, 그 차이는 다음과 같다. 참고로 이때 이뤄지는 원격 미러링 모드는 공통적으로 크게 2가지로 구별되며, 나머지는 벤더마다 약간씩의 차이가 있다. 이것을 정리하면 다음과 같다.

1. 동기 방식
로컬 사이트에 데이터를 저장한 후 애플리케이션에게는 데이터가 저장됐음을 알린다. 동시에 데이터는 원격 사이트에 저장하려고 하는데, 이때 약간의 지연 시간이 발생한다. 애플리케이션 입장에서는 데이터가 저장된 것처럼 보이지만, 실제로 원격 사이트에서는 데이터 저장이 완전히 끝나지 않을 수 있다. 이러한 이유로 데이터의 손실이 생길 수 있다.
2. 비동기 방식
원격 사이트에 데이터를 먼저 저장한 후, 로컬 사이트에 데이터를 저장한다. 그 다음 애플리케이션에게 해당 데이터가 기록(Write)됐음을 알린다. 이러한 방식은 데이터의 손실은 없지만, 얼마나 빨리 원격 사이트에 데이터를 저장하느냐가, 온라인 중에 있는 로컬 사이트의 업무 시간 지연을 최소화시킬 수 있는지와 관련 있는 요소 중 하나다.

3. MWC(Mirror Write Consistency) 방식
로컬 사이트에 데이터 저장과 동시에 원격 사이트에 데이터를 저장한다. 이때 원격 사이트에서 데이터 저장의 신호가 오기 전까지는 로컬 쪽에서 기록을 끝낸 것으로 보지 않는다. 동기 방식보다는 속도가 빠르고 비동기 방식보다는 유연하게 데이터를 관리할 수 있다.
NAS 게이트웨이는 IP 통신을 통해 로컬 사이트의 데이터를 원격 사이트의 저장공간으로 원격지 복제를 실시하게 된다. 그러나 NAS 게이트웨이를 통한 원격 미러링인 경우 IP 랜망을 통해 데이터 이동이 일어나므로 병목이 발생할 수 있는 가능성과 고속의 랜 네트워크 구성이 필수적이다.

맺음말
지금까지 NAS의 기본적인 개념에서부터 유사 솔루션, 그리고 DR까지 살펴봤다. NAS를 단순 네트워크에 붙어있는 스토리지로만 생각해서는 안된다. NAS 게이트웨이를 통해 랜과 SAN의 통합에 유용한 솔루션임을 인지해야 한다.
오늘날 대부분의 기업은 SAN으로 통합하고 있으며, 이는 여러 면에서 IP를 통한 스토리지 풀을 갖는 것보다는 이점이 있다. 그러나 IP에 비해 아직 벤더별 표준화가 덜 돼 있는 상태이며 SAN을 구축하기 위한 인프라 구축 비용이 만만치 않게 든다.
반면 IP 스토리지 네트워킹 기술은 현재 구축돼 있는 랜망을 그대로 사용할 수 있기 때문에 인프라 구축 비용이 적게 들며, IP에 대해서는 대부분이 표준화 돼 있어 이식성이 좋다. 그러한 이유 때문에 고가용 고성능의 엔터프라이즈급 시장에서는 SAN을 선호하고 있고, 미드레인지급의 시장에서는 적은 비용으로 동일한 효과를 낼 수 있는 IP 스토리지 네트워킹 방식을 채택하기도 한다.
그러나 현재 시점에서 재난복구(DR)에 대한 수요는 어느 정도 공급이 됐다고 보여진다. 몇 년 전부터 정부에서 금융권을 중심으로 재해 복구 솔루션에 대해 구축 의무를 뒀기 때문에 이미 많은 고객들은 그러한 솔루션을 갖추고 있는 상태다. 따라서 이러한 DR 시장이 갑자기 늘어나기를 기대하기는 어렵다.


블로그 이미지

유효하지않음

,

RAID 1-6 레벨 이해하기

H/W 2009. 1. 20. 13:26
[출처] 다음,네이버 검색사이트

1부터 6까지의 RAID 레벨의 장단점을 알아보고, 스토리지를 구성할 때 목적에 맞는 최적의 레벨을 찾아보자.

데이터는 많은 조직에서 가장 중요하고 요즘 같은 인터넷 시대에는 데이터를 빠르고 믿을 수 있게 접근하는 것이 매우 중요하다. 그렇게 조직은 대부분 데이터를 무결하게 유지하기 위해 RAID의 어떤 레벨을 사용한다.

요즘은 대부분 그렇지만 RAID 5가 쉽고 최선일 것 같기 때문에 얼마나 많은 서버에 RAID 5를 적용하고 있을까? 대부분의 경우 RAID 5가 옳은 선택이지만 쓰기 성능을 고려한다면 다른 RAID 레벨이 최선일지도 모른다.

지금 얼마나 많은 사람들이 RAID 10과 50를 즉석해서 설명할 수 있을까? 새로 발명된 RAID 레벨이 RAID 5의 단점을 보완할 수 있고 아직도 스토리지 시스템에서는 많은 것을 예비용으로 사용한다. 이 글에서 기본적인 RAID 레벨의 장단점을 소개하고 다음 글에서 나는 RAID 10같이 네스티드(nested)라고 불리는 좀 더 복잡한 RAID 레벨을 소개하려고 한다. (주: http://www.acnc.com/04_00.html에서 각 RAID 레벨의 그림을 볼 수 있다.)

RAID 0(디스크 스트라이핑)
* 최소 드라이브 개수 : 2
* 최대 용량 : 디스크의 수 x 디스크의 용량
* 설명 : 데이터를 블럭으로 쪼개서 저장하는데 각 블럭은 다른 디스크로 나뉘어 저장된다.

* 장점 : 매우 빠르다. 데이터는 여러 개의 "모터(spindles)"로 스토리지에서 읽고 쓴다. 즉, I/O 로드가 분산되는 것을 의미하기 때문에 매우 빠르다. 이론적으로 디스크를 추가하는 족족 성능은 향상된다. 보통 엄청난 성능이 필요할 때 사용하는데 성능이 정말 좋은지 알아 보기 위해 스토리지를 아이오미터(IOmeter)같은 도구를 사용하여 확인한다.
* 단점 : 드라이브 하나가 고장 나면 이 RAID 레벨은 어떤 안전장치도 없기 때문에 천체 어레이가 고장 날 수 있고 디스크를 추가할 수록 위험이 증가한다.(주: 어레이는 여러 개의 디스크 배열을 의미)


RAID 1 (디스크 미러링)
* 최소 드라이브 개수 : 2
* 최대 용량 : (디스크의 수/2) x 디스크의 용량
* 설명 : 스토리지에 저장되는 모든 데이터는 두 개의 물리적인 디스크에 각각 저장되고 모든 데이터는 중복된다.

* 장점 : 드라이브 하나가 고장 나면 똑같은 내용의 다른 드라이브가 하나 더 있기 때문에 매우 안전하다. RAID 1은 읽기 성능이 단일 드라이브에서의 성능과 같거나 훨씬 좋다.
* 단점 : 각 드라이브는 미러링되기 때문에 전체 용량의 절반밖에 사용하지 못한다. 드라이브 두 개에 동일한 데이터를 써야 하기 때문에 쓰기 성능이 나빠질 수 있지만 아직 다른 RAID 레벨의 쓰기 성능보다는 훨씬 낫다.


RAID 2: 이 레벨은 더 이상 사용되지 않는다

RAID 3(패리티를 사용하고 디스크를 병렬로 처리한다)
* 최소 드라이브 개수 : 3
* 최대 용량 : (디스크의 수 - 1) x 각 디스크의 용량
* 설명 : 데이터는 바이트 단위로 쪼개져서 모든 디스크에 균등하게 나뉘어 저장되고 패리티 정보는 별도의 전용 디스크에 저장된다.

* 장점 : 한 개의 드라이브가 고장 나는 것을 허용하며 순차적 쓰기(sequential write) 성능과 순차적 읽기(sequential read) 성능이 우수하다.
* 단점 : 잘 사용되지 않고 문제를 해결하는 것이 어려울 수 있다. 하드웨어 RAID가 되어야 실제로 쓸만하다. RAID 3은 보통 매우 효율적이지만 임의 쓰기(random write) 성능이 나쁘고 임의 읽기(random read) 성능은 꽤 좋다. .


RAID 4 (각 디스크는 패리티 블럭을 공유한다)
* 최소 드라이브 개수 : 3
* 최대 용량 : (디스크의 수 - 1) x 디스크의 용량
* 설명 : 모든 파일은 블럭으로 쪼개지고 각 블럭은 여러 디스크에 저장되지만 균등하진 않다. RAID 3처럼 RAID 4도 패리티를 처리하기 위해 별도의 디스크를 사용한다. 동시 트랜잭션 사용량이 많은 시스템에서 읽기 속도는 매우 중요한데 이런 시스템에 적합하다.
* 장점 : 드라이브 하나가 고장 나는 것을 허용하고 읽기 성능이 매우 좋다.
* 단점 : 쓰기 성능이 나쁘지만 블럭 읽기(block read) 성능은 괜찮다.


RAID 5(패리티를 순환시키는 것 없이 각 어레이에 접근한다)
* 최소 드라이브 개수 : 3
* 최대 용량 : (디스크의 수 - 1) x 디스크의 용량
* 설명 : RAID 4처럼 데이터의 블럭은 모든 디스크에 나뉘어 저장되지만 항상 균등하진 않고 패리티 정보도 모든 디스크에 나뉘어 저장된다.
* 장점 : 지원하는 회사가 많고 한 개의 드라이브가 고장 나는 것을 허용한다.
* 단점 : 디스크 재구성(rebuild)이 매우 느리고 쓰기 성능은 패리티 정보를 끊임없이 갱신해야 하기 때문에 우수하다고 할 수는 없다.


RAID 6(각 디스크에 패리티 정보가 두 번 독립적으로 분산된다)
* 최소 드라이브 개수 : 3
* 최대 용량 : (디스크의 수 - 2) x 디스크의 용량
* 설명 : RAID 4처럼 데이터의 블럭은 모든 디스크에 나뉘어 저장되지만 항상 균등하진 않고 패리티 정보도 모든 디스크에 나뉘어 저장된다.

* 장점 : 두 개의 드라이브까지 고장 나는 것을 허용하고 읽기 성능이 우수하고 매우 중요한 경우에 적합하다.
* 단점 : 쓰기 성능은 패리티를 여러 번 갱신해야 하기 때문에 RAID 5보다 매우 나쁘다. 디스크를 재구성하는 동안에 성능이 매우 나빠질 수 있다



[출처] http://blog.naver.com/mybrainz/150003200069


RAID 1-6 레벨 이해하기

1부터 6까지의 RAID 레벨의 장단점을 알아보고, 스토리지를 구성할 때 목적에 맞는 최적의 레벨을 찾아보자.

데이터는 많은 조직에서 가장 중요하고 요즘 같은 인터넷 시대에는 데이터를 빠르고 믿을 수 있게 접근하는 것이 매우 중요하다. 그렇게 조직은 대부분 데이터를 무결하게 유지하기 위해 RAID의 어떤 레벨을 사용한다.

요즘은 대부분 그렇지만 RAID 5가 쉽고 최선일 것 같기 때문에 얼마나 많은 서버에 RAID 5를 적용하고 있을까? 대부분의 경우 RAID 5가 옳은 선택이지만 쓰기 성능을 고려한다면 다른 RAID 레벨이 최선일지도 모른다.

지금 얼마나 많은 사람들이 RAID 10과 50를 즉석해서 설명할 수 있을까?

 
새로 발명된 RAID 레벨이 RAID 5의 단점을 보완할 수 있고 아직도 스토리지 시스템에서는 많은 것을 예비용으로 사용한다.
 
이 글에서 기본적인 RAID 레벨의 장단점을 소개하고 다음 글에서 나는 RAID 10같이 네스티드(nested)라고 불리는 좀 더 복잡한 RAID 레벨을 소개하려고 한다.
(주: http://www.acnc.com/04_00.html에서 각 RAID 레벨의 그림을 볼 수 있다.)

 

RAID 0(디스크 스트라이핑)

 
* 최소 드라이브 개수 : 2
 
* 최대 용량 : 디스크의 수 x 디스크의 용량
 
* 설명 : 데이터를 블럭으로 쪼개서 저장하는데 각 블럭은 다른 디스크로 나뉘어 저장된다.

* 장점 : 매우 빠르다. 데이터는 여러 개의 "모터(spindles)"로 스토리지에서 읽고 쓴다. 즉, I/O 로드가 분산되는 것을 의미하기 때문에 매우 빠르다. 이론적으로 디스크를 추가하는 족족 성능은 향상된다. 보통 엄청난 성능이 필요할 때 사용하는데 성능이 정말 좋은지 알아 보기 위해 스토리지를 아이오미터(IOmeter)같은 도구를 사용하여 확인한다.
 
* 단점 : 드라이브 하나가 고장 나면 이 RAID 레벨은 어떤 안전장치도 없기 때문에 천체 어레이가 고장 날 수 있고 디스크를 추가할 수록 위험이 증가한다.(주: 어레이는 여러 개의 디스크 배열을 의미)

 

 

RAID 1 (디스크 미러링)

* 최소 드라이브 개수 : 2

 
* 최대 용량 : (디스크의 수/2) x 디스크의 용량

 
* 설명 : 스토리지에 저장되는 모든 데이터는 두 개의 물리적인 디스크에 각각 저장되고 모든 데이터는 중복된다.

* 장점 : 드라이브 하나가 고장 나면 똑같은 내용의 다른 드라이브가 하나 더 있기 때문에 매우 안전하다. RAID 1은 읽기 성능이 단일 드라이브에서의 성능과 같거나 훨씬 좋다.

* 단점 : 각 드라이브는 미러링되기 때문에 전체 용량의 절반밖에 사용하지 못한다. 드라이브 두 개에 동일한 데이터를 써야 하기 때문에 쓰기 성능이 나빠질 수 있지만 아직 다른 RAID 레벨의 쓰기 성능보다는 훨씬 낫다.
RAID Level 1 : Mirroring and Duplexing
 
 
RAID 2: 이 레벨은 더 이상 사용되지 않는다
RAID Level 2 : Hamming Code ECC

 
 
RAID 3(패리티를 사용하고 디스크를 병렬로 처리한다)

 
* 최소 드라이브 개수 : 3

 
* 최대 용량 : (디스크의 수 - 1) x 각 디스크의 용량

 
* 설명 : 데이터는 바이트 단위로 쪼개져서 모든 디스크에 균등하게 나뉘어 저장되고 패리티 정보는 별도의 전용 디스크에 저장된다.

* 장점 : 한 개의 드라이브가 고장 나는 것을 허용하며 순차적 쓰기(sequential write) 성능과 순차적 읽기(sequential read) 성능이 우수하다.
 
* 단점 : 잘 사용되지 않고 문제를 해결하는 것이 어려울 수 있다. 하드웨어 RAID가 되어야 실제로 쓸만하다. RAID 3은 보통 매우 효율적이지만 임의 쓰기(random write) 성능이 나쁘고 임의 읽기(random read) 성능은 꽤 좋다. .
 
RAID Level 3 : Parallel Transfer with Parity

 

RAID 4 (각 디스크는 패리티 블럭을 공유한다)
 
* 최소 드라이브 개수 : 3
 
* 최대 용량 : (디스크의 수 - 1) x 디스크의 용량
* 설명 : 모든 파일은 블럭으로 쪼개지고 각 블럭은 여러 디스크에 저장되지만 균등하진 않다. RAID 3처럼 RAID 4도 패리티를 처리하기 위해 별도의 디스크를 사용한다. 동시 트랜잭션 사용량이 많은 시스템에서 읽기 속도는 매우 중요한데 이런 시스템에 적합하다.
 
* 장점 : 드라이브 하나가 고장 나는 것을 허용하고 읽기 성능이 매우 좋다.
* 단점 : 쓰기 성능이 나쁘지만 블럭 읽기(block read) 성능은 괜찮다.

RAID Level 4 : Independent Data Disks with Shared Parity Disk
 
 

RAID 5(패리티를 순환시키는 것 없이 각 어레이에 접근한다)

* 최소 드라이브 개수 : 3
 
* 최대 용량 : (디스크의 수 - 1) x 디스크의 용량

 
* 설명 : RAID 4처럼 데이터의 블럭은 모든 디스크에 나뉘어 저장되지만 항상 균등하진 않고 패리티 정보도 모든 디스크에 나뉘어 저장된다.
 
* 장점 : 지원하는 회사가 많고 한 개의 드라이브가 고장 나는 것을 허용한다.

 
* 단점 : 디스크 재구성(rebuild)이 매우 느리고 쓰기 성능은 패리티 정보를 끊임없이 갱신해야 하기 때문에 우수하다고 할 수는 없다.
 
 
RAID 6(각 디스크에 패리티 정보가 두 번 독립적으로 분산된다)
* 최소 드라이브 개수 : 3
 
* 최대 용량 : (디스크의 수 - 2) x 디스크의 용량
* 설명 : RAID 4처럼 데이터의 블럭은 모든 디스크에 나뉘어 저장되지만 항상 균등하진 않고 패리티 정보도 모든 디스크에 나뉘어 저장된다.
 
* 장점 : 두 개의 드라이브까지 고장 나는 것을 허용하고 읽기 성능이 우수하고 매우 중요한 경우에 적합하다.
* 단점 : 쓰기 성능은 패리티를 여러 번 갱신해야 하기 때문에 RAID 5보다 매우 나쁘다. 디스크를 재구성하는 동안에 성능이 매우 나빠질 수 있다.
 
RAID Level 6 : Independent Data Disks with Two Independent Distributed Parity Schemes
 
 
RAID 10(고신뢰도 + 고가용성)
 
* 최소 드라이브 개수 : 4
* 최대 용량 :
 
* 설명 & 장점 :
RAID 10 is implemented as a striped array whose segments are RAID 1 arrays

RAID 10 has the same fault tolerance as RAID level 1

RAID 10 has the same overhead for fault-tolerance as mirroring alone

High I/O rates are achieved by striping RAID 1 segments

Under certain circumstances, RAID 10 array can sustain multiple simultaneous drive failures

Excellent solution for sites that would have otherwise gone with RAID 1 but need some additional performance boost

 
* 단점 :
Very expensive / High overhead

All drives must move in parallel to proper track lowering sustained performance

Very limited scalability at a very high inherent cost

* 사용하기 좋은 곳 :

Database server requiring high performance and fault tolerance

 
 
RAID 10 : Very High Reliability Combined with High Performance
 
 
 
RAID 50(고속 입출력 & 고속 데이터 전송)
 
* 최소 드라이브 개수 : 6
 
* 최대 용량 :
 
* 설명 & 장점 :

RAID 50 should have been called "RAID 03" because it was implemented as a striped (RAID level 0) array whose segments were RAID 3 arrays (during mid-90s).

 

Most current RAID 50 implementation is illustrated above RAID 50 is more fault tolerant than RAID 5 but has twice the parity overhead .

 

High data transfer rates are achieved thanks to its RAID 5 array segments.

High I/O rates for small requests are achieved thanks to its RAID 0 striping.

 

Maybe a good solution for sites who would have otherwise gone with RAID 5 but need some additional performance boost.

* 단점 :

Very expensive to implement.

All disk spindles must be synchronized, which limits the choice of drives.

Failure of two drives in one of the RAID 5 segments renders the whole array unusable.

 

* 사용하기 좋은 곳 :

RAID 5를 이용하는 곳 중에서 추가적인 성능향상을 하고자 하는 곳.

 
RAID Level 50 : High I/O Rates and Data Transfer Performance
 
 
 
RAID 1+0(고속 데이터 전송)
 
* 최소 드라이브 개수 : 4
 
* 최대 용량 :
 
* 설명 & 장점 :
RAID 0+1 is implemented as a mirrored array whose segments are RAID 0 arrays.
RAID 0+1 has the same fault tolerance as RAID level 5.
RAID 0+1 has the same overhead for fault-tolerance as mirroring alone.
High I/O rates are achieved thanks to multiple stripe segments.
Excellent solution for sites that need high performance but are not concerned with achieving maximum reliability
 
* 단점 :

RAID 0+1 is NOT to be confused with RAID 10.

A single drive failure will cause the whole array to become, in essence, a RAID Level 0 array.

Very expensive / High overhead.

All drives must move in parallel to proper track lowering sustained performance.

Very limited scalability at a very high inherent cost.

 

* 사용하기 좋은 곳 :

Imaging applications

General fileserver

 
RAID Level 0+1 : High Data Transfer Performance 
블로그 이미지

유효하지않음

,

 Bouncy Castle

The Bouncy Castle and unlimited strength JCE policy files add the encryption algorithms required for Lawson Single Sign-on.  During the Lawson installation, you will select the algorithms you want to use. However, not all algorithms are compatible with all versions of JDK. If you select an incompatible algorithm during the installation, an error message will prompt you to choose a different algorithm.  Some customers may want to use a specific algorithm. After completing this section, Lawson recommends that you use the regression tests provided by Bouncy Castle to verify that your algorithm is compatible with your JDK before you begin the installation.  

IMPORTANT Bouncy Castle is added to all JDKs used by the Lawson system before you install any Lawson products. Repeat the steps below for all JDKs consumed by the Lawson system, for example:

TheJDKdefined as JAVA_HOME and LAW_JAVA_HOME on the Lawson server.
• The JDK delivered with and used by the application server.
• Any JDKs consumed by other Lawson products that use Lawson Single Sign-on via the Distributed SSO solution (for example, Lawson Business Intelligence (LBI) applications such as Smart Notification and Framework Services).

 

Download Bouncy Castle files

 1. Log in as root.

 2. Download the following files from the Bouncy Castle download site http://www.bouncycastle.org/latest_releases.html.

• If you are using Java SDK 1.4.2, use Bouncy Castle 1.4 files.
• If you are using Java SDK 5, use Bouncy Castle 1.5 files.

File

Purpose

Bcprov-jdk1X-XXX.jar

Deliver algorithms to the JDK.

Bctest-jdk1X-XXX.jar

Contain regression tests used to verify which algorithms are compatible with your JDK.  Download these files if you want to verify algorithms before installing Lawson.

 3. Download the unlimited strength JCE policy files for the JDK(s) you are using:

JDK

Platform

Policy files to use

Where to find files

Lawson JDK (LAW_JAVA_HOME)

AIX

IBM

https://www6.software.ibm.com/dl/jcesdk/jcesdk-p

Lawson JDK (LAW_JAVA_HOME)

HP

 

Solaris

Sun

For JDK 1.4.2, use the “Other Downloads” link at http://java.sun.com/j2se/1.4.2/download.html

 

For JDK 5, use the “Other Downloads” link at http://java.sun.com/javase/downloads/index_jdk5.jsp

WebSphere JDK

HP

Solaris

For WebSphere 6.0.2.x, use Sun

 

Dor WebSphere 6.0.1.x, use IBM

For WebSphere 6.0.2.x, use the “Other Downloads” link at http://java.sun.com/j2se/1.4.2/download.html

 

For WebSPhere 6.1, use the IBM policy files at https://www6.software.ibm.com/dl/jcesdk/jcesdk-p

WebSphere JDK

AIX

IBM

https;//www6.software.ibm.com/dl/jcesdk/jcesdk-p

 

Note that the IBM policy files are the same for JDK 1.4 and JDK 1.5

   

Install Bouncy Castle

 1. Create a temporary directory to hold the Bouncy Castle regression test .jar file.

mkdir BCTestDir

 2. Copy the regression .jar into the temporary directory.

cp bctest-jdk1X-XXX.jar BCTestDir

 3. Copy the bcprov-jdk1X-XXX.jar to the following location(s).

Configuration

Location

All installations

$JAVA_HOME/jre/lib/ext

WebSphere installations

$WAS_HOME/java/jre/lib/ext

 4. Verify that the file permissions on the Bouncy Castle .jar files allow read and execute access for "owner", "group", and "other".  If they do not, change permissions on the files.

chmod 555 bcprov-jdk1X-XXX.jar
                
chmod 555 bctest-jdk1X-XXX.jar

where X-XXX is the version number of the .jar file

 NOTE The Bouncy Castle .jar file must be owned by the user who runs the servlet container. During the installation process, that user is always root. Once the Lawson installation is complete, you can change the ownership of the file.

 Configure Java Encryption

 1. Extract local_policy.jar and US_export_policy.jar from the unlimited strength policy files and copy them into the following location(s). 

Configuration

Location

All installations

$JAVA_HOME/jre/lib/security

WebSphere installations

$WAS_HOME/java/jre/lib/security

 

2. Verify that the file permissions on the $JAVA_HOME/jre/lib/security/java.security file allow write access for "owner", "group", and "other".  If they do not, change permissions on the file.

chmod 777 java.security

 3. Use a text editor to open the$JAVA_HOME/jre/lib/security/java.security file. Add the following line.

security.provider.ProviderNumber=org.bouncycastle.jce.provider.BouncyCastleProvider
where ProviderNumber is the number that reflects the position where the line appears in the file.

You must change the ProviderNumber for each security.provider that appears after the Bouncy Castle line.

• For Sun JDK, the security.provider line for Bouncy Castle must come AFTER the sun.security.provider.Sun line.

 

Sun JDK Example
security.provider.1=sun.security.provider.Sun
security.provider.2=com.sun.net.ssl.internal.ssl.Provider
security.provider.3=com.sun.rsajca.Provider
security.provider.4=org.bouncycastle.jce.provider.BouncyCastleProvider
security.provider.5=com.sun.crypto.provider.SunJCE
security.provider.6=sun.security.jgss.SunProvider

• For IBM JDK, the security.provider line for Bouncy Castle must come AFTER the com.ibm.crypto.provider.IBMJCE line.

IBM JDK Example
security.provider.1=com.ibm.crypto.provider.IBMJCE
security.provider.2=com.ibm.jsse.IBMJSSEProvider
security.provider.3=com.ibm.security.jgss.IBMJGSSProvider
security.provider.4=org.bouncycastle.jce.provider.BouncyCastleProvider
security.provider.5=com.ibm.security.cert.IBMCertPath
security.provider.6=com.ibm.crypto.pkcs11.provider.IBMPKCS11

 

4. Change file permissions on the java.security file to read/execute access for "owner", "group", and "other".

chmod 555 java.security

 

5. Repeat these steps for all JDKs used by your system, including the following:

• The WebSphere JDK located in WAS_HOME/java/jre/lib/security

JDKs on machines running applications that connect to Lawson using the Distributed Single Sign-on Solution (DSSO).

 

6. Run the Bouncy Castle algorithm verification tests.

 

Example: 

cd /tmp/dwnlds/bc
Mkdir bctest
cprp t* bctest/
cp -rp bcprov* $JAVA_HOME/jre/lib/ext
cp -rp bcprov* $WAS_HOME/java/jre/lib/ext
chmod 555 $JAVA_HOME/jre/lib/ext/bcprov*
chmod 555 $WAS_HOME/java/jre/lib/ext/bcprov*
chmod 555 /tmp/dwnlds/bc/bctest/bctest*

 

BACK_UP

cd /tmp/dwnlds/bc/
mkdir javabkup
mkdir wasbkup
cp -p $JAVA_HOME/jre/lib/security/* javabkup
cp -p $WAS_HOME/java/jre/lib/security/* wasbkup

jar -xvf unrestrict142.zip
cp -p local_policy.jar $JAVA_HOME/jre/lib/security/
cp -p US_export_policy.jar $JAVA_HOME/jre/lib/security/
cp -p local_policy.jar $WAS_HOME/java/jre/lib/security/
cp -p US_export_policy.jar $WAS_HOME/java/jre/lib/security/

 cd /etc/java5/jre/lib/security
chmod 777 java.security

 EDIT:

vi  $JAVA_HOME/jre/lib/security/java.security

security.provider.6=org.bouncycastle.jce.provider.BouncyCastleProvider

 vi $WAS_HOME/java/jre/lib/security/java.security

security.provider.9=org.bouncycastle.jce.provider.BouncyCastleProvider

 $JAVA_HOME/bin/java -cp bctest-jdk15-137.jar org.bouncycastle.crypto.test.RegressionTest > java.crypto.out 2>&1

 $JAVA_HOME/bin/java -cp bctest-jdk15-137.jar org.bouncycastle.jce.provider.test.RegressionTest > java.jcecrypto.out 2>&1

 $WAS_HOME/java/bin/java -cp bctest-jdk15-137.jar

org.bouncycastle.crypto.test.RegressionTest > was.crypto.out 2>&1

 $WAS_HOME/java/bin/java -cp bctest-jdk15-137.jar org.bouncycastle.jce.provider.test.RegressionTest > was.jcecrypto.out 2>&1

블로그 이미지

유효하지않음

,

Bandwidth Limiter Module

Bandwidth limiter module allows Apache web server to control over resources for each its virtual hosts. The module is an output filter in the Apache filters chain; each time a user requests data from the web server, the data (response) has to go through the module. The module breaks the data into smaller pieces and sends the pieces. And the module controls the bandwidth by introducing a small delay while sending the pieces. Looking at the module characteristics, the module is useful to limit access to predefined areas of the website and protect the web server from malicious users. It will significantly help small web-hosting servers with limited outbound bandwidth.

Illustration

Applying 100 kB/s bandwidth limit for a vhost gives 100 kB/s download speed for the first client requesting the vhost. When the second client requests the vhost, the speed will be equally divided to 50 kB/s for each client. Of course, when the third client requests the vhost, the speed will then be equally divided to 33.3 kB/s for each client. This equal division will keep continue each time a new user requests the vhost.

Installing Apache mod_bw in Ubuntu Linux

Bandwidth module (mod_bw) is not a default option in the Apache installation under Ubuntu Linux. The following are the steps to have bandwidth module enabled in Apache web server:

  • (Optional) If you may want to download wget and apxs2 to be able to download and compile mod_bw.
    # sudo apt-get install wget apache2-threaded-dev
  • Download and compile mod_bw.
    # wget http://ivn.cl/files/source/mod_bw-0.8.tgz
    # tar xvzf mod_bw-0.8.tgz # cd mod_bw # apxs2 -i -a -c mod_bw.c

    I am assuming that you get this error:

    apxs:Error: Activation failed for custom /etc/apache2/httpd.conf file..
    apxs:Error: At least one `LoadModule’ directive already has to exist..

    Yes, it is expected. Just ignore the error.

  • Create the load file.
    # cd /etc/apache2/mods-available
    # sudo sh -c "echo 'LoadModule bw_module /usr/lib/apache2/modules/mod_bw.so' > bw.load"
    # cd ../mods-enabled
    # ln -s ../mods-available/bw.load bw.load
  • Add Bandwidth Configuration to your Virtualhost, for example:
    <Virtualhost *>
    Servername www.example.com BandwidthModule On ForceBandWidthModule On Bandwidth all 1024000 MinBandwidth all 50000 LargeFileLimit * 500 50000 </Virtualhost>
    <Virtualhost *>
    Servername www.example.com
    BandwidthModule On
    ForceBandWidthModule On
    Bandwidth all 10240
    MinBandwidth all -1
    LargeFileLimit * 500 50000
    </Virtualhost>

    For more examples, please visit mod_bw setup.

  • Restart apache2 to activate the bandwidth module.
    # /etc/init.d/apache2 restart

 http://www.ivn.cl/apache/

블로그 이미지

유효하지않음

,

ORA-08002: 시퀀스 **.CURRVAL은 이 세션에서는 정의 되어 있지 않습니다

NEXTVAL 하기 전까지는 CURRVAL을 동일세션에서 사용할 수 없습니다

굳이 필요하다면 다음과 같이 해야합니다

 SELECT  LAST_NUMBER
 FROM    USER_SEQUENCES
 WHERE  SEQUENCE_NAME = '시퀀스명(대문자)'

블로그 이미지

유효하지않음

,
[출처] http://www.ibm.com/developerworks/kr/library/os-ecbug/

난이도 : 중급

Chris Aniszczyk, Software Engineer, IBM 
Pawel Leszek, Independent Software Consultant, Freelance

2007 년 6 월 05 일

소프트웨어 프로젝트 디버깅에 Eclipse 플랫폼에 내장된 디버깅 기능을 사용하는 방법을 배워봅시다. 디버깅은 프로그래머들에게는 피할 수 없는 문제입니다. 많은 수행 방법들이 있겠지만 궁극적으로 버그를 일으킨 코드를 찾는 것이 중요합니다. 예를 들어, 리눅스® 애플리케이션에서 가장 일반적인 에러는 세그멘테이션 오류(segmentation fault)입니다. 프로그램이 할당되지 않은 메모리에 액세스를 시도할 때 세그멘테이션 위반으로 인해 종료됩니다. 이러한 유형의 에러를 픽스 하려면 그러한 작동을 일으킨 코드 라인을 찾아야 합니다. 문제의 코드 라인을 찾았다면, 에러가 발생한 정황, 제휴 값, 변수, 메소드에 대해 아는 것도 도움이 됩니다. 디버거를 사용하면 이러한 정보를 매우 간단하게 찾을 수 있습니다.

편집자 주: 본 기술자료는 2003년 5월 Pawel Leszek이 집필하였고, 2007년 4월에 Chris Aniszczyk가 업데이트 하였습니다.

Eclipse 디버거와 Debug 뷰

Eclipse SDK -- 특히, Java™ Development Tools (JDT) 프로젝트-는 단계별 실행을 수행하는 기능, 중단점과 값을 설정하는 기능, 변수와 값을 검사하는 기능, 쓰레드를 중지하고 재시작 하는 기능을 포함하여 표준의 모든 디버깅 기능들을 제공하는 빌트인 자바 디버거들로 구성되어 있다. 게다가, 원격 머신에서 실행되는 애플리케이션들을 디버깅 할 수도 있다. Eclipse 플랫폼은 다른 프로그래밍 언어들도 각각의 언어 런타임에 이 디버그 장치들을 사용할 수 있다는 강점을 갖고 있다. 앞으로 알게 되겠지만, 같은 Eclipse Debug 뷰 역시 C/C++ 프로그래밍 언어에도 적용될 수 있다.

Eclipse Platform Workbench와 툴은 JDT 컴포넌트에 구현되어 다음과 같은 기능들을 Eclipse에 제공한다.

  • 프로젝트 관리 툴
  • 퍼스펙티브와 뷰
  • 빌더, 에디터, 검색, 빌드 함수
  • 디버거

Eclipse 디버거는 그 자체로 표준 플러그인 세트이다. Eclipse에는 또한 특별한 Debug 뷰가 있어서, 이 뷰를 통해서 Workbench에서 프로그램의 디버깅 및 실행을 관리할 수 있다. 디버깅 하고 있는 각 대상에 대해 중지된 쓰레드에 대한 스택 프레임을 디스플레이 한다. 프로그램의 각 쓰레드는 트리에 있는 노드로서 나타나고, Debug 뷰는 여러분이 실행하고 있는 각 대상의 프로세스를 디스플레이 한다. 쓰레드가 중지되면, 스택 프레임은 자식 엘리먼트로서 보여진다.

Eclipse 디버거를 사용하기 전에 Java SDK/JRE (Java VM V1.4를 권장한다.) 와 Eclipse Platform SDK V3.3이 설치되고, 이것들이 아무런 문제 없이 실행되고 있는 것으로 간주하겠다. 일반적으로, Eclipse 샘플을 사용하여 디버깅 옵션을 테스트 하는 것도 좋은 생각이다. C/C++ 프로젝트를 개발 및 디버그 한다면, C/C++ Development Tools (CDT)를 설치해야 한다. Java SDK/JRE, Eclipse 플랫폼과 샘플, CDT에 대한 링크는 참고자료 섹션을 참조하라. 그림 1은 Debug 퍼스펙티브의 모습이다.


그림 1. Eclipse Debug 퍼스펙티브의 뷰
 


자바 프로그램 디버깅

프로젝트를 디버깅 하기 전에, 코드가 깨끗하게 컴파일 및 실행되어야 한다. 애플리케이션에 맞게 실행 설정을 해야 하고 이것이 올바르게 시작되는지를 확인해야 한다. Run > Debug 메뉴를 사용하여 디버그 설정을 한다. 디버거에 의해서 메인 자바 클래스로서 사용될 클래스를 선택해야 한다. (그림 2) 단일 프로젝트에 원하는 만큼의 디버그 설정을 가질 수 있다. (Run > Debug에서) 디버거가 시작될 때, 새로운 창에서 열리며 이제 디버깅을 시작할 준비가 된 것이다.


그림 2. 디버거 설정 시 프로젝트의 메인 자바 클래스 설정하기
 


이제는 Eclipse에서의 일반적인 디버깅 방법들을 설명하도록 하겠다.

중단점 설정하기

디버깅을 위해 애플리케이션을 시작할 때, Eclipse는 자동으로 Debug 퍼스펙티브로 전환한다. 가장 일반적인 디버깅 절차는 조건 문 또는 루프 내에 변수와 값을 검사할 수 있는 중단점을 설정하는 것이다. Java 퍼스펙티브의 Package Explorer 뷰에서 중단점을 설정하려면, 선택된 소스 코드를 더블 클릭하여 에디터에서 연다. 코드를 검사하고 마커 바(에디터 영역의 왼쪽 가장자리)에 있는 커서를 중지된 코드가 있는 라인에 둔다. 더블 클릭하여 중단점을 설정한다.


그림 3. 에디터의 왼쪽 부분에 있는 두 개의 중단점 마커 
 

이제 Run > Debug 메뉴에서 디버깅 세션을 시작한다. 한 라인에 여러 문을 놓지 않는 것이 중요하다. 같은 라인에 있는 한 개 이상의 문에 라인 중단점을 뛰어넘거나 설정할 수 없기 때문이다.


그림 4. 왼쪽 여백에 화살표로 현재 실행되고 있는 것을 보여주고 있다. 
 

모든 중단점들을 관리하는 편리한 Breakpoints 뷰도 있다.


그림 5. Breakpoints 뷰
 


조건적 중단점

에러가 어디에서 발생했는지 알았다면 프로그램이 충돌하기 전에 올바르게 수행되었는지를 확인해야 한다. 한 가지 방법은 문제 지점에 다다를 때까지 한번에 하나씩 프로그램의 모든 문을 검사하는 것이다. 가끔은 코드의 한 섹션을 실행하고 그 지점에서 실행을 멈춰서 그 위치에 있는 데이터를 검사하는 것이 더 나을 때가 있다. 식의 값이 변할 때마다 실행되는 조건적 중단점을 선언할 수도 있다. (그림 6) 게다가, 조건 식을 타이핑할 때 Code Assist를 사용할 수 있다.


그림 6. 조건적 중단점 트리거 설정하기
 


식 계산하기

Debug 퍼스펙티브에 있는 에디터에서 식을 계산하려면, 중단점이 설정된 전체 라인을 선택하고 콘텍스트 메뉴에서 Ctrl+Shift+I 또는 관심 있는 변수를 오른쪽 클릭하여 Inspect 옵션을 선택한다. 식은 현재 스택 프레임 컨텍스트에서 계산되고 결과는 Display 윈도우의 Expressions 뷰에 디스플레이 된다.


그림 7. Inspect 옵션을 이용하여 식 계산하기 
 

활성 코드 스크랩북킹(Scrapbooking)

Display 뷰에서는 스크랩북 형태로 활성 코드를 조작할 수 있다. (그림 8) 변수를 처리하려면 Display 뷰에 변수 이름을 타이핑 하면 익숙한 Content Assist가 나타난다.


그림 8. Display 뷰
 


디버거가 중단점에서 멈추면 Debug 뷰 툴바에서 Step Over 옵션을 선택하여 디버거 세션을 계속 진행할 수 있다. (그림 9) 이것은 하이라이트 된 코드 라인을 건너뛰고 같은 메소드의 다음 라인에서 실행을 계속한다.(또는 현재 메소드가 호출되었던 메소드에서 실행을 계속한다.) 마지막 단계의 결과로 변경된 변수들은 색깔로 하이라이트 된다. (기본 색은 노란색이다.) 색상은 디버그 프레퍼런스 페이지에서 변경할 수 있다.


그림 9. 색상을 변경하는 변수
 


Debug 뷰에서 쓰레드의 실행을 중지하기 위해, 실행 쓰레드를 선택하고 Debug 뷰 툴바에서 Suspend를 클릭한다. 이 쓰레드에 대한 현재 호출 스택이 디스플레이 되고 현재 실행 라인이 Debug 퍼스펙티브의 에디터에서 하이라이트 된다. 쓰레드가 중지되면 커서는 Java 에디터의 변수 위에 놓이고 그 변수의 작은 창으로 디스플레이 된다. 또한, 이 쓰레드의 상단 스택 프레임이 자동으로 선택되고 스택 프레임에 있는 변수들이 Variables 뷰에 디스플레이 된다. 이름을 클릭하여 Variables 뷰에 있는 해당 변수들을 검사할 수 있다.

Hotswap Bug Fixing: 코드 픽스

Java Virtual Machine (JVM) V1.4 또는 이후 버전을 실행한다면, Eclipse는 Hotswap Bug Fixing (JVM V1.3 이하 버전에서는 실행되지 않음)이라고 하는 기능을 지원한다. 디버거 세션 중에 소스 코드를 변경할 수 있는데 이는 애플리케이션을 종료해서 코드를 수정하고 재컴파일 한 다음 또 다른 디버깅 세션을 시작하는 것 보다 낫다. 이 기능을 사용하려면 에디터에서 코드를 수정하고 디버깅을 재시작 한다. 이 기능은 JVM V1.4가 Java Platform Debugger Architecture (JPDA)와 호환되면서 사용할 수 있게 되었다. JPDA는 실행 애플리케이션에서 수정된 코드를 대체하는 기능을 구현한다. 물론 이것은 애플리케이션을 시작하거나 오류가 난 지점으로 가는데 오랜 시간이 걸릴 경우에 특히 유용하다.

디버깅을 끝냈음에도 프로그램이 완전하게 실행되지 않는다면 Debug 뷰의 콘텍스트 메뉴에서 Terminate 옵션을 선택한다. 디버거 세션에 있는 동안 Resume 대신 Debug 또는 Run을 사용하는 실수를 흔히 저지른다. 이것은 현재 세션을 지속하는 것이 아닌 또 다른 디버거 세션을 시작한다.




위로


원격 디버깅

Eclipse 디버거는 원격 애플리케이션을 디버깅 하는데도 재미있는 옵션을 제공한다. 자바 애플리케이션을 실행하는 원격 VM으로 연결하여 애플리케이션에 부착할 수 있다. 원격 디버깅 세션에서 실행하는 것은 로컬 디버깅과 비슷하다. 하지만, 원격 디버깅 설정에는 Run > Debug 윈도우에서 다른 설정을 해야 한다. 왼쪽 뷰에서 Remote Java Application 항목을 선택한 다음 New를 클릭한다. 새로운 원격 시작 설정이 이루어지면 세 개의 탭(Connect, Source, Common)이 보인다.

Connect 탭의 Project 필드에서 (소스 코드 검색용) 시작 참조용으로 사용할 프로젝트를 선택한다. Connect 탭의 Host 필드에서, 자바 프로그램이 실행되는 원격 호스트의 IP 주소나 도메인 이름을 입력한다. Connect 탭의 Port 필드에서, 원격 VM이 연결을 수락하는 포트를 입력한다. 일반적으로, 이 포트는 원격 VM이 시작될 때 지정된다. Terminate 명령어를 원격 세션에서 사용할 수 있는지 여부를 디버거가 결정하도록 하려면 Allow termination of remote VM 옵션을 선택한다. 연결된 VM을 종료하고 싶다면 이 옵션을 선택한다. 이제 여러분이 Debug 옵션을 선택하면, 디버거는 지정된 주소와 포트에 있는 원격 VM으로 연결하고 결과가 Debug 뷰에 디스플레이 된다.

런처(launcher)가 지정된 주소에 있는 VM에 연결되지 않으면 에러 메시지가 나타난다. 일반적으로, 원격 디버깅 기능의 가용성은 원격 호스트에서 실행되는 Java VM에 달려있다.


그림 10. 원격 디버깅 세션을 위한 연결 프로퍼티 설정하기 
 

-Xdebug
-Xnoagent
-Djava.compiler=NONE
-Xrunjdwp:transport=dt_socket,server=y,address=3999,suspend=n




위로


다른 언어 디버깅 하기

자바가 Eclipse에서 가장 일반적으로 사용되지만, Eclipse는 다른 많은 언어들도 지원할 수 있는 확장성 있는 플랫폼이다. Eclipse는 C/C++ Development Tools (CDT) 프로젝트를 통해 C/C++을 지원한다. CDT는 C/C++ 코드를 디버깅하는 기능으로 표준 Eclipse Debug 뷰를 확장하고, CDT Debug 뷰에서는 워크벤치의 C/C++ 프로젝트의 디버깅을 관리할 수 있다. CDT에는 내부 디버거가 없지만 GNU GDB 디버거에 대한 프론트엔드를 제공한다. 이것은 로컬에서만 사용된다. PHP Development Tools (PDT) 같은 프로젝트도 고유의 디버거를 제공한다. (그림 11)


그림 11. PHP 디버거
 





위로


결론

Eclipse 플랫폼은 단계 실행을 수행하는 기능, 중단점과 값을 설정하는 기능, 변수와 값을 검사하는 기능, 쓰레드를 중지 및 시작하는 기능을 포함한, 표준 디버깅 기능들을 갖춘 자바 디버거를 제공한다. 원격 머신에서 실행되는 애플리케이션을 디버깅 하는 데에도 사용될 수 있다. Eclipse 플랫폼은 주로 자바 개발 환경이지만, 같은 Eclipse Debug 뷰가 C/C++, PHP, 기타 프로그래밍 언어에서도 사용될 수 있다.




위로


감사의 말

그림 11"을 만들어 준 Tyler Anderson에게 감사의 말을 전한다.



참고자료

교육

제품 및 기술 얻기

토론
  • Eclipse CDT newsgroups: C/C++ 디버깅 (기본 Usenet 뉴스 리더기 애플리케이션이 시작되면 eclipse.platform이 열린다.)

  • Eclipse ATF newsgroups: JavaScript 디버깅 (기본 Usenet 뉴스 리더기 애플리케이션이 시작되면 eclipse.platform이 열린다.)

  • Eclipse platform newsgroups: 디버깅 및 기타 Eclipse 플랫폼 관련 질문들 (기본 Usenet 뉴스 리더기 애플리케이션이 시작되면 eclipse.platform이 열린다.)

  • Eclipse Platform newsgroups: Eclipse 관련 기본 질문들 (기본 Usenet 뉴스 리더기 애플리케이션이 시작되면 eclipse.platform이 열린다.)

  • Eclipse newsgroups: Eclipse 사용과 확장과 관련한 자료들

  • Participate in developerWorks blogs and get involved in the developerWorks community.



필자소개

Chris Aniszczyk는 IBM Lotus 팀에서 OSGi 관련 개발 분야의 소프트웨어 에지니어이다. 오픈 소스에 대한 강한 열정을 지니고 있으며 Gentoo Linux로 작업하고 있다. 몇몇 Eclipse 프로젝트(PDE, ECF, EMFT)의 커미터로서도 활약하고 있다. 언제라도 오픈 소스와 Eclipse에 대해 이야기할 준비가 되어 있다.


Pawel Leszek(Studio B 저자)은 독립 소프트웨어 컨설턴트이자 Linux/Win/Mac OS 시스템 아키텍처와 관리를 전문으로 다루는 저자이다. 많은 운영 체제, 프로그래밍 언어, 네트워크 프로토콜, Lotus Domino와 DB2에 경험이 있다. "LinuxWorld"의 기자이며, "PC World"의 리눅스 칼럼니스트로 활동하고 있다. Warsaw에서 아내와 딸과 함께 살고 있다. (pawel.leszek@ipgate.pl)


블로그 이미지

유효하지않음

,
[출처]  http://kyungseo.pe.kr/blog/trackback/102

JEUS 운영 및 관리

JEUS 5.0을 버전을 기준으로 하고 설치시 입력한 JEUS 관리자의 비밀번호는 jeusadmin이라고 전제한다.

JEUS 구동

주로 jboot, jdown이란 이름으로 스크립트를 작성하여 실행한다. 이 파일들의 실제 명령행은 다음과 같다.

  • jboot: jeus -Uadministrator -Pjeusadmin
  • jdown: jeusadmin -Uadministrator -Pjeusadmin jeusexit

jeusadmin console

jeusadmin 콘솔툴을 이용하여 JEUS 컨테이너기동/종료, 엔진리스트확인 등 JEUS 엔진의 상태를 제어 및 점검한다.

  • 콘솔 실행: jeusadmin 'hostname' -Uadministrator -Pjeusadmin
  • 명령 목록
    • allenglist: jeusadmin의 allenglist 명령은 현재 각 컨테이너의 엔진기동 상태를 보여준다.
    • downcon <container-name>: 지정된 컨테이너를 종료시킨다.
    • startcon <container-name>: 지정된 컨테이너를 기동시킨다.
    • pidlist: JEUS의 엔진 프로세스를 확인한다.

webadmin console

webadmin 콘솔은 JEUS의 컨테이너 내부에 기동된 서블릿 엔진의 상태를 모니터링하기 위한 명령프롬프트이다.

  • 콘솔 실행: webadmin <container-name> -Uadministrator -Pjeusadmin
  • 명령 목록
    • ti: ti는 Thread Information의 약자로 JEUS 서블릿 엔진의 컨텍스트그룹 내부의 Worker Thread의 상태를 체크하기 위한 명령어이다.
    • st -m: 현재 Container의 JVM Memory 사용 현황
    • st -r: 설정한 Context로 들어온 요청 count와 평균처리시간
    • st -s: 현재 유지하고 있는 세션 객체의 수

webadmin 반복 모니터링

webadmin 내의 모니터링 명령어를 주기적으로 자동실행하게 하려면 다음과 같은 형식으로 명령어를 실행한다.

  • <command> -i 주기(초) -k 횟수
  • 예) ti -i 2 -k 10 : ti 명령어를 2초 간격으로 10번 수행

dbpooladmin console

dbpooladmin 콘솔은 컨테이너별로 할당된 Database Pool의 상태를 모니터링하기 위한 명령프롬프트이다.

  • 콘솔 실행: dbpooladmin<container-name> -Uadministrator -Pjeusadmin
  • 명령 목록
    • Info: 해당 컨테이너에서 관리되고 있는 Database Pool의 정보가 표시된다.
    • min, max 값은 JEUSMain.xml에 설정한 Pool의 최소/최대값이며 current는 현재 풀에 보관되고 있는 실제 커넥션의 수, idle의 풀에 보관되고 있는 커넥션중, 사용가능한 개수를 의미한다.

JEUS 웹 관리자

http://hostname:9744/webadmin 로 접속하여 administrator/jeusadmin 계정으로 로그인한다.

 

JEUS 웹 관리자

JEUS 장애 처리

JEUS 프로세스ID (PID) 확인

JEUS의 엔진 프로세스는 다음과 같이 2가지 방법으로 확인할 수 있다.

  • ps -ef | grep java
    • -Xmx512m 이후 부분을 확인하여 JEUS Manager 프로세스임을 확인한다.
    • [-D컨테이너이름]을 이용하여 컨테이너 프로세스임을 확인한다.
  • jeusadmin 콘솔툴을 이용한 PID 확인
    • pidlist: pidlist 명령을 사용하여 PID를 확인한다.

JAVA Dump

  • 덤프 생성: kill -3 [JEUS-PID]
  • 덤프 확인: JEUS JAVA프로세스에서 생성한 덤프는 JeusServerLog에서 확인한다.
    • 예) vi $JEUS_HOME/logs/`hostname`/JeusServer_20070201.log
WebtoB 운영 및 관리

WebtoB 구동

  • wsboot
  • wsdown-I : ps -ef을 이용하여 wsm, hth, htl, html 등의 프로세스가 나타나지 않으면 정상 종료

wsadmin console

WebtoB 시스템을 관리하기 위해서 wsadmin이라는 프로그램이 제공된다. wsadmin 프로그램은 UNIX 환경의 shell과 비슷한 Command Interpreter 이다. 즉, 항상 프롬프트상태로 대기중이다가 입력되는 명령어를 해석하여 이를 실행하게 된다. 여러 Node를 한 Domain으로 사용하는 경우 wsadmin으로 전체를 중앙관리가 가능하며 각 Node 별로 로컬에서만도 관리가 가능하다.

  • wsadmin
  • 명령 목록
    • ci: 요청에 대한 현재 클라이언트 정보를 표시한다. HTH당 접속한 클라이언트의 KeepAlive 되어있는 개수를 보여준다. WebtoB단에 요청을 보내고 HTTP Session의 KeepAliveTimeout 전까지 유지되고 있는 클라이언트의 총 개수 정보이다.
    • ci -s: 현재 클라이언트의 전체 수를 표시한다.
    • si: 웹서버 환경설정 파일에서 *SERVER 절에 선언한 서버들의 수행정보를 보여준다.
    • st -s: 웹서버 환경설정 파일에서 *SERVER, *URI, *EXT 절에 설정한 서비스의 상태가 보인다.
    • st -p: WebtoB 프로세스의 상태를 표시한다. 주로 JEUS-WebtoB간 연동 상태를 확인할 때 사용한다.

wsadmin 명령 연속 보기

ci, st -s, st -p, si 등의 명령어를 다음과 같이 수행하면 주기적으로 WebtoB의 상태를 모니터링할 수 있다.

  • r -i <시간(초)> -k <횟수> <명령>
  • 예) r -i 1 -k 1000 st -s
JEUS alias 설정

.profile 참고

...
export JEUS_HOME=/jeus
...
#### JEUS alias ####
alias ja='jeusadmin `hostname` -Uadministrator -Pjeusadmin'
alias ea='ejbadmin `hostname`_ejb_engine1 -Uadministrator -Pjeusadmin'
alias wa='webadmin `hostname`_container1 -Uadministrator -Pjeusadmin'
alias da='dbpooladmin `hostname`_container1 -Uadministrator -Pjeusadmin'
alias ti='webadmin `hostname`_servlet_engine1 -Uadministrator -Pjeusadmin ti -i 3 -k 100000'
alias ss='webadmin `hostname`_servlet_engine1 -Uadministrator -Pjeusadmin st -s -i 3 -k 100000'
alias sd='webadmin `hostname`_servlet_engine1 -Uadministrator -Pjeusadmin st -d -i 3 -k 100000'
alias di='dbpooladmin `hostname`_container1 -Uadministrator -Pjeusadmin info -i 3 -k 100000'

alias jcfg='cd ${JEUS_HOME}/config/`hostname`'
alias jbin='cd ${JEUS_HOME}/bin'
alias scfg='cd ${JEUS_HOME}/config/`hostname`/`hostname`_servlet_engine1'
alias ecfg='cd ${JEUS_HOME}/config/`hostname`/`hostname`_ejb_engine1'

alias jhome='cd ${JEUS_HOME}'
alias lhome='cd ${JEUS_HOME}/logs'

alias jlog='tail -f ${JEUS_HOME}/logs/`hostname`/JeusServer_`date +%Y%m%d`.log'
alias alog='tail -f ${JEUS_HOME}/logs/`hostname`_servlet_engine1/MyGroup/accesslog/access_`date +%Y%m%d`.log'
alias elog='tail -f ${JEUS_HOME}/logs/`hostname`_servlet_engine1/MyGroup/errorlog/error_`date +%Y%m%d`.log'
alias ulog='tail -f ${JEUS_HOME}/logs/`hostname`_servlet_engine1/MyGroup/userlog/user_`date +%Y%m%d`.log'

...
 
 
블로그 이미지

유효하지않음

,

folding linux lines

OS/Linux 2008. 11. 25. 16:05

fold : 접다, 우리안에 넣다.
80 컬럼이 넘는 긴 라인을 갖는 파일을 80컬럼으로 만들고자 한다면 다음의 명령어를
사용할 수 있다.

$ fold -w 60 filename

60 컬럼으로 만들고 싶은 경우 위의 명령어를 사용할 수 있다.

자세한 옵션은 man page 참조. 원문에는 Linux 명령어라고 하는데 Solaris에서도
명령어가 작동한다.
블로그 이미지

유효하지않음

,
[출처] http://pgclks.tistory.com/140

host login: root
configuration error - unknown item 'PASS_MIN_LEN' (notify administrator)
Password:

o 참고 URL

http://kldp.org/files/______________________________520.doc http://www.puschitz.com/SecuringLinux.shtml#EnablingPasswordAging
http://www.puschitz.com/SecuringLinux.shtml#EnforcingStrongerPasswords

o 사용예 설명

다음 예제는 어떻게 다음의 패스워드 규칙을 적용시키는가를 보여준다.
- 패스워드의 최소길이 8자
    pam_cracklib.so minlen=8
- 소문자 최소 1자
    pam_cracklib.so lcredit=-1
- 대문자 최소 1자
    pam_cracklib.so ucredit=-1
- 숫자 최소 1자
    pam_cracklib.so dcredit=-1
- 문자와 숫자이외의 문자 최소 1자(특수문자를 말하는 듯..)
    pam_cracklib.so ocredit=-1

이 패스워드 제한을 설정하려면 /etc/pam.d/system-auth 파일을 열어 파란색으로 된 부분을 추가하거나
변경을 하라

auth           required       /lib/security/$ISA/pam_env.so
auth           sufficient      /lib/security/$ISA/pam_unix.so likeauth nullok
auth           required       /lib/security/$ISA/pam_deny.so
account      required       /lib/security/$ISA/pam_unix.so
account      sufficient      /lib/security/$ISA/pam_succeed_if.so uid < 100 quiet
account      required       /lib/security/$ISA/pam_permit.so
password   requisite       /lib/security/$ISA/pam_cracklib.so retry=3 minlen=8 lcredit=-1 ucredit=-1 dcredit=-1 ocredit=-1
password   sufficient      /lib/security/$ISA/pam_unix.so nullok use_authtok md5 shadow
password   required       /lib/security/$ISA/pam_deny.so
session      required       /lib/security/$ISA/pam_limits.so
session      required       /lib/security/$ISA/pam_unix.so

password aging은 /etc/shadow 파일을 직접 수정해서 변경할 수도 있지만
chage 명령을 이용하면 좀더 쉽게 사용할 수 있습니다.

chage -l ID : 현재의 에이징 정보
chage -m mindays ID : 암호 의무사용기간 수정
chage -M maxdays ID : 암호 유효기간 수정
chage -d lastdays ID : 암호 변경일 수
chage -E expiredays ID : 계정 만료일 수정

블로그 이미지

유효하지않음

,

시스템 시간 동기화

OS 2008. 11. 25. 16:02

○ NTP 서버(2008년 4월 23일 기준)
    time.bora.net
    time.wonkwang.ac.kr

○ Time Sync
    1) Solaris
        # rdate [NTP서버]
            예) # rdate time.bora.net
    2) linux
        # rdate -s [NTP서버]
            예) # rdate -s time.bora.net
    3) windows
        i) 날짜/시간 등록정보창에서 표준시간대 선택
            - 한국이면 (GMT+09:00) 서울
        ii) cmd 창 실행
            - net time /setsntp:time.bora.net
                                       ^^^^^^^^^^^^^
                                         NTP Server


○ Windows 2008  Sync
1. w32tm /resync 
로컬 컴퓨터에 다시 동기화 명령을 보내는 중
사용 가능한 시간 데이터가 없어 컴퓨터가 동기화하지 못했습니다.

2. w32tm /config /manualpeerlist:"time.bora.net,0x9" /syncfromflags:MANUAL
명령이 성공적으로 완료되었습니다.

3. net stop w32time
Windows Time 서비스를 멈춥니다..
Windows Time 서비스를 잘 멈추었습니다.

4. net start w32time
Windows Time 서비스를 시작합니다..
Windows Time 서비스가 잘 시작되었습니다.

5. w32tm /resync
로컬 컴퓨터에 다시 동기화 명령을 보내는 중
명령이 성공적으로 완료되어습니다.


블로그 이미지

유효하지않음

,

VIM을 사용하자

OS/Linux 2008. 11. 24. 13:42

[출처] http://teamblog.joinc.co.kr/yundream/3

VIM을 사용하자

윤 상배

dreamyun@yahoo.co.kr

고친 과정
고침 0.9 2004년 3월 10일 17시
vim 모드와 관련된 부가내용 추가
고침 0.8 2003년 3월 1일 23시
최초 문서작성

차례

1. vim 이란

vim 은 유닉스 계열에서 전통적으로 널리 사용도던 vi 의 improve 즉 undo, syntax coloring, split windows 등의 기능을 포함시킨 vi 의 보강된 프로그램이다.

이 문서는 vim 의 기본적인 사용법과, 프로그래밍을 위한 여러가지 팁을 담고 있다. vim 버젼은 6.0 을 기준으로 한다. vim(vi)에 대한 자세한 사용방법은 여기에서는 제시하지 않을것이다. 가장 기본적인 사항만 언급할것이며, 자세한 사용법은 vi 사용자그룹 사이트를 참고하기 바란다.


2. VIM의 기본사용법 익히기

이번장에서는 vim의 기본적인 사용법에 대해서 알아보도록 하겠다. 위에서 언급했듯이, 이문서는 VIM의 레퍼런스 가이드는 아니다. 기본적인 사용이 가능하도록 가장 기초적인 내용들만 다룰것이다.


2.1. vim 모드

다른 에디터를 사용하던 유저가 vim을 처음 접하면서 가장 난감해 하는 부분이 vim의 상태(mode)개념이다.vim은 다른 에디터들과 달리, 실행을 시켰다고 해서 즉시 입력이 이루어지지 않는다. 많은 vim을 처음 접하는 유저는 어떻게 글을 입력할지 몰라서 vim의 사용을 접게되는 경우가 발생하는데, 여기에 그 이유가 있다. vi 는 크게 세가지 상태로 나뉘어진다. 첫번째가 명령어 모드로 키입력이 바로 실행되는 상태이며, 다음은 상태모드로 실제 문서를 편집하는 모드 마지막이 ex 상태로 ex 명령을 실행시키는 상태이다.

vi 를 처음실행시키면 입력모드가 아닌 명령모드 상태에 놓이게 된다. 이 상태에서는 문자의 입력이 이루어지지 않으며, 찾기등과 같은 간단한 문서관련 명령을 실행할 수 있다. 이 명령모드 상태에서 ":" 키를 누르면 ex 상태로 a, i, o 키 등을 누르면 입력 상태로 넘어가게 된다. 일단 입력상태로 들어가게 되면 문서 편집을 할수 있게 되는데, 이때 ESC 키를 누르면 명령모드 상태로 넘어가게 된다.

표 1. vim의 상태(mode)

명령 상태 처음 vim을 실행했을때, 입력상태/명령상태에서 ESC입력시 간단한 찾기, 커서 이동, ex 상태로 넘어가기
ex 상태 명령 상태에서 (":") 각종 치환, 저장, 파일읽기, vim설정등과 같은 대부분의 작업들
입력 상태 명령 상태에서 (a,i,o 키 입력) 내용 입력


2.2. 명령어모드의 사용

우리는 명령모드에서 여러가지 명령을 입력함으로써, 복사, 붙이기, 삭제 문서입력, 문서저장, 문서불러오기, 커서이동 등의 작업을 할수 있다. 이번 장에서는 이러한 명령모드에서 사용되는 각종 명령어에 대해서 알아보도록 하겠다.


2.2.1. 커서 이동

기본적으로 vi 는 입력모드에서 방향키를 이용해서 커서 이동을 하지 못하도록 되어있다. 비록 최근의 vim 이 입력모드에서 방향키를 이용한 커서 이동을 지원하고 있기는 하지만, 명령모드에서의 키이동이 훨씬 빠르고 편하므로, 처음에는 좀 어색하더라도 명령모드에서의 키 이동을 익히도록 하자.

표 2. 커서 이동

k 커서를 위로 움직임
j 커서를 아래로 움직임
h 커서를 왼쪽으로 움직임
l 커서를 오른쪽으로 움직임
- 커서를 줄의 처음으로 옮김
e, E 다음단어의 끝으로, 문자단위 이동
w, W 다음단어의 처음으로, 문자단위 이동
$ 줄의 마지막으로
0 줄의 처음으로
^ 줄의 처음으로(공백이 아닌 처음시작되는 문자)
Shift+g 문서의 마지막으로 이동한다.
gg, 1g 문서의 처음으로 이동한다. 1대신 다른 숫자를 입력하면 해당 숫자의 라인으로 이동한다.
), ( 다음, 이전 문장의 처음으로
}, { 다음, 이전문단의 처음으로
]], [[ 다음, 이전 구절의 처음으로


2.2.2. 화면 스크롤

위의 커서명령 이동이 매우 편하기는 하지만, 만약 페이지가 한 2000라인 될경우, 위의 커서를 이용해서 한줄씩 이동하는데에는 너무 많은 시간이 걸릴것이다. 그래서 vi 에서는 화면 단위의 스크롤이 가능한 명령들을 제공한다. 아래의 화면 스크롤 명령어들을 익히면 빠른 위치이동을 위해 매우 유용하게 사용할수 있다. ^F 는 CTRL+F 를 의미한다.

표 3. 화면 스크롤

^F 한 화면 을 앞으로 스크롤
^B 한 화면 을 뒤로 스크롤
^D 반 화면 을 앞으로 스크롤
^U 반 화면 을 뒤로 스크롤
^E 한줄 앞으로 스크롤
^Y 한줄 뒤로 스크롤
Shift + h 화면의 맨 윗줄로
Shift + m 화면의 중간줄로
Shift + l 화면의 맨 아랫줄로


2.2.3. 마크 이동

일종의 책갈피 기능이라고 보면 된다. 자주 참조해야할 라인에 마크를 해놓고 필요할때 곧바로 마크된 영역으로 이동하기 위해서 사용한다. 마크는 mx 형식으로 사용할수 있다. x 는 (a~z)까지의 문자로 마크된 영역의 이름을 지정하기 위해서 사용한다. 마크된 영역으로 이동하기 위해서는 'x 와 `x 를 사용한다. 'x 는 마크된 라인의 가장 앞으로 이동하고, `x 는 마크된 라인의 정확한 위치로 이동한다.


2.2.4. 입력 명령

지금 vi 를 실행시켜보자. vi 는 기본적으로 명령모드로 실행되므로, 지금상태에서는 문서 작성을 할수 없을것이다. 우리는 다음과 같은 키입력을 통해서 입력모드 상태로 전환할수 있다.

표 4. 입력 명령

i 현재위치에서 삽입
I 현재줄의 처음위치에서 삽입
a 현재위치에서 한칸앞으로 이동해서 삽입
A 현재줄의 마지막위치에서 삽입
o 새로운 줄을 커서 아래에 연다
O 새로운 줄을 커서 위연다
s 현재 위치의 문자를 지우고 입력모드로 들어간다.
S 현재위치의 라인을 지우고 입력모드로 들어간다.


2.2.5. 편집명령

여기에서는 vi의 편집기능인 복사, 붙이기, 삭제에 대해서 알아 보도록 하겠다. 다른 에디터들은 보통 마우스를 이용해서 블럭을 지정해서 편집을 하는 반면, vi 는 명령어 모드에서 키보드 만을 이용해서 편집이 가능하므로, 매우 편리하고 빠르게 편집작업들이 가능하다. 또한 라인단위 블럭, 블럭단위 블럭등의 선택 모드를 지원함으로써, 문서에서 원하는 부분에 대한 작업을 좀더 쉽게 할수 있다.


2.2.5.1. 편집(none visual block 모드)

visual block 모드가 아닌 상태에서이 편집에 관한 내용이다.

표 5. 복사,삭제,붙이기

y 한줄 복사
yn 현재 라인에서부터 n라인만큼을 복사
p 복사된 내용 붙이기
dd 한줄삭제
dw 한단어 삭제
Shift+d, d$ 현재커서 위치에서 마지막까지 삭제
Shift+j 현재 행의 개행문자를 제거한다. 즉 아래라인을 현재라인에 덧붙인다.


2.2.5.2. Undo (되돌리기)

vim 은 다중의 undo 기능을 지원한다. 뒤로 되돌리고 싶다면 단지 'u'키만 입력하면 된다.


2.2.5.3. 블럭 지정

이번엔 블럭지정, 그중에서도 vim 에서 지원하는 visual 블럭 지정에 대해서 알아보겠다. vim visual 블럭 지정 기능을 사용할경우 지정범위가 반전되면서 눈에 보이기 때문에, 효과적인 블럭지정이 가능하도록 도와준다. 범위지정을 위해서 'hjkl', 'Shift+g,GG' 과 같은 이동명령 과 화면스크롤 명령을 사용해서 범위지정을 좀더 빠르게 할수 있다.

표 6. 블럭지정

v 단어단위로 블럭지정이 가능하다. 블럭범위는 이동명령인 'hjkl' 로 원하는 범위 만큼 지정할수 있다.
Shift+v 라인단위 블럭지정이다. 라인전체가 선택되며, 위아래 이동명령 'hj' 으로 범위 지정이 가능하다.
Ctrl+v 블럭단위 블럭지정이다. 4각형의 블럭지정이 가능하며 이동명령인 'hjkl' 로 원하는 범위를 지정할수 있다.
Shift+v 와 같이 블럭지정을 한후 Shift+G 를 입력하면 현재라인부터 마지막 라인까지가 블럭 지정이 될것이다.


2.2.5.4. 편집(visual block 모드)

일단 vim 의 visual 블럭 지정 기능을 이용해서 편집하기 원하는 블럭을 지정했다면, 각종 편집명령을 이용해서 복사, 붙이기, 삭제 작업이 가능하다. 블럭을 지정한 상태에서 아래의 명령을 이용해서 편집을 하면 된다. 명령어는 기본적으로 none visual block 모드의 편집 명령어과 같다.

표 7. 편집(복사, 삭제, 붙이기)

y 지정된 블럭을 복사한다.
p 복사된 블럭을 현재라인(커서) 아래에 붙인다.
d 지정된 블럭을 삭제한다.
dd 현재라인을 삭제한다.


2.3. ex 모드

2.3.1. 찾기/치환

vim 의 기능중 가장편리한 기능으리면 뭐니뭐니 해도, 정규표현식을 이용한 강력한 찾기기능과 치환기능이라고 할수 있을것이다. 물론 다른 대부분의 에디터들도 찾기기능과 치환기능을 제공하긴 하지만, vim 의 기능은 다른 에디터들에 비해서 정말로 독보적인 편리함과 강력함을 제공한다. vi 사용자가 다른 에디터로 넘어가기 힘든이유중 가장큰 이유가, 바로 "키를 이용한 방향입력" 과 "찾기 및 치환" 기능 때문이다.

사실 찾기 치환의 기능을 제대로 이해하고 사용하기 위해서는 정규표현식(regular expression) 에 대한 이해가 필요로 하는데, 이것은 다음의 사이트를 참조하기 바란다. 정규 표현식의 간략한 소개

먼저 찾기 기능에 대해서 알아보겠다. 찾기기능은 ':/패턴/' 를 이용 하면된다. 찾기 원하는 문자혹은 패턴을 입력하고 엔터키를 누르면 현재 커서위치에서 가장 가까운 곳에 위치한 문자열로 커서를 이동시킨다(문서 아래방향으로). 다음 문자열을 찾기를 원한다면 'n'키를 누르면 된다. 문서에서 가장 마지막에 이르르게 되면, 문서의 가장처음부터 다시 찾기 시작한다. 'Shift+n' 을 이력하면 반대 방향(문서의 위쪽으로)으로 찾기를 시작한다.

치환이야 말로 vim 의 꽃이라고 할수 있다. :[범위]s/[oldpattern]/[newpattern]/ 의 형식으로 사용하면 된다. 범위 지정은 visual block 을 이용할수도 있으며, 직접 범위를 입력할수도 있다. visual block 를 이용한 치환은 visual block 를 지정한다음 ':' 를 입력해서 ex 모드로 넘어가면 된다. 그리고나서 ':'<,'>s/[oldpattern]/[newpattern/' 과 같은 방법으로 치환하면 된다.

visual block 를 사용하지 않고 직접범위를 입력할수도 있다. :[시작],[마지막]s/[old]/[new]/ 식으로 범위를 지정하면 된다. 여기에는 몇가지 지정된 범위를 위한 특수 기호들이 있다. '%' 는 전체문서(처음부터 끝까지), '.' 은 현재, '$' 은 마지막 을 나타낸다. 숫자를 입력할경우 숫자는 라인을 나타낸다. 다음은 간단한 사용예이다.

# 문서 처음부터 마지막까지의 char 를 _char_ 로 치환한다. 
:%s/char/_&_/g

# 현재(커서위치)부터 마지막까지의 char 를 _char_ 로 치환한다.
:.,$s/char/_&_/g

# buf_.*[255], buf_in[255], buf_get[255] 와 같은 문자열을 hello 로 변경한다.  
:1,10s/buf_.*\[255\]/hello/g
				
마지막에 쓰인 'g' 는 global 이다. 즉 해당 라인 전체에 걸쳐서 검색후 치환한다. 'g' 를 사용하지 않을경우 라인에서 처음에 검색된 문자만 치환하고 다음 라인으로 넘어간다.


2.3.2. 파일 저장, 열기, 종료

파일열기의 경우 vi 를 실행시킬대 명령행 옵션으로 열기가 가능하다. 또한 vi 를 이미 실행 시킨후에도 명령모드에서 명령을 입력함으로 파일을 열수 있다. 열고자 하는 파일이 이미 존재할경우에는 존재하는 파일이 열리고, 열고자 하는 파일이 존재하지 않을경우 새로운 파일이 만들어진다.

표 8. 저장,열기,종료

:e [filename] filename 으로 파일열기
:q, :q!, :wq 종료, 강제종료, 저장후 종료
:w, :w [filename] 현재파일명으로 저장, filename 로 저장
:<범위>w [filename] 지정한 범위만 다른 파일로 저장
:e [filename] filename 을 편집하기 위해서 연다
ZZ 지금파일을 저장하고 vim 을 종료한다.
:f 현재 작업중인 파일의 이름과, 라인수를 출력한다

3. 개발자를 위한 vim 사용팁

3.1. 화면 나누기

vim 은 수평나누기와 수직나누기를 제공한다. 수평나누기는 ":split [파일이름]" 수직나누기는 "vs [파일이름]" 으로 나눌수 있다. 파일이름을 지정한 경우, 새로 만들어진 창에는 파일이름 을 가지는 파일이 열리고, 파일이름을 지정하지 않을경우 똑같은 파일이 열린다. 이 기능은 현재 파일의 다른 부분을 참조하고 싶을때 유용하게 사용할수 있다(참조하는 부분으로 이동하기 위해서 왔다갔다 하지 않아도 되므로). 또한 ":10split [파일이름]", "10vs [파일이름]" 등으로 창의 크기를 조절해 줄수도 있다. 창 나누기는 2개 이상 나누기도 가능하다.

이렇게 창을 분할시켜 놓으면 쏘쓰를 참조하기도 편하고, 무엇보다 편집(삭제,복사,붙이기)가 가능하므로 훨씬더 작업을 수월하게 할수 있다.


3.1.1. 화면 이동

명령 모드에서 CTRL+ww 를 입력하면 된다. 그러면 아래창으로 이동한다. 임의로 이동하기 위해서는 Ctrl+w 를 입력한 상태에서 이동명령[hjkl]를 이용하면 원하는 방향으로 창이동이 가능하다.


3.1.2. 파일 네비게이션

vim 6.0 부터는 파일네비게이션 기능이 존재합니다. 예를들어 vi 로 파일을 열때 파일을 디렉토리로 지정하면 해당디렉토리의 내용이 네비게이션 되고, 디렉토리 이동및 파일 선택이 가능하다.

	
vi ./   # 현재 디렉토리내용을 네비게이션 해준다. 
				


3.2. 파일 네비게이션 바 만들기

윈도우의 울트라 에디트와 같은 프로그램을 보면 왼쪽에 파일네비게이션이 있어서 원하는 파일을 바로 선택해서 편집하는 기능이 있다. vim 으로도 이러한 기능을 구현할수 있다. 이것은 vim 의 file navigation 기능과 창나누기 기능을 이용해서 구현하면 된다.

vi 가 실행되 상태에서 수직창 나누기 기능을 이용해서 ":20vs ./" 명령을 내려보자 그럼 그림과 같이 오른쪽에 파일 네비게이션 바가 생김을 알수 있다.

그림 1. 파일네비게이션을 만든 화면

이제 열기를 원하는 파일위치에 가서 shift+o 를 입력해보자, 그럼 옆의 편집창에 새로운 파일이 열리는것을 알수 잇을것이다. 여기에 더해서 편집장을 split 로 나누면, 여러개의 파일을 오가면서 편집이 가능해질 것이다.


3.3. 여러개의 파일 편집하기

위에서는 창나누기를 이용한 여러개의 파일편집에 대해서 알아봤는데, 또다른 방법이 있다. 처음에 vim 을 통하여 여러개의 파일을 open 하고 여러개의 열린 파일을 이동하면서 편집하는 방법이다. 먼저 vim을 다음과 같이 실행시킨다.

 
[yundream@localhost test]# vim file1.txt file2.txt ...
			
그러면 처음 화면은 file1.txt 편집화면일것이다. 2번째 파일인 file2.txt 편집화면으로 넘어가길 원한다면(앞에 있는 파일 편집)
:n
			
file2.txt 에서 file1.txt 를 편집하길 원한다면(뒤에 있는 파일편집)
:e#
			
split 를 이용해서 여러개의 파일을 편집할때와 마찬가지로, 각종 편집기능(복사,삭제,붙이기)이 서로 공유되므로 편하게 작업이 가능하다.


3.4. 잠시 쉘로 나가기

보통 vim상에서 쉘명령어를 실행시키기 위해서 :![명령어] 를 사용하는데, 이것 보다는 Ctrl+z 를 이용해서 쉘로 빠져나가서 작업하는게 더 편하다. sehll 이 job control 기능을 이용한것으로, 쉘에서 원하는 작업을 수행하후 fg 명령을 이용해서 다시 vi 편집 상태로 되돌아 올수 있다. vim 사용자를 보면 가끔 쉘작업을 하기 위해서 vim 을 아예 종료 시켜서 쉘로 빠져나간 다음에 작업을 하고 vim 을 다시 실행시키는 경우가 있는데, 이제는 그럴필요가 없이 좀더 편하게 작업을 할수 있을것이다.


3.5. 선택된 block 를 다른 이름으로 저장하기

split 기능을 이용해서 창을 나누고, 원하는 블럭을 선택해서 복사한다음에, 새로만든창에 가져다 붙이기를 하면 된다.

그러나 이방법은 조금 복잡한 감이 없잖아 있다. 이럴때는 블럭을 선택해서 :'<,'>w [파일명] 하면 좀더 간단하게 원하는 작업을 수행할수 있다.


3.6. 빠른 괄호 이동

C나 C++ 을 사용하다보면 제어문이나 함수에서 많은 괄호('{','(')를 만나게 된다. 이때 괄호의 제일 마지막으로 이동하고 싶을때가 있을것이다. 이럴때는 ']}' 를 사용하면 된다. '[{' 를 사용하면 괄호의 처음으로 이동한다.


3.7. 위치 마크(mark)하기

일종의 북마크기능으로 자주참조할만한 라인을 마킹해두고 필요할때 간단히 해당 마킹지역으로 이동하기 위해서 사용한다. 마킹을 위해서는 명령모드에서 m키를 눌러서 마킹모드로 들어가면 된다. 그리고 영문 [a-zA-Z]키중 아무거나 눌러주면 된다. 만약 a를 눌러주었다면, 현재라인은 a이름으로 마킹된다. 이후 작업을하다가 a마킹라인으로 가고 싶다면 'a 해주면된다. 이상태에서 원래라이으로 되돌아가고 싶다면 ''를 눌려주면 된다.

물론 다중마킹도 허용한다. 마킹할수 있는 문자는 단일영문자이다. 마킹에 사용되는 영문자는 대소문자를 구분함으로 최대마킹가능한 수는 27*2가 될것이다.


3.8. 폴더(접기) 기능이용하기

vim 6.0 에 새로이 포함된 좋은 기능으로 코드의 특정영역을 접을수 있다. 그럼으로 코드를 분석할때 쓸데 없는 부분을 감춰줘서 좀더 편하게 분석이 가능합니다. visual block 를 이용해서 원하는 영역을 선택한다음 :zf 를 이용하면 해당영역이 접힌다. :zo 를 사용하면 접힌영영을 원상태로 복구할수 있고 :zc 를 사용하면 해당영역을 다시 접을수 있다. 또한 다중 접기를 허용해서 접근구역을 다시 접을수도 있다.


3.9. 간단한 man 페이지 참조

vim 을 이용 코딩중에 함수의 프로토 타입이 생각나지 않을때 주로 man page 를 참조하게 된다. 보통은 창을 하나따로 띄워서 그곳에서 man page 를 보는데, 코딩중에 간단하게 해당 함수에 대한 man page 를 볼수 있다. man page 를 원하는 함수 위로 커서를 옮긴다음 Shift + k 를 입력하면 함수의 man page 가 뜰것이다. 'q' 를 입력해서 man page 를 종료시키면 원래의 vim 화면으로 되돌아온다.


3.10. 함수/변수명 자동완성

코딩중에 가장 범하기 쉬운 잘못중의 하나가 변수명및 함수명 오타일것이다. 또 변수명이 기억이 잘 나지 않아서 처음 선언한곳을 다시 확인하는 작업역시 코딩을 매우 번거롭게 한다. 이때 함수 자동완성 기능을 이용하면 이러한 염려들을 줄일수 있다.

int client_sockfd 라고 변수 선언을 했다고 하자. 코딩중에 client_sockfd 를 쓸일이 있다면 cli^p 를 입력해보자. 그러면 변수 이름이 자동으로 완성되는것을 볼수 있을것이다. ^p는 Ctrl+p 이다.


3.11. ctags 를 이용한 쏘쓰 분석

쏘쓰를 분석하는데 있어서 가장 중요한 것은 역시 함수를 분석해서, 함수가 어떤일을 하는지 알아내는 것이다. ctags 를 이용하면 이러한 쏘쓰 분석작업을 좀더 수월하게 할수 있다. ctags 와 관련된문서는 ctags 를 이용한 쏘쓰 분석 을 참고하기 바란다.


3.12. 자동들여쓰기

프로그래밍 할때 indent 는 쏘쓰코드를 보기좋게 만들기 위한 필수 사항이다. 보통 tab 을 주로 쓰는데,

:set ai
			
명령을 이용하면 자동적으로 indent (auto indent) 를 적용시켜주므로, 좀더 코딩에만 집중할수 있도록 도와준다.
:set noai 
			
명령을 사용해서 auto indent 상태를 해제할수 있다.

요즘의 vim 은 기본적으로 auto indent 상태이므로, 별다른 설정없이 편하게 사용가능하다. 그러나 웹에서 가져다 붙이기를 할때 여기에 auto indent 가 적용되어서 것잡을수 없이 tab 이 들어가는 경우가 생길때도 있는데, 이럴때 set noai 를 이용해서 auto indent 를 해제하고 가져다 붙이기를 하면 된다.


3.13. 탭사이즈 조정하기

쏘쓰에서 indent 를 위해서 주로 탭을 사용하는데, 보통 이 탭 사이즈는 8로 되어 있다. 그런데 8이란 탭사이즈가 때로는 너무 커서, 쏘쓰가 화면밖으로 나가서 오히려 쏘쓰 보기를 어렵게 만들때도 있다. 이럴때 는 탭사이즈를 줄여야 하는데 다음과 같은 명령을 통해서 탭사이즈 변경이 가능하다.

:set ts=4
			


3.14. 라인 넘버링

코딩하다보면 라인넘버가 있으면 할때가 있다. 그럴때는

:set nu 
			
하면 된다.

그림 2. 라인 넘버링

라인넘버를 없애고 싶다면,
:set nonu
			
하면 된다.


3.15. 코드를 HTML로 저장하기

vim 은 또한 코드를 HTML 형태로 저장하는 기능을 가지고 있다. 이 기능을 이용하면 syntax highlight 된 상태 그대로 HTML로 변환이 가능하다. 쏘쓰코드의 예제를 만들어서 웹상에 올리고자 할때 유용하게 사용할수 있는 기능이다.

:so $VIMRUNTIME/syntax/2html.vim 
			


3.16. vim 설정파일 만들기

지금까지 우리는 다양한 설정을 통해서 vim 을 좀더 쉽게 사용하는 방법을 알아 보았다. 그런데, 탭사이즈를 적용하기 위해서 vim 을 실행시킬때 마다 ":set ts=4" 이런식으로 하면 작업이 매우 귀찮을것이다. 이럴때는 vim 을 위한 설정파일을 만들어서, vim 이 시작할때 설정파일을 읽어들여서 환경이 자동으로 설정되도록 하면된다.

자기의 계정(Home) 디렉토리에 보면, .vimrc 라는 파일이 존재 할것이다. (존재하지 않는다면 만들도록한다) 이것이 설정파일로 아래와 같은 방법으로 자기가 원하는 내용을 설정하면 된다.

set ts=4
set nu
			

블로그 이미지

유효하지않음

,

ANT

Programming Language/Java 2008. 11. 24. 11:34

[출처] 생각이...??

설치하기 

Linux(ubuntu)에서는 아래 한줄로 내려받기 + 설치 + 환경설정 끝.

  1. sudo apt-get install ant

      

윈도우에서는

  1. 다운로드 받는다.
    http://ant.apache.org/
  2. 압축을 풀어서 적당한 위치로 이동한다.
    C:\Program Files\apache-ant-1.7.1\     이정도 위치에
  3. 시작 > 제어판 > 시스템 > 고급 > 환경변수 로 들어가서
    - PATH 에 C:\Program Files\apache-ant-1.7.1\bin 추가
    - JAVA_HOME 변수 추가 (이미 설치된 자바의 위치 등록)

 

다음 명령으로 잘 설치 되었는지 확인 한다.

ant --version

 

 

SVN 사용하기

 

사이트 : http://subclipse.tigris.org/svnant.html

            http://svnkit.com/kb/user-guide-svnant.html                    

 

  1. 다운 로드    
    SvnAnt 1.2.x 버전을 다운 받는다.

     

  2. 설치
    /lib/*.jar 파일을 $ANT_HOME/lib 로 Copy 하면 끝.

 

예)

  1. <taskdef resource="org/tigris/subversion/svnant/svnantlib.xml"/>
    
  2. <target ..... >
        <svn username="guest" password="">
          <checkout url="http://subclipse.tigris.org/svn/subclipse/trunk/svnant/" revision="HEAD" destPath="svnant" />
        </svn>
    </target>
    

 

위 소스중 다음의 태그를 포함시키지 않으면, "failed to create task or type svn"를 만나게 될 것이다.

<taskdef resource="org/tigris/subversion/svnant/svnantlib.xml"/>


ㅇ Update

  1. <svn>
    <update dir="${target.web}" />
    </svn>


ㅇ commit

  1. <svn username="${svn.userid}" password="${svn.userpwd}">
        <commit message="변경 사항" dir="${target.web}" recurse="true" />
    </svn>


ㅇ auto file add

  1. <svn >
    <add>
    <svnFileSet dir="${target.web}">
    <svnUnversioned/>
    </svnFileSet>
    </add>
    </svn>


ㅇ 더 자세한 내용은

사이트에 직접 상세문서가 없다(나만 못찾는가?) .

antsvn을 설치하기 위해 받은 파일을 열어보면 doc 라는 디렉토리에서 상세 문서를 볼 수 있다


*.jar 를 classpath 로 잡기


웹서버 프로그램 컴파일시 /WEB-INF/lib/*.jar 파일을 classpath로 참조 하게 되는데 ant build시 일일이 적어 줘야 하는 부담이 있다.

특히나, cvs나 svn 같은 버젼관리 프로그램으로 다운받은 프로그램을 컴파일 할 경우 일일이 작성해서 만들 수 는 없는것이다.

그래서 다음과 같은 방법을 통해 동적인 참조를 만들어 본다.


컴파일시 다음과 같이 사용된다.

  1. <target name="compile" >
        <javac destdir="${svn.dest}/WEB-INF/classes" srcdir="${svn.dest}/WEB-INF/src" >
    <classpath >
  2. <fileset dir="${svn.dest}">
        <include name="**/WEB-INF/lib/*.jar" />
        <include name="**/WEB-INF/lib/.*.zip" />
    </fileset>
  3. </classpath> </javac>
    </target>


디렉토리가 없을 조건의 경우 만들기


ㅇ 디렉토리가 없으면 true가 되는 조건

  1. <condition property="check_dir" >
        <not>
            <available file="${svn.dest}/WEB-INF/classes"/>
        </not>
    </condition>


ㅇ위 조건이 참일 경우 디렉토리 만들기

  1. <target name="make_dir_classes" if="check_dir">
    <mkdir dir="${svn.dest}/WEB-INF/classes" />
    </target>


파일들을 이동


ㅇ 파일을 복사

  1. <copy todir="${project.dest}" file="some.file" />


ㅇ파일들을 복사

  1. <copy todir="${project.dest}" > <!-- to dir -->
    <fileset dir="${svn.dest}" /> <!-- from -->
    </copy>


ㅇ 일부 파일만 복사

  1. <copy todir="${project.dest}/WEB-INF/classes/" >
    <fileset dir="${project.dest}/WEB-INF/src/" includes="*.xml" />
    <fileset dir="${project.dest}/WEB-INF/src/" includes="*.propertie"/>
    </copy>


네이티브 명령어 실행

운영체제에 적절한 명령어를 실행 할 경우 <exec> 태그를 사용

네이티브 명령어
(testdb라는 데이타베이스 생성)

  1. psql -U postgres -c 'create database testdb'


ant에서는

  1. <exec executable="/usr/bin/psql"
    dir="." >
    <arg line="-U postgres -c 'create database testdb'" />
    </exec>


Ant Task를 사용하여 Java Class 이용

 
ant 명령어로 처리 할 수 없는 좀더 복잡한 로직에 대해서는 직접 java class를 만들어 이용 할 수 있다.

먼저 ant 소스부터 보자

  1. <target name="change_context_name" >
    <taskdef name="ccn" classname="com.action.ChangeContextName"/> <!-- Class 정의 -->
    <ccn context_name="testsrv"
    file="**/WEB-INF/sun-web.xml" /> <!-- 사용 -->
    </target>


ㅇ <taskdef /> 태그를 이용하여 사용자가 만든 클래스를 사용할수 있도록 정의

ㅇ <ccn />은 <taskdef /> 태그에서 정의된 name이다. 사용자가 임의로 바꿔 사용할 수 있다.


ChangeContextName 를 열어 보면 다음과 같다

  1. package com.action;

    public class ChangeContextName extends org.apache.tools.ant.Task
    {
        String context_name;
        public String getContext_name()
        {
           return context_name;
        }
        public void setContext_name(String context_name)
        {
           this.context_name = context_name;
        }

        public void execute()
        {
           System.out.println("실행이 되었다...... ^^");
           System.out.println("컨텍스트명["+this.context_name+"]");
        }
    }


ㅇ Ant Task가 되려면

  1. org.apache.tools.ant.Task를 상속 받아야 한다.
  2. public void execute(){ .... } 에서 실행이 된다
  3. attribute값을 전달 받으려면
    public void setXXXX(String val) 와 같이 사용한다.


out of memory

ant 구동중 out of memory를 만날경우

다음의 내용을 환경변수에 추가 하면된다.

  1. ANT_OPTS=-Xmx512M


사용자에게 입력받기

<input>태그를 이용하여 사용자로부터 값을 입력받도록 한다

  1. <target name="get-input">
    <input message="작업할 디렉토리명은?"
    addproperty="target.name" />
    <echo message="입력받은값 > [${target.name}]"/>
    </target>


ant-contrib사용(조건문 사용하기)

ㅇ 설치

http://ant-contrib.sourceforge.net/ > download page 접속 > ant-contrib package 클릭 > ant-contrib-1.0b3-bin.zip 다운로드
압출풀면 ant-contrib-1.0b3.jar 파일이 나옴
이파일을 ANT_HOME/lib/ 에 copy 하면 끝.

ㅇ 선언문

<taskdef resource="net/sf/antcontrib/antcontrib.properties" />

정의 해 주면 사용가능 해 진다

ㅇ 사용 태그

<if> <switch> <foreach> <trycatch> 태그가 사용 가능하다.

  • switch
  1. <switch value="${input.value}">
        <case value="1">
            <echo message="1의 경우..."/>
        </case>

        <default>
            <echo message="이도저도 아닌경우.."/>
        </default>
    </switch>
  • if
  1. <if> 
        <equals arg1="${foo}" arg2="bar" /> 
        <then> 
           <echo message="The value of property foo is bar" /> 
        </then> 
    <else> 
           <echo message="The value of property foo is not bar" /> 
    </else> 
    </if> 

  • foreach
  • tyrcatch
블로그 이미지

유효하지않음

,
 . exporting table NG01_REPORT_INFO
EXP-00056: ORACLE error 24801 encountered
ORA-24801: illegal parameter value in OCI lob function
. . exporting table NG01_REPORT_LINK 0 rows exported
. . exporting table NG01_SCORE_OF_INFO 72 rows exported
EXP-00002: error in writing to export file
EXP-00056: ORACLE error 1403 encountered
ORA-01403: no data found
. . exporting table NG01_SMS_LOG_INFO
EXP-00015: error on row 96 of table NG01_SMS_LOG_INFO, column SLI_TEXTMSG, datatype 1
EXP-00002: error in writing to export file
EXP-00002: error in writing to export fileerror closing export file 20081120_qes_bsc.dmp
EXP-00000: Export terminated unsuccessfully
$ . . exporting table NG01_PROTEST 142 rows exported
ksh: .: not found
$ . . exporting table NG01_QNA 0 rows exported
ksh: .: not found
$ . . exporting table NG01_REPORT_COMMENT 20138 rows exported
ksh: .: not found
$ . . exporting table NG01_REPORT_INFO
ksh: .: not found



exp qes_bsc/qes_bsc file=(qes_bsc1.dmp,qes_bsc2.dmp,qes_bsc3.dmp) filesize=2G

데이터량이 많은 DB에 대해 export시 다음과 같은 오류가 발생하면 위처럼 dump파일을 여러개 만들면 된다.

블로그 이미지

유효하지않음

,
package com.util.mail;   
 
import java.security.Security; 
import java.util.Date; 
import java.util.Properties;   
 
import javax.mail.Authenticator; 
import javax.mail.Message; 
import javax.mail.MessagingException; 
import javax.mail.PasswordAuthentication; 
import javax.mail.Session; 
import javax.mail.Transport; 
import javax.mail.internet.InternetAddress; 
import javax.mail.internet.MimeMessage;   
 
import org.apache.log4j.Logger;   
 
 public static final void sendMail(String to, String title, String content) { 
  try { 
     Security.addProvider(new com.sun.net.ssl.internal.ssl.Provider()); 
   final String SSL_FACTORY = "javax.net.ssl.SSLSocketFactory"; 
   Properties props = System.getProperties(); 
   props.setProperty("mail.smtp.host", "smtp.gmail.com"); 
   props.setProperty("mail.smtp.socketFactory.class", SSL_FACTORY); 
   props.setProperty("mail.smtp.socketFactory.fallback", "false"); 
   props.setProperty("mail.smtp.port", "465"); 
   props.setProperty("mail.smtp.socketFactory.port", "465"); 
   props.put("mail.smtp.auth", "true"); 
   final String username = "your@gmail.com"; 
   final String password = "your password"; 
   Session session = Session.getDefaultInstance(props, 
     new Authenticator() { 
      protected PasswordAuthentication getPasswordAuthentication() { 
       return new PasswordAuthentication(username, 
         password); 
      } 
     });   
 
   // -- Create a new message -- 
   Message msg = new MimeMessage(session);   
 
   // -- Set the FROM and TO fields -- 
   msg.setFrom(new InternetAddress(to)); 
   msg.setRecipients(Message.RecipientType.TO, InternetAddress.parse( 
     to, false)); 
   msg.setSubject(title); 
   msg.setText(content); 
   msg.setSentDate(new Date()); 
   Transport.send(msg);   
 
  } catch (MessagingException e) { 
   _log.error(e); 
     }   
  } 
}

  1. //set CLASSPATH=%CLASSPATH%;activation.jar;mail.jar
  2. import javax.mail.*;
  3. import javax.mail.internet.*;
  4. import java.util.*;
  5.  
  6. public class Mail
  7. {
  8.          String  d_email = "iamdvr@gmail.com",
  9.             d_password = "****",
  10.             d_host = "smtp.gmail.com",
  11.             d_port  = "465",
  12.             m_to = "iamdvr@yahoo.com",
  13.             m_subject = "Testing",
  14.             m_text = "Hey, this is the testing email using smtp.gmail.com.";
  15.     public static void main(String[] args)
  16.     {
  17.                 String[] to={"XXX@yahoo.com"};
  18.                 String[] cc={"XXX@yahoo.com"};
  19.                 String[] bcc={"XXX@yahoo.com"};
  20.                 //This is for google
  21.                         Mail.sendMail("venkatesh@dfdf.com","password","smtp.gmail.com","465","true",
  22. "true",true,"javax.net.ssl.SSLSocketFactory","false",to,cc,bcc,
  23. "hi baba don't send virus mails..","This is my style...of reply..
  24. If u send virus mails..");             
  25.     }
  26.  
  27.         public synchronized static boolean sendMail(String userName,String passWord,String host,String port,String starttls,String auth,boolean debug,String socketFactoryClass,String fallback,String[] to,String[] cc,String[] bcc,String subject,String text){
  28.                 Properties props = new Properties();
  29.                 //Properties props=System.getProperties();
  30.         props.put("mail.smtp.user", userName);
  31.         props.put("mail.smtp.host", host);
  32.                 if(!"".equals(port))
  33.         props.put("mail.smtp.port", port);
  34.                 if(!"".equals(starttls))
  35.         props.put("mail.smtp.starttls.enable",starttls);
  36.         props.put("mail.smtp.auth", auth);
  37.                 if(debug){
  38.                 props.put("mail.smtp.debug", "true");
  39.                 }else{
  40.                 props.put("mail.smtp.debug", "false");         
  41.                 }
  42.                 if(!"".equals(port))
  43.         props.put("mail.smtp.socketFactory.port", port);
  44.                 if(!"".equals(socketFactoryClass))
  45.         props.put("mail.smtp.socketFactory.class",socketFactoryClass);
  46.                 if(!"".equals(fallback))
  47.         props.put("mail.smtp.socketFactory.fallback", fallback);
  48.  
  49.         try
  50.         {
  51.                         Session session = Session.getDefaultInstance(props, null);
  52.             session.setDebug(debug);
  53.             MimeMessage msg = new MimeMessage(session);
  54.             msg.setText(text);
  55.             msg.setSubject(subject);
  56.             msg.setFrom(new InternetAddress("p_sambasivarao@sutyam.com"));
  57.                         for(int i=0;i<to.length;i++){
  58.             msg.addRecipient(Message.RecipientType.TO, new InternetAddress(to[i]));
  59.                         }
  60.                         for(int i=0;i<cc.length;i++){
  61.             msg.addRecipient(Message.RecipientType.CC, new InternetAddress(cc[i]));
  62.                         }
  63.                         for(int i=0;i<bcc.length;i++){
  64.             msg.addRecipient(Message.RecipientType.BCC, new InternetAddress(bcc[i]));
  65.                         }
  66.             msg.saveChanges();
  67.                         Transport transport = session.getTransport("smtp");
  68.                         transport.connect(host, userName, passWord);
  69.                         transport.sendMessage(msg, msg.getAllRecipients());
  70.                         transport.close();
  71.                         return true;
  72.         }
  73.         catch (Exception mex)
  74.         {
  75.             mex.printStackTrace();
  76.                         return false;
  77.         }
  78.         }
  79.  
  80. }


우선 smtp를 지원하는 메일서비스만 할 수 있습니다.
naver는 지원하긴 하지만, 조낸 써야지 smtp를 사용할 수 있습니다.
저는 일반사용자인데 으뜸사용자가 되야하는 듯 합니다.
그래서 그냥 지원해주는 gmail이랑 daum메일로 테스트를 해봤습니다. 잘 되는군요.
기존에 25포트가 디폴트로 메일을 사용했는데 보안 때문에 SSL을 사용하고, smtps라는 프로토콜로 465번포트로 하는군요.
이건 좀 더 공부를 해봐야할 듯 싶네요. 그냥 기존의 ssl을 사용하지 않는 메일은 host랑 id랑 password만 지정해주면 돼요.


우선 설정파일입니다.
applicationContext.xml

<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans" xmlns:xsi=http://www.w3.org/2001/XMLSchema-instance
   
xmlns:p="http://www.springframework.org/schema/p"
   
xmlns:context=http://www.springframework.org/schema/context
   
xsi:schemaLocation="
      http://www.springframework.org/schema/beans
      http://www.springframework.org/schema/beans/spring-beans-2.5.xsd
      http://www.springframework.org/schema/context
     http://www.springframework.org/schema/context/spring-context-2.5.xsd"
>
   
<context:component-scan base-package="mailtest" />


   
<!-- 일반용  
    <bean id="mailSender"
        class="org.springframework.mail.javamail.JavaMailSenderImpl"
        p:host="STMP서버주소"
        p:username="아이디"
        p:password="비밀번호" />
    -->

   
   
<!-- gmail, hanmail 용 -->
   
<bean id="mailSender"
       
class="org.springframework.mail.javamail.JavaMailSenderImpl"
       
p:host="한메일: pop.hanmail.net, 지메일:smtp.gmail.com"
       
p:port="465"
       
p:protocol="smtps"
       
p:username="아이디"
       
p:password="비밀번호">
       
<property name="javaMailProperties">
           
<props>
               
<prop key="mail.smtps.auth">true</prop>
               
<prop key="mail.smtps.startls.enable">true</prop>
               
<prop key="mail.smtps.debug">true</prop>
           
</props>
       
</property>
   
</bean>


   
<bean id="templateMessage"
       
class="org.springframework.mail.SimpleMailMessage"
       
p:from="송신자 주소"
       
p:to="수신자 주소"
       
p:subject="안녕!" />
   </beans>






templateMessage는 임시로 메세지를 지정해주는 것으로 미리 지정할 껀 지정하는 겁니다.
물론, 나중에 java코드에서 수정이 가능합니다.

서비스부분입니다.

MailTestService.java


package mailtest;

import org.springframework.beans.factory.annotation.Autowired; import org.springframework.mail.MailSender; import org.springframework.mail.SimpleMailMessage; import org.springframework.stereotype.Service;
@Service public class MailTestService {     @Autowired     private MailSender mailSender;  
   
@Autowired     private SimpleMailMessage simpleMailMessage;       public void sendEmail()     {
        SimpleMailMessage msg = new SimpleMailMessage(this.simpleMailMessage);         msg.setText("난 종천이라고해!");         this.mailSender.send(msg);     } }



저기서 simpleMailMessage를 받아와서 text만 설정해줍니다. 저기서 msg.setTo하면 수신자도 설정할 수 있죠. 그리고 그냥 send메소드만 호출해주면 메일이 전송됩니다.

package mailtest;

import org.springframework.context.ApplicationContext; import org.springframework.context.support.ClassPathXmlApplicationContext;
public class MailTest {     public static void main(String[] args)     {         String configLocation = "applicationContext.xml";         ApplicationContext context = new ClassPathXmlApplicationContext(configLocation);         MailTestService mailTestService = (MailTestService) context.getBean("mailTestService");         mailTestService.sendEmail();     } }

더욱 심화된 기능은 reference를 참조하세요
http://static.springframework.org/spring/docs/2.5.x/reference/mail.html

블로그 이미지

유효하지않음

,

[ This explains how to use gmail to send emails in php using PHPMailer]
1 Download PHPMailer from http://phpmailer.sourceforge.net
2 Extract to folder phpmailer
3 Create a file email.php
4 Paste this code and change the values in blue as you need (I modified the sample code given on the PHPMailer homepage)

IsSMTP(); // send via SMTP
$mail->SMTPAuth = true; // turn on SMTP authentication
$mail->Username = "username@gmail.com"; // SMTP username
$mail->Password = "password"; // SMTP password
$webmaster_email = "username@doamin.com"; //Reply to this email ID
$email="username@domain.com"; // Recipients email ID
$name="name"; // Recipient's name
$mail->From = $webmaster_email;
$mail->FromName = "Webmaster";
$mail->AddAddress($email,$name);
$mail->AddReplyTo($webmaster_email,"Webmaster");
$mail->WordWrap = 50; // set word wrap
$mail->AddAttachment("/var/tmp/file.tar.gz"); // attachment
$mail->AddAttachment("/tmp/image.jpg", "new.jpg"); // attachment
$mail->IsHTML(true); // send as HTML
$mail->Subject = "This is the subject";
$mail->Body = "Hi,
This is the HTML BODY "
; //HTML Body
$mail->AltBody = "This is the body when user views in plain text format"; //Text Body
if(!$mail->Send())
{
  echo "Mailer Error: " . $mail->ErrorInfo;
}
else
{
  echo "Message has been sent";
}
?>

5 Open the file class.smtp.php in phpmailer directory
6 Paste this code
$host = "ssl://smtp.gmail.com";
$port = 465;
before the line 104 #connect to the smtp server
Hint: Search for #connect
7 Open this page in browser and it will send the email using GMail.

Hint: When you want to email the details from a form, set the variables using the form variables.
eg. $mail->Username=$_POST['email']


[원문] http://deepakssn.blogspot.com/2006/06/gmail-php-send-email-using-php-with.html
블로그 이미지

유효하지않음

,