반응형

출처: http://ezcocoa.com/?p=2376

http://www.ipwork.co.kr/index.php?document_srl=22398&mid=page_private

 

새로 시작하는 서비스를 등록하기 위해 스크립트 작성과 서비스 등록법을 설명한다.

해당 자료는 askubuntu.com에서 참조하였다.

Init 스크립트

#!/bin/bash

### BEGIN INIT INFO
# Provides:        tomcat7
# Required-Start:  $network
# Required-Stop:   $network
# Default-Start:   2 3 4 5
# Default-Stop:    0 1 6
# Short-Description: Start/Stop Tomcat server
### END INIT INFO

PATH=/sbin:/bin:/usr/sbin:/usr/bin

start() {
 sh /usr/share/tomcat7/bin/startup.sh
}

stop() {
 sh /usr/share/tomcat7/bin/shutdown.sh
}

case $1 in
  start|stop) $1;;
  restart) stop; start;;
  *) echo "Run as $0 "; exit 1;;
esac

위 스크립트 작성 후 /etc/init.d/에 위치시킨다.

chmod 755 /etc/init.d/tomcat7
update-rc.d tomcat7 defaults

등록 후

service tomcat7 [start|stop|restart]

로 사용이 가능하다.

그럼 update-rc.d는 무엇일까? 우분투는 부팅시 서비스를 등록 할 수 있다. 그 때 이 명령어를 이용한다.

방법은 위와 동일하다.
1. /etc/init.d/ 위치에 스크립트 생성
2. chmod를 이용하여 권한 부여
3. update-rc.d를 이용하여 서비스를 등록 한다.

삭제 법은 아래와 같다
update-rc.d -f ‘service name’ remove

아래는 런레벨에 대해서 설명하고 있다.

레벨 설명
0 시스템 정지
1 단일 사용자 모드
2~5 다중 사용자 모드
6 시스템 재가동

update-rc.d 명령은 /etc/init.d/와 rcN.d 디렉토리의 파일 사이에 연결을 만든다.
그 연결 파일의 명칭은 ‘S’, ‘K’로 시작, 그 뒤로 두자리 숫자와 등록된 스크립트 파일명으로 구성된다. 각 rcN.d 는 N에 해당하는 런레벨으로 실행 될 때 ‘S’로 시작되는 스크립트들이 실행되고, ‘K’는 해당 런레벨 N을 빠져 나올 때 실행되게 된다. ‘S’, ‘K’ 뒤에 숫자는 실행 순서를 나타내게 된다.

 

반응형
반응형

출처: http://www.test104.com/kr/tech/3800.html

 

직접 응용 프로그램을 작성하거나 오픈 소스 도구를 활용하거나

inotify는 읽기, 쓰기, 생성하기와 같은 파일 시스템 연산을 감시하는 리눅스(Linux®) 기능입니다. inotify는 반응성이 좋으며, 놀랍도록 사용하기 쉬우며, 크론 작업으로 바쁘게 폴링하는 경우보다 훨씬 더 효율적입니다. inotify를 응용 프로그램으로 통합하는 방식을 익히고 시스템 관리를 자동화하는 데 사용하는 명령행 도구 집합을 살펴봅시다.
시스템 관리는 일상 생활과 상당히 비슷하다. 세수하고 야채를 먹듯이, 자그마한 일상 유지 보수 작업은 기계를 제대로 돌아가게 만든다. 문서 꾸미기, 호출에 응답하기, 업데이트 내려받기, 프로세스 감시와 같은 작업 때문에 방해 받는 상황에서 주기적으로 임시 파일이나 진단 로그 파일과 같은 거추장스러운 찌꺼기를 청소해야 한다. 다행스럽게도 셸 스크립트를 활용한 자동화, Nagios와 같은 도구를 사용한 감시 작업, 만능 크론으로 수행하는 자동화된 작업 일정은 어깨에서 짐을 덜어준다.

아주 묘한 이야기지만, 이런 도구는 모두 반응성이 떨어진다. 조건을 감시하기 위해 크론 작업으로 일정을 지정해 놓을 수 있지만, 자원을 많이 사용하고 계산이 바쁜 작업을 바쁘게 폴링하면 확장성이 그다지 좋지 않다. 예를 들어, FTP 디렉터리로 들어오는 자료를 감시해야 한다면, 새로운 파일이 들어왔는지 찾기 위해 find 명령으로 개별 폴더를 감시해야 한다. 하지만 동작이 매끄럽게 돌아가는 듯이 보일지라도 find 명령어 수행과 더불어 새로운 셸을 매번 띄워야 하므로, 디렉터리를 열고 탐색하기 위해 시스템 호출이 여러 번 필요하다. 아주 잦거나 여러 번에 걸쳐 바쁘게 일어나는 폴링 작업은 오래 지나지 않아 누적될 수 있다. (설상가상으로, 바쁘게 일어나는 폴링이 항상 적절하지는 않다. 맥 OS X의 파인더와 같은 파일 시스템 브라우저가 갱신 내용을 폴링하기 위해 치루는 비용과 복잡성을 상상해 보자.)

그러면 관리자가 해야 할 일은 무엇일까? 다행스럽게 믿을 만한 컴퓨터에 다시 한번 의지할 수 있다.

inotify란?

inotify는 리눅스 커널 기능으로 파일 시스템을 감시하고 있다가 삭제, 읽기, 쓰기, 심지어 unmount 연산에 이르기까지 관련 사건을 기다리는 응용에 즉시 경고를 준다. 세부 기능으로 파일 시작과 목적지를 파악해 이동까지도 추적이 가능하다.

inotify의 용법은 단순하다. 파일 기술자를 만들어 워치를 한 개 이상 붙인다(워치는 경로와 사건 집합이다). 그러고 나서 read() 메서드를 사용해 기술자에서 사건 정보를 받는다. 아까운 CPU 사이클을 낭비하는 대신에, read()는 사건이 발생할 때까지 차단된다.

금상첨화로 inotify는 전통적인 파일 기술자로 동작하기에, 전통적인 select() 시스템 호출을 활용해서 동시에 여러 입력이 들어오는 상황에서도 워치를 감시하도록 만들어준다. 파일 기술자를 사용한 차단이나 select()를 사용한 멀티플렉싱이라는 양쪽 접근 방법 모두가 바쁘게 일어나는 폴링을 회피한다.

이제 inotify를 살펴보고, 자그마한 C 코드를 작성해보고, 빌드할 수 있는 명령행 도구를 살펴보며 파일 시스템 사건에 반응하는 명령과 스크립트를 구성해보자. inotify는 한 밤중에 고양이(역주: cat을 중의적인 의미로 사용하고 있다)를 풀어놓지는 않지만, 필요하다면 cat과 wget을 돌려 의도한 작업을 정확하게 수행할 수 있다.

inotify를 사용하려면, 리눅스 커널 2.6.13 이상을 탑재한 리눅스 기계가 있어야 한다(2.6.13 이전 리눅스 커널은 dnotify라는 기능이 다소 뒤떨어지는 파일 감시 기능을 사용한다). 커널 버전을 모르겠다면, 셸에서 uname -a 명령을 내려보자.

% uname -a
Linux ubuntu-desktop 2.6.24-19-generic #1 SMP ... i686 GNU/Linux

여기서 나온 커널 버전이 최소한 2.6.13이라면, 시스템은 inotify를 지원해야 한다. /usr/include/sys/inotify.h 파일도 살펴보자. 이 파일이 있다면 커널이 inotify를 지원할 가능성이 높다.

참고: FreeBSD와 (이에 영향을 받은) 맥 OS X은 kqueue라는 inotify 유사 기능을 제공한다. FreeBSD 기계에서 man 2 kqueue를 입력하면 더 많은 정보를 얻을 수 있다.

이 기사는 맥 OS X 버전 10.5 레퍼드에 패러렐즈 데스크톱 버전 3.0을 설치한 다음에 가상으로 돌리는 (하디라고 알려진) 우분투 데스크톱 버전 8.04.1에 기반을 둔다.

 

inotify C API

inofity는 파일 시스템 모니터를 만드는 세 가지 시스템 호출을 제공한다.

inotify_init()는 커널에서 inofity 하위 시스템 인스턴스를 만든다. 성공하면 파일 기술자를 반환하며, 실패하면 -1을 반환한다. 다른 시스템 호출과 마찬가지로 inotify_init()가 실패하면, errno를 점검해서 문제 원인을 진단하자.
inotify_add_watch()inotify_add_watch()는 이름이 암시하듯이, 워치를 추가한다. 각 워치는 경로 이름과 적절한 사건 목록을 제공해야 한다. 여기서 사건은 IN_MODIFY와 같은 상수로 지정한다. 사건을 두 개 이상 감시하려면, 논리 OR 연산자(C에서 |)로 각 사건을 연결한다. inotify_add_watch()가 성공하면, 호출 결과로 등록된 워치를 가리키는 고유 식별자가 반환된다. 그렇지 않으면 -1이 반환된다. 이 식별자를 활용해 연관된 워치를 변경하거나 삭제한다.
inotify_rm_watch()는 워치를 제거한다.
read()와 close() 시스템 호출 역시 필요하다. inotify_init()에서 받은 기술자로 read()를 호출해 경고를 기다린다. 전형적인 파일 기술자 용법에 따라, 응용 프로그램은 스트림에서 자료로 표현되는 사건 송신을 기다리는 동안 차단 상태로 들어간다. inotify_init()에서 받은 기술자를 넘기면서 close() 시스템 호출을 부르면 inotify 인스턴스와 관련된 모든 메모리와 모든 활성 워치를 삭제하고 할당을 해제한다. (전형적인 참조 카운터 관련 주의 사항이 여기에도 적용된다. 인스턴스와 관련된 모든 파일 기술자는 워치와 inotify가 소비하는 메모리가 해제되기 전에 닫혀야만 한다.)

단지 강력한 세 가지 API와 "모든 것이 파일"이라는 익숙한 패러다임이 전부다. 이제 예제 응용 프로그램 작성으로 옮겨갈 준비가 끝났다.

예제 응용 프로그램: 사건 감시

Listing 1은 짧은 C 프로그램으로 파일 생성과 삭제라는 두 가지 사건이 일어나는지 디렉터리를 감시한다.

Listing 1. 디렉터리에서 생성, 삭제, 변경 사건을 감시하는 예제 inotify 응용
#include <stdio.h>
#include <stdlib.h>
#include <errno.h>
#include <sys/types.h>
#include <sys/inotify.h>

#define EVENT_SIZE  ( sizeof (struct inotify_event) )
#define BUF_LEN     ( 1024 * ( EVENT_SIZE + 16 ) )

int main( int argc, char **argv )
{
int length, i = 0;
int fd;
int wd;
char buffer[BUF_LEN];

  fd = inotify_init();

  if ( fd < 0 ) {
perror( "inotify_init" );
}

  wd = inotify_add_watch( fd, "/home/strike",
IN_MODIFY | IN_CREATE | IN_DELETE );
length = read( fd, buffer, BUF_LEN ); 

  if ( length < 0 ) {
perror( "read" );

  while ( i < length ) {
struct inotify_event *event = ( struct inotify_event * ) &buffer[ i ];
if ( event->len ) {
if ( event->mask & IN_CREATE ) {
if ( event->mask & IN_ISDIR ) {
printf( "The directory %s was created.\n", event->name );      
}
else {
printf( "The file %s was created.\n", event->name );
}
}
else if ( event->mask & IN_DELETE ) {
if ( event->mask & IN_ISDIR ) {
printf( "The directory %s was deleted.\n", event->name );      
}
else {
printf( "The file %s was deleted.\n", event->name );
}
}
else if ( event->mask & IN_MODIFY ) {
if ( event->mask & IN_ISDIR ) {
printf( "The directory %s was modified.\n", event->name );
}
else {
printf( "The file %s was modified.\n", event->name );
}
}
}
i += EVENT_SIZE + event->len;
}

  ( void ) inotify_rm_watch( fd, wd );
( void ) close( fd );

  exit( 0 );
}

응용은 fd = inotify_init();로 inofity 인스턴스를 만들고 나서 wd = inotify_add_watch(...)로 /home/strike에서 파일 생성과 삭제를 감시하는 워치를 하나 추가한다. read() 메서드는 경고가 도착할 때까치 차단된다. 각 파일/사건 쌍으로 이뤄진 경고 명세는 바이트 스트림으로 전송된다. 따라서 응용 프로그램 루프를 도는 동안에 들어온 바이트 스트림을 일련의 사건 구조체로 형변환해야 한다.

사건 구조체 정의는 /usr/include/sys/inotify.h에서 C 구조체 형식으로 정의되어 있다.Listing 2를 참조하자.

Listing 2. 사건 구조체 정의
struct inotify_event
{
int wd;              /* 워치 기술자 */
uint32_t mask;   /* 워치 마스크 */
uint32_t cookie;  /* 두 사건을 하나로 묶는 쿠키 */
uint32_t len;              /* name 필드에 들어있는 파일 이름 길이 */
char name __flexarr;  /* 파일 이름, NUL로 끝난다 */     
}

wd 필드는 사건과 관련된 워치를 가리킨다. inotify 인스턴스당 워치를 두 개 설정하면, 향후 처리 진행 방법을 결정하는 과정에 이 필드를 사용한다. mask 필드는 어떤 일이 벌어질지를 명세하는 비트 집합이다. 각 비트를 독립적으로 검사하자.

파일이 어떤 디렉터리에서 다른 디렉터리로 옮겨지는 경우에 cookie를 활용해 두 사건을 하나로 묶을 수 있다. 출발지와 목적지 디렉터리를 감시해야 inofity는 이동 사건 두 가지를 생성한다. 여기서 하나는 출발지이며 하나는 목적지며, cookie를 설정하는 방식으로 두 개를 하나로 묶는다. 이동을 감시하려면 IN_MOVED_FROM과 IN_MOVED_TO를 명세하거나 양쪽 다 감시하는 단축 상수인 IN_MOVE를 명세한다. 사건 유형을 검사하려면 IN_MOVED_FROM과 IN_MOVED_TO를 사용하자.

마지막으로 name과 len은 (경로를 제외한) 파일 이름과 영향을 받는 파일 이름 길이를 포함한다.

예제 응용 코드 빌드

코드를 빌드하려면, 디렉터리를 홈으로 옮겨 파일에 코드를 저장하고 C 컴파일러를 호출한다. 대다수 리눅스 시스템에는 gcc가 설치되어 있다. 그러고 나서 Listing 3처럼 실행 파일을 수행한다.

 

Listing 3. 실행 파일 수행
% cc -o watcher watcher.c
% ./watcher

반응형
반응형

http://www.opensource.apple.com/source/text_cmds/text_cmds-9/tail/tail.c

 

출처: http://jangpd007.tistory.com/17

 

kernel 2.6.1 이상이어야 함 이하는 dnotify 사용해야 함


#include <stdio.h>
#include <time.h>
#include <signal.h>
#include <sys/time.h>
#include <sys/types.h>
#include <string.h>
#include <stdlib.h>
#include <errno.h>
#include <sys/inotify.h>

int   exitflag = 1;

int main (int argc, char *argv[])
{
  if (argc == 1)  {
    printf ("tail filename\n");
    return 0;
  }
  char  fname [256];
  sprintf (fname, "%s", argv[1]);
  FILE *fp = fopen (fname, "r");
  if (!fp)  {
    printf ("file(%s)open failed (%d:%s)\n", fname, errno, strerror (errno));
    return 0;
  }

  fseek(fp, 0, SEEK_END);
  int eventfd = inotify_init();
  if (eventfd < 0)  {
    printf ("initial inotify failed (%d:%s)\n", errno, strerror(errno));
    return 0;
  }
  int   wd = 0;
  wd = inotify_add_watch (eventfd, fname, IN_MODIFY|IN_DELETE_SELF|IN_MOVE_SELF);
  if (wd < 0) {
    printf ("add inotify watch failed (%d:%s)\n", errno, strerror(errno));
    return 0;
  }
  while (exitflag)  {
    fd_set  fdset;
    FD_ZERO (&fdset);
    FD_SET (eventfd, &fdset);
    struct  timeval tv;
    tv.tv_sec = 1;
    tv.tv_usec = 0;
    int rc = select ( eventfd + 1, &fdset, (fd_set*)NULL, (fd_set*)NULL, &tv);
    if (rc == 0)  continue;
    if (rc < 0) {
      printf ("select failed (%d:%s)\n", errno, strerror (errno));
      exitflag = 0;
      break;
    }
    if (!FD_ISSET(eventfd, &fdset)) continue;
    char  buff[1024];
    int readlen = read (eventfd, buff, sizeof (buff));
    if (readlen < 0)  {
      printf ("event read failed (%d:%s)\n", errno, strerror(errno));
      exitflag = 0;
      break;
    }
    int eventpos = 0;
    while (eventpos < readlen)  {
      struct  inotify_event *event = ( struct inotify_event*)&buff[eventpos];
      if (event->mask & IN_MODIFY)  {
        char  readbuff[1024];
        if (fgets (readbuff, sizeof (readbuff), fp) == NULL)  continue;
        printf ("%s", readbuff);
      }
      else if (event->mask & IN_DELETE_SELF || event->mask & IN_MOVE_SELF)  {
        printf ("file delete or move event recved\n");
        exitflag = 0;
        break;
      }
      eventpos += (sizeof (struct inotify_event) + event->len);
    }
  }
  inotify_rm_watch (eventfd, wd);
  close (eventfd);
  fclose (fp);
  printf ("normal terminate (exitflag = 0)\n");
  return 0;
}

반응형

+ Recent posts