Wednesday, May 18, 2016

NPM으로 Node.js 업그레이드 하기

1. check current version

$>node -v

2. delete npm cache

$>sudo npm cache clean -f

3. install ‘n’

$>sudo npm install -g n

4. upgrade to the specific version,

$>sudo n {VERSION}

or upgrade to the latest stable version

 $>sudo n stable

5. check version

$>node -v

note)
At 5, if the version is not your favorite, try to reboot...

Sunday, April 10, 2016

Upstart로 오래 도는 프로세스 관리하기

오래 돌아야 하는 서버 또는 워커를 어떻게 관리하고 계신가요? 설마 이렇게 하고 계신가요?

  • screen이나 tmux 안에 띄워놓고 잊어버리기
  • nohup으로 실행해두고 잊어버리기
  • 프로세스가 꺼졌는지 한참동안 모르고 있다가 당황하기
  • 시스템 재부팅 될 때마다 헬을 만나기
우분투에서 기본으로 제공되는 Upstart를 사용하면,
  • 시스템 부팅 시에 서비스 띄우기
  • 다른 서비스가 시작된 후에 서비스 띄우기
  • 프로세스가 오류로 꺼지면 자동으로 다시 띄우기
  • stdout/stderr를 로그 파일에 기록하기
  • 로그 파일이 커지면 쪼개기
와 같은 기능을 어렵지 않게 사용할 수 있습니다.

설정 파일 설치하기

Upstart 서비스 설정 파일은 /etc/init/에 모여있습니다. 따라서 /etc/init/ 디렉토리에 서비스명.conf 파일을 만들어 넣으면 됩니다.

심볼릭 링크로 설치하기

/etc/init/에는 시스템 서비스의 설정 파일도 모두 들어있기 때문에, 조금 더 관리를 편하게 하려면 별도의 디렉토리에 서비스 설정 파일을 모아두는 것도 좋은 선택입니다. 그러려면 /etc/init에 심볼릭 링크를 걸어야 합니다.
sudo ln -s /home/ubuntu/something.conf /etc/init/
주의! /etc/init/에 직접 들어있지 않고 심볼릭 링크로 들어있는 파일이 수정될 때는 Upstart가 변화를 감지하지 못합니다. 따라서 다음 명령어로 설정 파일을 다시 불러오게 해야 합니다.
sudo initctl reload-configuration

서비스 관리

설정 파일 작성법을 알아보기 전에 서비스 관리하는 방법을 먼저 알아둡시다.
  • 시작: sudo start 서비스명
  • 중단: sudo stop 서비스명
  • 재시작: sudo restart 서비스명 (주의: 서비스 설정 파일을 다시 읽어오지 않습니다. 설정 파일이 바뀌었으면 stop 후 start할 것)
  • 점잖은 재시작: sudo reload 서비스명 (정확히는, 프로세스에 HUP 시그널을 보냅니다)

설정 파일 작성하기

명령어 지정

가장 간단하게는 exec 뒤에 명령어를 쓰면 됩니다.
exec uname -a
좀 더 긴 쉘 스크립트가 필요할 경우 script 구문을 사용합니다.
script
    sleep 5
    uname -a
end script
어떤 명령어들은 실행하면 자동으로 백그라운드로 들어가는(detach/daemonize) 경우가 있습니다. 이를 방지하는 옵션이 있다면 켜는 것이 좋습니다. (보통 --foreground나 --nodetach)
포어그라운드 모드로 실행하는 옵션을 지원하지 않는 경우 Upstart 문서를 참고해서 설정하시기 바랍니다.

자동 시작/중단 조건

서비스를 특정 조건이 만족되었을 때 시작되거나 중단되게 할 수 있습니다.
가장 많이 사용하게 될 설정은 부팅 시 시작, 시스템 종료 시 중단이겠죠? 다음과 같이 적으면 됩니다.
start on runlevel [2345]
stop on runlevel [016]
또는 다른 서비스가 시작된 이후에 띄우고 싶을 수도 있습니다. A 서비스가 시작된 후를 조건으로 지정하려면,
start on started A
and 연산자로 여러 조건을 조합할 수도 있습니다.
start on started mysql and started nginx
mysql과 nginx 서비스가 시작된 뒤가 시작 조건이 됩니다.

실행 권한

프로세스는 기본적으로 root 권한을 가지고 실행됩니다. 보안을 위해 별도의 사용자/그룹 권한을 주고 실행하는 것을 권장합니다.
setuid username
setgid groupname

실행 환경 설정

  • 환경 변수 설정: env KEY=value (환경 변수는 exec/script 구문 안에서 $KEY로 참조할 수 있습니다)
  • 디렉토리 변경: chdir /path/to/current/dir

자동 재시작(respawn)

한 줄만 추가하면 프로세스가 예기치 않게 종료됐을 때 (종료 코드가 0이 아닐 때) 자동으로 다시 실행됩니다.
respawn
프로세스가 너무 빨리 되살아나는 것을 방지하기 위해 5초 동안 10번 재시작되면 더이상 재시작하지 않습니다. 이 제한은 respawn limit으로 바꿀 수 있습니다.
# 주의: respawn limit 구문이 있더라도 respawn 구문이 없으면 자동 재시작이 되지 않습니다
respawn
respawn limit COUNT INTERVAL # INTERVAL초 동안 COUNT번 재시작되면 포기합니다.
respawn limit unlimited # 제한을 없앱니다.

로그 파일

stdout/stderr로 출력된 내용은 /var/log/upstart/서비스명.log에 저장됩니다.
우분투 (14.04 기준)에서는 이 로그 파일이 하루에 한번 분할되고 최대 7개의 파일이 유지되는 것이 기본 설정입니다. /etc/logrotate.d/upstart에서 설정을 바꿀 수 있습니다.

설정 파일 예제

gunicorn으로 파이썬 웹 애플리케이션을 실행하는 예제입니다.
start on runlevel [2345]
stop on runlevel [016]
respawn
setuid www-data
setgid www-data
env PORT=11000
chdir /home/ditto/animeta
exec env/bin/gunicorn animeta.wsgi --bind 127.0.0.1:$PORT --error-logfile -
view rawgistfile1.txt hosted with ❤ by GitHub

대안

  • 우분투 차기 (또는 차차기) 버전에서 Upstart가 systemd로 대체될 예정이라고 합니다. 데비안에서는 이미 systemd가 기본입니다.
  • 시스템과 독립적으로 작동하면서 Upstart 같은 기능을 제공하는 Supervisor도 많이 사용됩니다.

Thursday, March 17, 2016

JavaScript Coding Convention

Intro

javascript(이하 js)로 개발함에 있어서 개발자들간에 지켜야할 코딩 규약을 정하고자 한다.

Convention

Javascript File

  1. file encoding은 UTF-8로 한다.
  2. file extention은 .js로 한다. ex) Test.js
  3. javascript 코드는 기본적으로 HTML 파일에 들어가지 않는것을 권장한다.
  4. HTML에서 javascript include는 <script src="filename.js"> 형태로 기술한다.

Indentation & Line

  1. indent는 space 4칸으로 한다.(tab 지양)
  2. line length는 가능한 80 line에 맞추도록 한다.

Declaration

Variable

  1. 변수 선언은 반드시 var 를 사용한다.
  2. var statement는 function body의 최상단에 위치한다.
  3. var statement는 alphabetical ascending order로 배치 될수 있도록 한다.
    변수선언 샘플
    ...
    function printName() {
        var channel;
        var program;
        var size;
        ...
    }

Function

  1. function은 가능한 expressive하게 선언하지 않고 declarative하게 선언하는것을 권장한다.
    함수선언 샘플
    // suggest not to use if you can.
    var foo = function (arg1, arg2) {
        ...
    };
    // suggest to use this style.
    function foo(arg1, arg2) {
    ...
    }
  2. named function은 function keyword와 name 사이 space 1칸, parameter와 { 사이 space 1칸으로 한다.
    named function
    function myName(arg1, arg2) {
        ...
    }
  3. anonymous function은 function keyword와 argument 사이 space 1칸, parameter와 { 사이 space 1칸으로 한다.
    named function
    var af = function (arg1, arg2) {
        ...
    };
  4. inner function의 정의는 var statement 다음에 위치하도록 한다.
    named function
    function myName(arg1, arg2) {
        var v1;
        function inner(a1) {
            ...
        }
        ...
    }
  5. immediate function invocation은 괄호"()" 사이에 function이 위치할 수 있도록 한다.
    named function
    var af = (function (arg1, arg2) {
        var a;
        ...
        return a;
    }());

Naming

  1. variable naming은 lowercase와 숫자, underscore(_)의 조합으로 만들도록 한다.
    named function
    var channel_number;
    var program_name;
    ...
  2. underscore(_)로 시작하는 이름은 private에 한해서만 사용하도록 한다.
  3. method로 사용할 function명은 lowercase로 시작된 camel type을 사용한다.
    named function
    function doStuff() {
        ...
    }
  4. constructor로 사용될 function명은 uppercase로 시작된 camel type을 사용한다.
    named function
    function ChannelManager() {
        ...
    }
    ...
    var ch = new ChannelManager();
  5. global variable은 어떻게 할까?...고민중

Statement

  1. statement는 마지막에 항상 semicolon(;)을 붙이도록 한다.
  2. compound statement는 아래와 같은 패턴을 사용하도록 권장한다.
    named function
    // if-else
    if (condition) {
        statements
    }
         
    if (condition) {
        statements
    else {
        statements
    }
    if (condition) {
        statements
    else if (condition) {
        statements
    else {
        statements
    }
    // for
    for (initialization; condition; update) {
        statements
    }
    for (variable in object) {
        if (filter) {
            statements
        }
    }
    // while
    while (condition) {
        statements
    }
    // do-while
    do {
        statements
    while (condition);
    // switch
    switch (expression) {
    case expression:
        statements
    default:
        statements
    }
    // try-catch
    try {
        statements
    catch (variable) {
        statements
    }
    try {
        statements
    catch (variable) {
        statements
    } finally {
        statements
    }

Comparator

  1. ==와 != 대신 ===와 !==를 사용하는 것을 권장한다.

Additional

  1. eval은 보안상의 문제가 있으니 되도록 쓰지않도록 한다."eval is evil"
  2. with는 알기 힘든 버그를 만들어 낼수 있으니 되도록 쓰지 않도록 한다.
    http://yuiblog.com/blog/2006/04/11/with-statement-considered-harmful/
  3. global scope이 필요한 경우가 아니면 Function constructor는 사용을 자제한다.