글쓴이 : 푸우     날짜 : 08-03-01 19:09     조회 : 486    


요즘 통 글을 안 올렸네요.
요즘 회사일로 정신이 없네요.
죄송하구요. ^^; 
아무튼 이번에는 UNIX/LINUX의 Deamon 프로세스 만드는 것에 대해 정리해 보도록 하겠습니다.
 
1. Daemon이란?
 
뭐 이글을 관심이 있어서 읽고 계시는 분 중에 Daemon이 뭔지를 모르시는 분은 없겠지만...
그래도 한번 정리해 봅니다.
Daemon의 뜻 자체는 "악마", "악령", "귀신"과 같이 좀 무시무시 합니다.
하지만 Daemon의 어원은 신화에서 신과 인간사이의 초자연적인 영적존재로서의 수호신에서 나왔다고 합니다. 뭐 좋은쪽으로 생각하죠.
컴퓨터 상에서 Daemon은 겉으로는 보이지 않지만 항상 뒤에서 뭔가를 계속해서 수행해 주는 프로그램을 말합니다. 예로 httpd, ftpd, telnetd 등...
이런면에서 왜 Daemon이라는 이름 지었는지 이해가 가네요.
윈도우즈에서는 Daemon이라는 용어가 마음에 들지 않았는지 아니면 뭔가 꼭 튀게 해야한다고 생각했는지 몰라도... UNIX/LINUX의 Daemon과 같은 역할을 하는 프로그램을 Service 라고 합니다.
"데몬"은 이름에 뭔가 철학을 담아 지은것 같은데... "서비스"... 참 단순해서 좋긴 좋네요. ㅋㅋ  ^^;
 
Daemon 프로그램이 되려면 몇가지 특징을 갖추어야 하지만 가장 중요한 것은 "OS가 부팅되면 사용자의 개입없이 실행될 수 있을 것"입니다.
이 말은 다시 말해 누군가가 로그인을 하여 굳이 실행하지 않아도 OS의 init프로세스에 의해 실행될 수 있어야 한다는 이야기 이고 이럴려면 프로그램을 제어하는 터미널(tty)를 갖지 말아야 한다는 것 입니다. 반대로 말하면 누군가 로그인 해서 데몬을 시작시켰다면 로그아웃할 때 해당 데몬은 계속해서 살아 있어야 한다는 말도 됩니다.
 
이제 이러한 특징을 갖는 프로그램을 만드는 방법을 단계별로 알아보도록 하죠.
 
 
2. 로그 아웃시 프로그램 종료되지 않게 하기
 
우선 데몬은 아니더라도 데몬과 비슷하게 수행하면 계속해서 작업을 수행 할 수 있도록 하는 방법에 대해서 알아 보겠습니다.
 
기본 소스는 다음과 같습니다.
 
#include <stdio.h>

int work()
{
        FILE *fp;
        unsigned long count=0;

        fp=fopen("/tmp/daemon.out""wt");
        if(fp==NULL) {
                printf("File Open Error\n");
                return -1;
        }

        while(1){
                sleep(1);
                fprintf(fp, "%lu\n", count);
                fflush(fp);
                fprintf(stdout, "%lu\n", count++);
        }
        fclose(fp);

        return 0;
}

int main(int argc, char *argv[])
{
        work();

        return 0;
}
 
 
위의 프로그램은 간단하니깐 보시면 아시겠지만 main()함수가 수행되면 work()라는 함수를 수행하게 됩니다.
work()함수는 무한루프를 돌면서 1초마다 "/tmp/daemon.out"파일에 카운팅을 기록합니다.
또 표준출력으로도 같은 값을 출력하는 프로그램입니다.
위의 소스를 컴파일하여 daemon이라는 실행파일을 생성했다고 하고 다음의 글들을 작성토록 하겠습니다.
 
자 그럼 로그아웃이 될때 어떤 현상이 일어날지에 대해 한번 알아보도록 하죠.
 
로그아웃하거나 해당 터미널이 끊기게 되면 OS 해당 터미널을 제어단말로 사용하던 모든 프로그램에게 특별한 신호를 보내게 됩니다.
이 신호가 SIGHUP, 즉, Hangup 시그널입니다.
일반적인 프로그램은 이 Hangup 시그널을 받으면 정상종료를 하게 됩니다.
뭐 프로세스가 알아서 정상종료 한다기 보다는 이 시그널을 어떻게 처리하라는 루틴을 구현하지 않은 프로세스는 조용히 OS가 죽이는 것이죠.
 
OS에 SIGHUP을 무시하게 해주는 'nohup'이라는 쉘명령어가 있습니다.
일반적인 사용방법은 다음과 같습니다.
 
#nohup daemon&amp;amp;
 
위의 명령어 중 daemon은 데몬 프로그램의 이름이고 마지막 &는 이 글의 주제와는 상관없지만 백그라운드로 실행해서 프롬프트를 다시 얻기 위함입니다.
이렇게 daemon을 실행한 뒤 로그아웃하거나 단말기를 끊고 다시 접속한 다음 "ps -ef | grep daemon" 명령을 통해 보시면 daemon이 살아 있음을 보실 수 있으실 것 입니다.
또한 "tail -f /tmp/daemon.out" 해서 보시면 살아 있을 뿐 더러 원래의 기능도 정상적으로 수행 하고 있음을 알 수 있습니다.
 
그런데 여기서 원래 daemon은 파일 뿐만 아니라 화면에도 카운팅 번호를 출력하도록 되어 있었는데 위의 명령의 수행 후에는 아래와 같은 메시지만 남기고 나타나지 않습니다.
 
appending output to `nohup.out'<br />
 
이는 nohup 명령어가 daemon의 표준 출력을 현재 경로의 'nohup.out'이라는 파일로 리다이렉트 시켰기 때문입니다.
 
어찌되었건 쉘에서 제공하는 명령어를 통해 데몬과 유사한 기능을 하도록 해 보았네요. 
 
자 이번에는 'nohup'과 같은 기능을 시스템 함수로 구현해 보도록 하겠습니다.
 
골자는 프로그램 내에서 SIGHUP시그널을 무시할 수 있도록 코딩하는 것입니다.
 
 위 함수에 #include <signal.h> 를 포함하고 main함수를 다음과 같이 고칩니다.
 
 
int main(int argc, char *argv[])
{
        signal(SIGHUP, SIG_IGN);

        work();

        return 0;
}
 
 
지금 부터는 work()함수의 표준 출력이 귀찮아 지므로 표준 출력으로 내보는 문장은 적절히 삭제하셔도 좋습니다.  
위의 main()함수는 signal()함수를 통해 SIGHUP시그널을 무시하도록 설정 한 뒤 work()함수를 수행한 것입니다.
 
컴파일 후 테스트는 여러분의 몫으로 하구요.
 
SIGHUP을 무시하는 방법은 아니지만 또 다른 방법이 있는데 이는 프로세스 내에서 자신의 그룹아이디를 바꾸는 것입니다.
 
이는 로그 아웃시 현재 터미널을 제어 단말기로 하고 있는 프로세스에 OS가 SIGHUP시그널을 보낼 때 쉘프로세스의 아이디를 그룹아이디로 갖는 모든 프로세스에게 보낸다는 것에 착안한 것입니다.
 
즉, 프로그램은 특정 쉘프로세스에서 수행되기 때문에 일반적으로 프로세스 그룹아이디는 수행 환경이 되었던 쉘프로세스 아이디를 갖게 되는데 이를 프로세스 내에게 바꾸는 것입니다. 
 
int main(int argc, char *argv[])
{
        int newpgid;

        newpgid = setpgrp();

        work();

        return 0;
}
 
위의 소스에 보이는 setpgrp()함수는 자신의 프로세스 그룹을 자신의 프로세스아이디로 바꿔줍니다.
이렇게 하면 로그아웃시 이 프로세스는 아예 SIGHUP시그널을 받지도 않으므로 종료되지 않습니다.
 
자 여기까지는 데몬 프로그램을 만드는 법이라기 보다는 일반적으로 프로세스에서 일어나는 일과 이들을 처리하는 방법, 그리고 간단히 데몬과 유사한 효과 내기라고 생각하시면 될 듯 싶습니다.
 
 
3. fork에 의한 Daemon만들기
 
 
위에서 이야기 한 방법들도 뭐 잘못된 방법들은 아니지만 일반적으로는 이제부터 이야기 하는 방법으로 주로 데몬을 만듭니다.
main()함수를 다음과 같이 바꾸세요.
 
int main(int argc, char *argv[])
{
        int pid;

        pid=fork();
        switch(pid){
        case -1:
                fprintf(stderr, "Fork Error\n");
                break;
        case 0:         // child
                break;
        default:        // parent
                return 0;
        }

        work();

        return 0;
}
 
위의 main()함수는 프로그램이 시작되자 마자 fork()를 수행해서 자식프로세스는 work()함수를 수행하고 부모프로세스는 종료하게 합니다.
그러면 사실 자식프로세스는 아직 살아 있는데 부모프로세스가 터미널과 연결되어 있었는데 사라지게 됩니다. 고로 자식 프로세스는 제어단말기를 가지지 않게 되고 부모가 없으므로 고아프로세스가 되었네요.
이렇게 고아프로세스가 발생하면 OS는 이 고아 프로세스를 init프로세스의 자식으로 만들어 줍니다.
부모,자식,고아를 이야기 했으니 입양이라고 해야 할까요? ㅋㅋㅋ
하지만 원래 init프로세스는 1번 프로세스로서 조상 프로세스에 해당됨으로 입양이라고 하기는 좀 그렇네요.
 
아무튼 위의 프로그램은 아무 문제가 없습니다. 좀비가 발생하지도 않구요.
 
하지만 이런 케이스를 생각해 보죠.
daemon도 프로세스이므로 현재 작업디렉토리를 갖습니다.
그래서 이 daemon이 실행된 후 daemon을 실행 시켰던 디렉토리가 속한 파일시스템을 "umount" 시키려 한다면 OS는 해당 파일시스템이 사용되고 있다고 umount 하지 못한다고 할 것 입니다.
이런 경우 해당 데몬을 내려야 하는데...
더욱 나쁜 경우는 어떤 데몬이 이 파일시스템을 사용하고 있는지를 알기가 힘들다는 것이죠.
그래서 데몬은 데몬이 되기 전에 현재 경로를 "/'와 같이 "umount"될 수 없는 곳으로 옮기는 것이 좋습니다.
 
또 한가지 고려해야 할 것은 현재 daemon은 뭐 파일에 숫자만 적고 있지만 여러분이 만드는 deamon은 어떤 일을 하게 될 지 사실 모릅니다.
예를 들어 daemon이 또 fork를 해서 자식 프로세스들을 갖을 수도 있고 exec()함수나 system()함수에 의해 아예 다른 프로그램을 실행 시킬 수도 있을 것입니다.
이때 새로 생성되는 프로세스를 현재 daemon이 제어 할 수 없다면 이 또한 문제일 수 있겠죠?
그래서 데몬프로세스는 데몬이 된 직 후 자신이 속한 프로세스 그룹의 리더가 아니라면 새로운 프로세스 세션을 만들고 자신이 리더가 된 후 다음 작업들을 하게 됩니다.  이러한 기능을 하는 함수가 바로 setsid()라는 함수 입니다. (참조: http://teamblog.joinc.co.kr/yundream/226)
 아래 소스는 chdir()과 setsid()함수를 호출하여 위에서 이야기한 내용을 반영하고 있습니다.
 
int main(int argc, char *argv[])
{
        int pid;

        pid=fork();
        switch(pid){
        case -1:
                fprintf(stderr, "Fork Error\n");
                break;
        case 0:         // child
                break;
        default:        // parent
                return 0;
        }

        chdir("/");
        setsid();

        work();

        return 0;
}
 
 
자 여기까지 하면 뭐 데몬이 잘 만들어 진 것 입니다.
 
추가로 실제 데몬을 프로그래밍 하실 때 주의하실 점은 시그널에 대한 처리를 꼭 하시라는 것 입니다.
위의 샘플 소스는 뭐 특별하게 시그널 처리를 할께 딱히 없지만 예를 들어 웹서버와 같이 통신 프로그램인 경우 SIG_PIPE와 같은 시그널을 처리해야 합니다.
 
 
4. 오뚜기 같은 Daemon만들기
 
마지막으로 이야기 하는 것은 일반적인 데몬에 대한 이야기는 아니구요 팁같은 거라고 할까요?
데몬은 서비스 제공하는 프로세스이다 보니깐...
시스템이 시작되면 시작되서 끝날때 까지 살아 있어야 하는데...
우리가 짜는 프로그램이 문제가 없다고 장담할 수는 없겠죠? (저만 그런가?)
 
만약 데몬으로 띄운 프로그램이 죽으면 타격이 크죠.
뭐 그 타격은 타격이더라도 세션이나 트랜잭션이 중요한 서비스가 아닌 경우라면 빨리 다시 시작이라도 시켜서 정상화를 시키고 싶은 경우가 있습니다.
 
이런 경우에 다음과 같은 방법으로 할 수 있을 것입니다.
먼저 일반 데몬을 하나 만들기 위해 일반 fork하시구요.
그리고 다시 fork를 해서 자식프로세스는 서비스를 수행하구요 부모프로세스는 자식이 종료되기를 기다립니다.
그런데 자식프로세스는 무한루프일 거니깐...
부모프로세스 입장에서 자식이 종료되었다면 실제로는 뭔가 문제가 생긴 것이겠죠?
이때 다시 fork를 해서 위의 과정을 반복합니다.
 
소스는 다음과 같습니다.  
 
int main(int argc, char *argv[])
{
        int pid;
        int ret;

        if (( pid = fork()) < 0) {
                fprintf(stderr, "Main Fork Error\n");
                return 0;
        } else if(pid > 0) {
                return 0;
        }

        chdir("/");
        setsid();

        while(1) {
                if (( pid = fork()) < 0) {
                        fprintf(stderr, "Sub Fork Error\n");
                        return 0;
                } else if(pid == 0) {
                        break;
                } else if(pid > 0) {
                        wait(&ret);
                }
        }

        work();

        return 0;
}
 
 
만약 자식이 종료될때 상태를 알고자 한다면 wait()함수의 인자인 ret값을 조사하면 됩니다.
 
자 이렇게 해서 UNIX/LINUX에서 Daemon만들기에 대한 이야기를 마치도록 하겠습니다. 


출처 : http://honeybox.tistory.com/
HTML 코드를 작성할때 5배 속도 내는 코딩 비법, zen coding을 아시나요?

zen coding은 여러분들이 흔히 쓰고 계신 에디터 프로그램의 플러그인으로서 동작하며

CSS선택자 같은 입력방식으로 HTML코딩을 산출해냅니다.

백문이 불여일견!

일단 코드를 살펴보실까요?


div#page>div.logo+ul#navigation>li*5>a



마치 CSS선택자 같은 이 친숙한 코드 한줄이 zen coding을 만나면


<div id="page">
        <div class="logo"></div>
        <ul id="navigation">
                <li><a href=""></a></li>
                <li><a href=""></a></li>
                <li><a href=""></a></li>
                <li><a href=""></a></li>
                <li><a href=""></a></li>
        </ul>
</div>





이렇게 변합니다.

굉장히 다양한 입력방식이 있으니 더 자세히 보고 싶으신 분들은 동영상을 보세요.


Zen Coding v0.5 from Sergey Chikuyonok on Vimeo.



또 다른 동영상 보기



zen coding은 공식지원되는 에디터와 third party 개발자들에 의해 만들어진 플러그인까지 포함하여

  • Aptana/Eclipse
  • TextMate
  • Coda
  • Espresso
  • Komodo Edit/IDE
  • Notepad++
  • PSPad
  • Dreamweaver
  • Sublime Text
  • UltraEdit
  • TopStyle
  • GEdit
  • BBEdit/TextWrangler
  • Visual Studio
  • EmEditor
  • Sakura Editor



이만큼이나 되는 에디터 들을 지원합니다.

저는 주로 windows 환경에서 editplus를 사용하는데 아쉽게 editplus용은 없네요.


아무튼 너무나도 멋진 플러그인임에는 틀림이 없네요!!

출처 : http://v.daum.net/link/10578136

이번에는 리눅스의 런 레벨에 대해 알아 보겠습니다. 우선 Run level이 무엇인지부터 알아야겠죠?
런레벨(Run level)이란, 시스템 관리의 용이함을 위하여 서비스의 실행을 단계별로 구분하여 적용하는 것을 말합니다.

런레벨은 0부터 6번까지 있는데요. 한번 알아보겠습니다.

# 0 - halt (DO NOT set initdefault to this)
시스템 종료를 의미합니다. 즉, 런레벨 0으로 변경하라는 명령을 내리면 시스템을 종료하는 것이죠.

# 1 - Single user mode
시스템 복원모드라고도 하며, 기본적으로 관리자 권한 쉘을 얻게 됩니다.
주로, 파일시스템을 점검하거나 관리자 암호를 변경할 때 사용합니다.

# 2 - Multiuser mode, without NFS (The same as 3, if you do ot have networking)
NFS(Network File System)을 지원하지 않는 다중 사용자 모드입니다.
네트워크를 사용하지 않는 텍스트 유저모드라고 할 수 있죠.

# 3 - Full muliuser mode
일반적인 쉘 기반의 인터페이스를 가진 다중 사용자 모드입니다.
쉽게 말하면 그래픽 유저 모드가 아닌 '텍스트 유저 모드'입니다.

# 4 - unused
4번은 쓰이지 않습니다. 기본적으로는 사용되지 않지만, 임의로 정의해서 사용할 수 있는 레벨입니다.

# 5 - X11
기본적으로는 level 3과 같습니다. 다른 점은 '그래픽 유저 모드' 라는것!!!

# 6 - reboot (DO NOT set initdefault to this)
시스템 재부팅을 의미합니다. 런레벨 6으로 변경하라는 명령을 내리면 시스템을 재부팅 하죠.



주로 사용하게 되는 것은 0, 3, 5, 6 을 많이 씁니다. 이 런레벨의 변경은 root 사용자의 경우만 가능합니다. 즉, 터미널 창에서 관리자 모드로 들어가 gedit /etc/inittab을 입력하면 런레벨을 바꿔줄 수 있습니다. 한번 해볼까요?




터미널 창을 켜고, 관리자 모드로 들어갑니다. gedit /etc/inittab 명령어를 입력해주세요.




그럼 아래와 같은 창이 켜지죠. 위에서 봤던 runlevel에 안내가 나옵니다.




그리고 그 간단한 안내 아래에서..! 런레벨을 바꿔줄 수 있습니다.
한번 텍스트 유저 모드로 바꿔볼까요? 블록한 부분을 봐주세요 :)




5를 3으로 바꿔주고 빨간색 네모로 강조한 '저장' 버튼 클릭하면 끝! 입니다 :)




그럼 이제 시스템을 다시 시작해볼까요? 아래 화면과 같이 텍스트 모드로 시작되는 것을 볼 수 있습니다. :)




다시 그래픽 유저 모드로 돌아가고 싶을 때는, init 명령어를 이용하시면 됩니다. 이렇게요. :)
inittab이나 init 명령어 처럼 런레벨을 변경하는 것은
오직 관리자 모드에서만 가능하므로 su - 부터 입력해주셔야합니다.




그럼 명령어 입력하기 무섭게 그래픽 유저 모드로 넘어가지요.






명령어 init단순히 런레벨을 변경해서 부팅하는 명령어이기 때문에
시스템 종료후, 이대로 다시 부팅하게 되면 텍스트 유저 모드로 부팅하게 됩니다.

다시 그래픽 유저 모드로 바꿔주려면,
 로그인하셔서 아까처럼 터미널 창에서 관리자 모드로 바꿔주고 gedit /etc/inittab 입력후
inittab창에서 id:3:initdefault → id:5:initdefault 로 바꿔주시면 됩니다. :)


1) 데몬의 종류

데몬이란 시스템에 백그라운드 모드로 수행중이며 어떤 사건, 즉 이벤트를 기다리거나 주기적으로 주어진 작업을 수행하기 위하여 대기하고 있는 프로세스를 의미한다. 일반적으로 데몬프로세스는 이름끝에 'd'자가 붙는다.
기본적으로 리눅스에는 여러 기능과 서비스를 제공하기 위한 다양한 데몬 프로세스들이 시스템에서 돌아가고 있다.
이런 서비스 데몬들의 실행여부는 레드햇 리눅스 계열에서 ntsysv 커맨드로 조정하면 된다. 리눅스상에서 현재 실행되고 있는 데몬의 현황을 보려면 pstree 커맨드를 쓴다.

데몬의 실행방식은 크게 stand-alone방식과 xinetd(슈퍼데몬)방식이 있다.
 # Stand-alone방식
(말뚝보초처럼 항상실행대기)
이 방식의 데몬들은 데몬이 시작되면 말 그대로 자기 스스로 시스템에서 상주하며 클라이언트 요청에 응답을 보내주는 방식으로 보통 아파치 데몬처럼 클라이언트의 요청이 잦은 데몬들이 이런 방식으로 실행된다. 스탠드 얼론방식의 데몬을 확인하려면 쉘상에서 pstree 명령을 내리면 데몬들을 트리형식으로 보여준다. 스탠드 얼론 방식의 데몬들은 xinetd방식보다는 클라이언트 요청에 신속하게 대응한다는 장점은 있으나 이런 스탠드 얼론 데몬들이 시스템에서 많이 생성되게되면 시스템의 자원낭비가 심해지게 되고 퍼포먼스도 떨어지게 된다.

 # inetd방식
(클라이언트 요청이 있을때만 실행)
스탠트 얼론처럼 자기 스스로 독립적으로 시스템에 실행되는게아니라 xinetd라는 수퍼데몬이 시스템에서 대기하고 있다고 클라이언트 요청이 들어오면 xinetd데몬에 의해 해당 서비스를 제공해줄 데몬을 실행시키는 방식이다. telnet이나 ftp같이 비교적 클라이언트 요청의 빈도가 낮은 서비스들은 이런 xinetd데몬이 시스템 활용측면에서는 유리하다. 또한 tcp wrapper를 써서 보안을 손쉽게 설정할 수 있는 것도 장점이다. 그러나 전술한 아파치 데몬같이 클라이언트의 자잘한 요청이 많은 서비스에 대해서는 inetd방식이 시스템효율을 도리어 떨어드리게된다. xinetd데몬은 스탠드 얼론방식으로 실행되는 슈퍼데몬이며 서비스 요청시 xinetd데몬의 차일드 프로세스로 다른 데몬이 실행된다. 이를 확인하려면 pstree로 xinetd데몬을 확인하고 다른 한텀창에서 telnet이나 ftp로 자신의 호스트에 접속해보라. 그럼 xinetd데몬에서 차일드 프로세스로 해당 데몬이 실행되는 것을 확인할 수 있다.

 

 

2) /etc/rc.d/init.d/ 데몬 설명

/etc/rc.d/init.d/autofs
오토마운트 파일시스템(Automount Filesystem) 데몬 스크립트입니다. 파일시스템 사용을 요구받았을 경우에는 마운트를 하고 파일시스템 사용이 끝났을 경우에는 마운트를 해제하게 됩니다.

/etc/rc.d/init.d/crond
cron 데몬 스크립트입니다. 여러분들께서도 잘 아시는 바와 같이 cron은 특정한 시간에 지정된 작업을 주기적으로 하도록 하는 리눅스 작업관리자 데몬입니다. 이런 cron데몬을 시작, 재시작 또는 종료시키는 스크립트입니다.

/etc/rc.d/init.d/functions
리눅스 시스템의 /etc/rc.d/init.d/디렉토리내의 거의 모든 쉘 스크립트에서 사용되어지는 함수를 내장하고 있는 파일입니다.

/etc/rc.d/init.d/gpm
GPM은 Midnight Commander와 같은 텍스트기반의 리눅스 어플리케이션에서 마우스의 복사 및 붙이기 기능과 콘솔상에서의 마우스 팝업기능을 제공하기 위한 데몬입니다.

/etc/rc.d/init.d/halt
halt는 시스템이 런레벨(runlevel) 0또는 런레벨(runlevel)6로 실행이 될 때에 init 프로세스에 의해 실행되는 스크립트로서 현재 시스템에 실행된 모든 프로세스를 죽이고 모든 파일시스템의 마운트를 해제한 후에 시스템을 종료(halt)시키거나 재부팅(reboot)합니다.

/etc/rc.d/init.d/iptables
iptables는 /etc/sysconfig/iptables에 미리 정의된 룰에 따라서 리눅스 서버의 방화벽을 실행 및 중지하기 위한 스크립트입니다. 즉, iptables로 구현하는 패킷필터링(packet filtering)방화벽입니다.

/etc/rc.d/init.d/irda
IrDA (Infrared Data Association)데몬 스크립트로서 IrDA는 무선통신, 적외선 통신을 위한 산업표준입니다. IrDA는 최근 거의 모든 장치들(laptops, LAN아답터, PDA, 프린터, 휴대폰등)에 사용될 수 있으며 9600bps에서 4Mbps의 속도범위를 가집니다.

/etc/rc.d/init.d/isdn
isdn 서비스를 시작하거나 종료하는 스크립트입니다.

/etc/rc.d/init.d/kdcrotate
/etc/krb5.conf에 정의되어 있는 KDC 리스트를 회전시키는 스크립트입니다.

/etc/rc.d/init.d/killall
현재 실행중인 서비스들을 대상으로 모두 중지시키는 스크립트입니다. 따라서 이 스크립트는 주로 시스템을 중지하거나 재시작할 때에 실행되는 스크립트입니다.

/etc/rc.d/init.d/kudzu
kudzu데몬은 새로운 하드웨어나 또는 변경된 하드웨어를 조사하여 설정하는 데몬입니다. 또한 kudzu데몬은 현재의 하드웨어 정보와 /etc/sysconfig/hwconf에 저장해 하드웨어 정보를 비교하여 변경된 하드웨어 또는 해로운 하드웨어가 존재하는가를 알아냅니다.
즉, 시스템 하드웨어의 변경 또는 새로운 하드웨어의 추가장착등과 같은 하드웨어에 대해 조사하는 kudzu데몬을 시작시키거나 종료하는 스크립트입니다.

/etc/rc.d/init.d/netfs
Network Filesystem(NFS)와 SMB(Lan Manager/Windows ), NCP(NetWare)를 마운트 시키거나 마운트 해제하는 데몬 스크립트입니다.

/etc/rc.d/init.d/network
리눅스 서버의 통신을 가능하도록 하기 위하여 관련 파일에 설정되어 있는대로 네트워크 설정을 하거나 중단하는 스크립트입니다.

/etc/rc.d/init.d/nfs
NFS 서비스 데몬을 시작(종료, 재시작)하는 스크립트입니다. NFS는 TCP/IP 네트워크상에서 파일공유를 위해 많이 사용되고있는 프로토콜입니다. 이 스크립트로 NFS서비스를 실행하면 /etc/exports파일의 설정대로 NFS서버기능을 할 수 있도록 설정합니다.

/etc/rc.d/init.d/nfslock
NFS파일 락킹서비스를 시작(종료,재시작)하는 스크립트입니다.

/etc/rc.d/init.d/nscd
네임서비스 캐쉬데몬(Name Service cache Daemon)을 시작하는 스크립트입니다. NSCD데몬은 가장일반적인 네임서비스에 대한 캐쉬기능을 제공하는 데몬으로서 /etc/passwd, /etc/group, /etc/hosts파일등에 대한 캐쉬정보를 가지고 있습니다. NSCD데몬의 설정파일은 /etc/nscd.conf입니다.

/etc/rc.d/init.d/pcmcia
pcmcia 데몬을 시작(종료)하기 위한 스크립트입니다. PCMCIA는 일반적으로 노트북등에서 사용되는 장치(모뎀, 이더넷등)를 지원하기 위한 것입니다.

/etc/rc.d/init.d/portmap
RPM 포트맵퍼(portmap daemon)을 시작(종료)하는 스크립트입니다. 일명 포터맵퍼(portmapper)라고 합니다. 이 portmapper는 NFS와 NIS 등과 같은 프로토콜이 사용되는 RPC연결을 제어하는 역할을 합니다. 따라서 이 portmapper는 RPC매카니즘을 사용하는 프로토콜이 탑재되어있어 서버로 사용되는 시스템에서는 반드시 실행되어있어야 합니다.

/etc/rc.d/init.d/random
리눅스 시스템에서의 난수사용을 위하여 난수발생데몬인 random을 시작시킵니다.

/etc/rc.d/init.d/rawdevices
하드드라이브 파티션과 같은 블록장치에 rawdevice를 할당하는 스크립트입니다. 잘아시는 Oracle과 같은 어플리케이션에서 사용될 수 있습니다. /etc/sysconfig/rawdevices파일을 수정, 편집함으로써 rawdevice에 블록장치매핑과 할당을 할 수 있습니다.

/etc/rc.d/init.d/single
시스템 실행레벨(runlevel) 1로 가고자 할 때 사용하는 스크립트입니다. 이 스크립트가 실행되면 시스템의 모든 프로세스들을 죽인 다음 시스템을 실행레벨 1상태로 만들어 줍니다. 실행레벨 1상태는 관리자(root) 전용모드입니다.

/etc/rc.d/init.d/sshd
sshd라는 OpenSSH서버데몬을 실행(중지)하는 스크립트입니다. telnet과는 달리 ssh는 암호화하여 통신을 하기 때문에 보안을 위한 통신방법으로 주로 사용됩니다. Telnet처럼 원격서버 로그인을 하는 ssh를 사용하려면 sshd데몬이 실행되어 있어야합니다. 이 스크립트는 sshd데몬을 실행시켜주는 스크립트입니다. 참고로 ssh는 TCP 22번과 UDP 22번을 사용합니다.

/etc/rc.d/init.d/syslog
syslog는 리눅스 시스템의 필수적인 로깅시스템입니다. 이런 로깅시스템을 시작(종료)하는 스크립트입니다. 이 스크립트에 의해 로깅시스템의 데몬인 syslogd가 실행되면 /etc/syslog.conf파일을 참조하여 각 설정에 해당하는 조건이 되면 지정된 로그파일에 로그메시지를 기록합니다. 로그파일이 기록되는 디렉토리는 /var/log/이며 대표적인 로그파일로는 /var/log/messages, /var/log/secure, 그리고 /var/log/maillog등이 있습니다. 이 스크립트에 의해 실행되는 데몬은 /sbin/syslogd와 /sbin/klogd가 있습니다.
/sbin/syslogd는 로깅시스템의 주된 그리고 일반적인 로그메시지를 기록하는 주데몬이며 klogd는 커널메시지를 기록하는 커널로그데몬입니다. 그리고 서버의 로그메시지를 원격서버에 실시간으로 저장하고자 한다면 syslogd데몬 실행시에 -r옵션을 사용하여 실행하시기 바랍니다. 참고로 syslogd는 UDP 514번을 사용합니다.

/etc/rc.d/init.d/xinetd
리눅스 서버의 인터넷 수퍼데몬인 XINETD데몬을 실행시키거나 중지시키는 데몬입니다. Xinetd는 TCP_Wrapper와 함께 사용되며 대부분의 인터넷 서비스들을 관장하며 telnet이나 ftp등과 같은 특정 서비스요청을 사용자프로세스와 서비스데몬을 연결시켜주는 역할을 합니다.

/etc/rc.d/init.d/ypbind
NIS/YP 클라이언트 시스템에서 실행되는 데몬으로서 NIS 도메인(domain)에 바인드시키는 역할을 합니다. NIS클라이언트에서 수행되기 위하여 반드시 glibc 기반 시스템에서 실행되어야합니다. 하지만 NIS를 사용하지 않는 시스템에서 실행되어져서는 안됩니다.


'OS > LINUX' 카테고리의 다른 글

Linux서버에 Memcached 설치/실행 하기  (0) 2011.06.09
리눅스의 런레벨(Run level)  (0) 2011.06.09
[/etc/rc.d/init.d/*] 데몬 실행 스크립트의 이해  (0) 2011.06.09
/dev/null 다시 만들기  (0) 2011.06.04
/dev/zero와 /dev/null  (0) 2011.06.04

1. 심볼릭링크

 

윈도우XP에서 한글2005를 실행시킬때의 구조를 살펴보자.

설치시 특별히 디렉토리를 변경하지 않았다면, 실행파일은 다음의 위치에 있다.

 

    C:\HNC\Hwp65\hwp.exe

 

그러나, 우리는 탐색기를 열어서.. C:\HNC\Hwp65\hwp.exe 파일을 더블클릭해서 직접 실행하지는 않는다.

보통은, '시작>프로그램>한글과컴퓨터>한글2005>한글 2005' 를 실행하거나,

아니면, 바탕화면의 단축아이콘을 더블클릭한다.

 

단.축.아.이.콘...!!

윈XP에서의 단축아이콘이 리눅스에서의 심볼릭링크이다.

 

 

2. /etc/rc.d/init.d/* 파일들의 이해

 

MS윈도우즈에서 프로그램을 설치하면 대부분 'C:\Program Files' 안에 설치된다.

물론, 다른 디렉토리에 설치해도 된다.

 

리눅스도 각각의 프로그램들(데몬들)을 원하는 디렉토리에 설치할 수 있다.

rpm으로 설치한다면, 특정 디렉토리가 지정되어 있겠지만...

소스로 설치할 때는 원하는 디렉토리에 설치한다.

apache를 소스설치할 때, --prefix 옵션으로 설치 디렉토리를 지정할 수 있는 것처럼 말이다.

물론, 관습적으로 대부분 /usr/local/ 밑에 설치하는 경향이 많다.

 

이렇게 각각의 디렉토리에 설치된 각각의 데몬들을 실행하거나, 중지하는 등의 관리를 할 때는 상당히 불편하다.

각 데몬이 어디에 설치되어 있는지 모두 알아야 하기 때문이다.

 

생각해보자.

어느누가 네임서버 데몬을 실행시키는데...

 

    # /usr/sbin/named

 

와 같이 데몬의 실행파일을 직접 실행시키겠는가..??

 

보통은...

 

    # /etc/rc.d/init.d/named start

 

와 같이 실행시킨다...

 

그렇다. 각 데몬의 실행파일들이 어디에 있는지와 상.관.없.이,

관리의 편의를 위하여....

각 데몬들을 실행할 수 있게 만든 쉘스크립트 파일모아놓고 관리를 한다.

그 디렉토리가 /etc/rc.d/init.d/ 디렉토리이며,

/etc/rc.d/init.d/ 밑의 모든 파일들은 vi 편집기로도 열리는, 쉘스크립트 파일들이다.

 

마치, 윈XP에서 각 프로그램들을 하드에 설치하고..

실행할 때는 '시작>프로그램>....' 에서 실행하는 것과 비슷하다.

 

 

3. 런레벨의 이해

 

기본적으로 다음 두 가지는 알고 있다고 가정하자.

 

① 런레벨 종류

    - 런레벨 1 : 싱글모드 부팅. MS윈도우즈의 안전모드와 비슷

    - 런레벨 3 : 콘솔모드로 부팅

    - 런레벨 5 : X 윈도우로 부팅

    - 런레벨 6 : 계속 재부팅만 한다.

 

② 런레벨 수정

    - /etc/inittab 파일에서 다음 항목의 숫자를 직접 수정함으로 변경 가능

      id:3:initdefault:

 

이제, 윈XP의 '시작>프로그램>시작프로그램' 을 생각해 보자.

시작프로그램에 특정 프로그램을(프로그램의 단축아이콘을) 등록해 놓으면,

컴퓨터를 켤 때 그 프로그램이 자동으로 실행된다.

 

리눅스도 시작할 때 자동으로 실행될 프로그램(=데몬)을 등록할 수 있다.

윈XP에서는 '시작프로그램'에 등록하지만, 리눅스는 디렉토리에 심볼릭링크를 만들어서 등록한다.

 

    - /etc/rc.d/init.d/rc3.d   : 런레벨 3으로 부팅될 때 자동실행할 데몬을 등록하는 곳

    - /etc/rc.d/init.d/rc5.d   : 런레벨 5로 부팅될 때 자동실행할 데몬을 등록하는 곳

 

필자는 런레벨 3으로 부팅하며, 다음과 같은 심볼릭링크 파일들을 볼 수 있다.

 

    # cd /etc/rc.d/rc3.d/
    # ls -al
    drwxr-xr-x    2 root     root         4096 12월 15 10:32 ./
    drwxrwxr-x   10 root     root         4096 12월 15 19:02 ../
    lrwxrwxrwx    1 root     root           13 12월 15 19:01 K15gpm -> ../init.d/gpm*
    lrwxrwxrwx    1 root     root           20 12월 15 19:02 K44rawdevices -> ../init.d/rawdevices*
    lrwxrwxrwx    1 root     root           18 12월 15 19:02 K45arpwatch -> ../init.d/arpwatch*
    lrwxrwxrwx    1 root     root           15 12월 15 19:02 K75netfs -> ../init.d/netfs*
    lrwxrwxrwx    1 root     root           15 12월 15 10:30 K95kudzu -> ../init.d/kudzu*
    lrwxrwxrwx    1 root     root           17 12월 15 19:02 S10network -> ../init.d/network*
    lrwxrwxrwx    1 root     root           16 12월 15 19:01 S12syslog -> ../init.d/syslog*
    lrwxrwxrwx    1 root     root           18 12월 15 19:00 S17keytable -> ../init.d/keytable*
    lrwxrwxrwx    1 root     root           16 12월 15 19:02 S20random -> ../init.d/random*
    lrwxrwxrwx    1 root     root           17 12월 15 19:02 S29sysstat -> ../init.d/sysstat*
    lrwxrwxrwx    1 root     root           15 12월 15 10:32 S55named -> ../init.d/named*
    lrwxrwxrwx    1 root     root           16 12월 15 19:02 S56xinetd -> ../init.d/xinetd*
    lrwxrwxrwx    1 root     root           15 12월 15 19:02 S90crond -> ../init.d/crond*
    lrwxrwxrwx    1 root     root           11 12월 15 19:02 S99local -> ../rc.local*
    lrwxrwxrwx    1 root     root           23 12월 15 19:02 S99oops-firewall ->
../init.d/oops-firewall*

 

디렉토리 안을 살펴보니, 모두 심볼릭링크 파일이라는 것을 알 수 있다.

심볼릭링크 파일은 제일 앞의 퍼미션을 나타내는 부분이 'l' 로 시작되며,

어떤 파일을 심볼릭링크했는지 화살표로 표시해 준다.

 

살펴보면, 모든 심볼릭링크의 원본파일들이 상위 디렉토리(../)의 init.d 디렉토리 내의 파일들,

, /etc/rc.d/init.d/파일들 이라는 것을 볼 수 있다.

따라서, 각 데몬의 실행파일을 관리하는 스크립트 파일들을 심볼릭링크한 것이다.

 

/etc/rc.d/rc3.d/ 밑의 파일들의 파일명을 살펴보면 다음과 같은 형식이다.

 

  S[혹은 K]{숫자}{데몬파일명}

 

S 로 시작되는 링크파일은 부팅할 때 시작(Start)되는 스크립트파일이다.

K 로 시작되는 링크파일은 부팅할 때 시작되지 않는(Kill) 스크립트파일이다.

 

{숫자}는 실행되는 우선순위를 나타낸다.

crond 데몬보다, named 데몬이 중요하고 꼭 실행되어야 한다면... crond 링크보다 숫자를 낮은 숫자로 하면 된다.

예전에는 컴퓨터(서버)의 사양이 좋지 않아, '어떻해도 가장 중요한 데몬'을 실행시키기 위해서 있었지만..

지금은 별 의미가 없다..

실행되지 않을 정도의 하드웨어 사양을 찾기가 힘들다... ^^;

{숫자}는 같은 숫자로 중복해서 사용할 수도 있다.

 

ntsysv 명령어로 각 데몬을 체크하거나, 체크를 지우는 것도...

알고보면 S 를 K 로 바꾸거나, K 를 S 로 바꾸는 작업이다.

 

/etc/rc.d/rc3.d/ 디렉토리에서는 S로 시작해서 심볼릭링크가 되어 있고,

/etc/rc.d/rc5.d/ 디렉토리에서는 K로 시작해서 심볼릭링크가 되어 있다면...

같은 /etc/rc.d/init.d/ 밑의 같은 데몬스크립트 파일이라고 하더라도..

런레벨마다 실행되거나, 실행되지 않을 수 있다.


출처 :
http://cafe.naver.com/asii/857

'OS > LINUX' 카테고리의 다른 글

리눅스의 런레벨(Run level)  (0) 2011.06.09
데몬의 종류, /etc/rc.d/init.d/  (0) 2011.06.09
/dev/null 다시 만들기  (0) 2011.06.04
/dev/zero와 /dev/null  (0) 2011.06.04
Perl 입문  (0) 2011.05.17

실전 HTML5 가이드

book

본 가이드는 웹 개발자들이 HTML5의 기본 개념을 배우고 모바일 웹에서 실질적으로 사용할 수 있도록 하기 위해 만들어졌습니다. 한국 웹 표준 커뮤니티가 주최한 HTML5 오픈 콘퍼런스의 다섯명의 발표자들이 각자 자원 봉사로 작성하였습니다.

총 5장으로 구성 되어 있으며, HTML5 소개 및 마크업, CSS3, HTML5 APIs 및 iPhone에서의 웹 앱 개발이 포함되어 있습니다.

A4크기로 총 170페이지이고, B5크기로 206페이지입니다. 우선 A4에서 출력가능한 PDF 파일을 배포합니다. 많은 이용 바랍니다.

실전 HTML5 가이드 다운로드(A4 인쇄용) | B5 인쇄용

별도의 고지가 없는 한, 본 사이트의 모든 콘텐츠는
Creative Commons Attribution Share-Alike License v3.0 라이센스 하에서 이용 가능합니다.

CC nc nd

동영상 강의 목록

저자들이 한 강의 동영상을 다운로드해서 보실 수 있습니다.

웹 표준의 전반적인 것에 대해서는 웹 표준화 프로젝트에서 2005년에 실전 웹 표준 가이드를 참고하세요.

History of this Guidebook

This guide was written for web developers to learn basic concepts of HTML5 and to adopt it into the mobile web application in direct. It was made by five speakers of the first HTML5 Open Conference in Korea organized by Web Standards Korea and several communities.

This book was published as a PDF format and except where otherwise noted, content on this site is licensed under the Creative Commons Attribution Share-Alike License v3.0 or any later version.

It has five sections of introduction, markup of HTML5, CSS3, HTML5 APIs and the mobile application development in iPhone.

This book has 170 pages (A4 format) or 206 pages (B5-Letter format). Now, you can download A4 printable size Download HTML5 Guidebook


출처 : http://webstandards.or.kr/html5

'Dev > RIA' 카테고리의 다른 글

Canvas2Image: Canvas 데이터를 이미지로 저장  (0) 2011.06.10
[HTML5] Canvas  (0) 2011.06.10

PHP로 웹 서비스를 구현하다 보면 반복적인 작업에다 비효율적으로 파일들을 만드는 경우가 많죠. 이를 깔끔하게 해결할 수 있도록 해 주는 DAO클래스를 자동으로 생성해조는 오픈소스가 있네요.
현업에 얼마나 사용하실지는 모르겠으나 잘 응용하면 좋은 프레임워크로 만들 수 있을 것 같아 자료를 공유합니다.

1. PHPDAO 다운로드
 - wget http://www.phpdao.com/phpdao-1.7.zip
 - mkdir phpdao-1.7
 - cd phpdao-1.7
 - mv ../phpdao-1.7.zip .
 - unzip phpdao-1.7.zip .

2. Mysql 커넥션 설정
 - vi templates/class/dao/sql/ConnectionProperty.class.php 에서 아래 항목 기입

   private static $host = 'localhost';
   private static $user = 'mimuluser';
   private static $password = 'mimuladmin';
   private static $database = 'mimuldb';

3. DAO 클래스 생성하기
 - php generate.php
 - 현재 디렉토리에 generated 디렉토리가 생겨서 위에서 설정한 데이터 베이스의 테이블 단위로 dto, dao, mysql 디렉토리가 생성되어 클래스가 자동 생성됨

4. PHPDAO 아키테처
phpdao


출처 : http://www.mimul.com/pebble/default/2009/09/01/1251803100000.html

Java Simple Daemon

뭐에 쓰는 물건인고?

Java Simple Daemon은 자바를 이용해서 데몬 프로그램을 작성하도록 도와주는 프레임워크이다(비록 프레임워크라고 부르기엔 너무도 작지만.. ^^).
가끔씩 특정 디렉토리에 들어오는 파일을 감시해서 파일이 들어오면 그 파일을 DB에 넣기만 하거나, 혹은 어떤 방식으로든 메시지를 받아서 받은 메시지를 가공해 다른 쪽에 메시지로 넘겨 주거나 하는 등의 역할을 하는 그런 프로그램을 자바로 짤 경우가 있다.
이러한 프로그램들은 일반적으로 그래픽 사용자 인터페이스(GUI)나 화면 출력이 필요 없이 파일로 로그만 남기고 자기 할 작업을 한다. 이러한 프로그램을 데몬(Daemon)이라 부른다.
자바로 이러한 데몬을 작성할 경우, 데몬을 실행시키는 것은 문제가 없다.

$ nohup java some.Daemon &
이러한 식으로 실행하면 된다. 헌데 문제는 종료이다. 프로그램과 의사 소통할 무슨 방법이 없기 때문에 Unix에서 ps -ef명령으로 "java" 프로세스를 찾아서 kill명령을 내리거나 윈도우의 경우에는 프로세스 종료를 시킬 수 밖에 없다. 이러한 문제를 해결하기 위해 만든 것이 Java Simple Daemon(이하 JSD)이다.

프로젝트 홈

다운로드

Java Simple Daemon 다운로드 목록

어찌 작동하는고?

원리는 단순하다. 데몬 역할을 하는 자바 클래스를 실행시켜주면서 쓰레드가 하나 떠서 사용자의 홈 디렉토리(Unix에서 $HOME 환경변수가 가리키는 디렉토리)에 특별한 파일이 존재하는지를 검사한다. 만약 그 특별한 파일이 존재한다면 JVM을 자동으로 종료시켜준다. JSD는 그 특별한 파일이 있는지 검사하는 역할과, 그 파일을 생성 시켜주는 역할을 한다.

덤으로, JSD는 데몬 클래스에 따라 락(Lock) 파일도 생성해준다. 홈 디렉토리에 락 파일이 존재할 경우, 데몬을 다시 띄우려고 하면 데몬 띄우기를 거부한다.

사용하기

  • 데몬 클래스는 net.kldp.jsd.SimpleDaemon 인터페이스를 구현해야 한다.
    • public void startDaemon() : 데몬작업을 수행하는 메소드. 여기에 실제 작업 구현이 들어간다.
    • public void shutdown() : 데몬이 종료하기 전에 수행할 작업을 기록한다.
  • net.kldp.jsd.SimpleDaemonManager의 객체를 생성하고, 객체에 데몬 클래스를 등록해 준다.
  • net.kldp.jsd.SimpleDaemonManager.start()를 실행하면 데몬이 시작된다.
  • net.kldp.jsd.SimpleDaemonManager.shutdownDaemon()를 실행하면 데몬을 종료시키는 파일이 $HOME 디렉토리에 생성되어, 데몬을 종료시키게 된다.

예제 보기

아래 예제는 대책없이 화면에 시간을 출력하는 데몬이다.

  • 데몬의 시작 : java net.kldp.jsd.sample.ShowTime
  • 데몬의 종료(다른 콘솔 창에서) : java net.kldp.jsd.sample.ShowTime -shutdown
여기서 데몬을 종료하기 전에 다시 한번 데몬을 시작해보면 락 파일이 존재하기 때문에 실행을 거부하는 것을 볼 수 있다.
/*
 * Created on 2004. 11. 6.

 */
package net.kldp.jsd.sample;

import java.io.IOException;
import java.util.Date;

import net.kldp.jsd.IllegalSimpleDaemonClassException;
import net.kldp.jsd.SimpleDaemon;
import net.kldp.jsd.SimpleDaemonManager;

/**
 * SampleDaemon 예제.
 * 
 * 현재 시간을 계속해서 보여주는 데몬이다.
 * 
 */
public class ShowTime implements SimpleDaemon {

  public static void main(String args[]) {
    // -shutdown 옵션이 있을 경우 데몬을 종료시킨다.
    if (args.length > 0 && args[0].equals("-shutdown")) {
      System.out.println("ShowTime 종료시작.");
      
      try {

        SimpleDaemonManager sdm = SimpleDaemonManager.getInstance(ShowTime.class);
        sdm.shutdownDaemon();
      } catch (IOException e1) {
        e1.printStackTrace();
      } catch (IllegalSimpleDaemonClassException e) {
        e.printStackTrace();
      }
      return; // 프로그램 종료.
    }

    SimpleDaemonManager sdm = null;
    
    try {
      sdm = SimpleDaemonManager.getInstance(ShowTime.class);
      sdm.start();
    }  catch (Exception e) {
      e.printStackTrace();
    }
  }
  
  /**
   * 데몬 작업수행 : 현재 시간을 계속 보여준다.
   */
  public void startDaemon() {
    while (true) {
      Date now = new Date();
      System.out.println(now.toString());
      try {
        Thread.sleep(5000);
      } catch (Exception ex) {
        ex.printStackTrace();
      }
    }
    
  }

  /**
   * ShowTime 종료시 실행할 내용들. 
   */
  public void shutdown() {
    System.out.println("ShowTime을 종료합니다.");
  }
}

[출처] Java Simple Daemon|작성자 승빈파파


'Dev > JAVA' 카테고리의 다른 글

Spring framework 설치  (0) 2012.11.25
자바 데몬(daemon) 만들기  (0) 2011.06.09
자바 이미지 사이즈 추출 예제  (0) 2011.04.23
자바 이미지 리사이즈(썸네일)  (0) 2011.04.06

+ Recent posts