GitHub Pages에서 다시 시작

|

작년에 GitHub Pages에서 블로그를 운영했었습니다. 그러다가 워드프레스(WordPress)를 사용해보고 싶은 생각에 구글 클라우드 플랫폼(Google Cloud Platform)기반으로 워드프레스 블로그를 오픈했습니다.

그리고는 약 1년만에 다시 Jekyll을 활용한 GitHub Pages로 돌아왔습니다. 워드프레스 기반의 블로그와 GitHub Pages 기반의 블로그는 장단점 및 그 특징이 뚜렷했습니다. 아무래도 동적 웹페이지 방식의 블로그와 정적 웹페이지 방식의 블로그라 그 특징이 명확했던 것 같습니다.

사실, 워드프레스도 크게 불만은 없었습니다. 설치나 운영은 오히려 더 쉽고 편했습니다. 테마나 각종 플러그인 설치도 쉬웠고, 문제가 생길 때마다 구글링을 통한 검색도 쉬웠습니다.

다만 My SQL 데이터베이스의 불안정 때문에 ‘데이터 베이스 연결 오류’가 자주 떴는데, 이게 은근히 스트레스가 되었습니다. 거기에 설치형 블로그다보니 호스팅비도 매달 내야 하는데, (구글 클라우드 플랫폼을 사용하면 1년간 무료이기 때문에 실제로는 아직 돈을 지불하지는 않았습니다.) 제 블로그 특성상 수익이 창출되지는 않기 때문에 이번 기회에 과감히 다시 GitHub Pages로 넘어오기로 마음먹었습니다.

블로그를 여러 군데 운영하는 것은 많은 수고와 노력이 필요하기에 지난 자료들을 GitHub Pages로 옮기는 작업이 끝나면, 앞으로는 여기에만 포스팅을 하도록 하겠습니다.

scp 사용법

|

SCP (Secure Copy)

SCP(Secure Copy) 명령어는 원격의 파일이나 폴더를 복사하는 Linux 명령어입니다.

scp 명령어는 다음과 같은 형태로 사용할 수 있습니다.

scp [옵션] [원본 경로] [타켓 경로]

예를 들어서, 다른 곳에 있는 파일을 현재 위치로 다운로드하고 싶을 경우는 다음과 같은 형태로 사용할 수 있습니다.

scp -r pi@192.168.0.100:/home/pi/temp ./

여기서 -r 옵션은 하위 폴더까지 모두 포함시키는 옵션입니다.

반대로 로컬에 있는 파일을 서버로 업로드할 경우는 다음과 같이 할 수 있습니다.

scp -P 22 ./index.html pi@192.168.0.100:/home/pi

-P 옵션은 포트를 지정할 때 사용하며, 기본적으로 22번 포트를 사용하는 경우는 생략을 해도 됩니다.

Ctrl + C 키 이벤트 가로채기

|

Linux에서 작동하는 코드입니다. (Cygwin에서 빌드하면 윈도우에서도 작동합니다.)

기본적으로 Ctrl + C 키를 누르게 되면 프로그램이 강제로 종료되는데, 프로그램이 종료되기 전에 뭔가 처리해야 할 요소가 있다면 아래의 코드를 이용해서 Ctrl + C 키 이벤트를 가로챌 수 있습니다.

예제 코드

#include <cstdio>
#include <sys/stat.h>
#include <cstdlib>
#include <unistd.h>

void (*breakCapture)(int);

void signalingHandler(int signo) {
  printf("'Ctrl + C' processing...");

  exit(1);
}

using namespace std;

int main(void) {
  printf("Hello SnowDeer.\n");

  setsid();
  umask(0);

  breakCapture = signal(SIGINT, signalingHandler);

  while(true) {
    printf("Hello...\n");
    sleep(1);
  }

  return 0;
}

실행 화면

image

Message 및 Message Queue

|

메세지(Message)와 메세지큐(MessageQueue)는 이벤트(Event)들을 한 곳에서 처리하거나 멀티 쓰레드(Multi-thread) 환경에서 쓰레드간 이벤트를 전달할 때 유용하게 사용됩니다.

C++로 구현된 메세지 및 메세지큐 예제입니다. 헤더 파일로만 이루어져 있어서 include 만으로 사용가능합니다. 또한 하단부에는 메세지와 메세지큐를 활용한 메세지 핸들러(Message Handler) 코드가 있습니다. 안드로이드의 핸들러(Handler)와 유사한 구조로 되어 있습니다.


Message.h

#ifndef SNOWDEER_MESSAGE_H
#define SNOWDEER_MESSAGE_H

class Message {
 public:
  Message(int _what) : what(_what), arg1(0), arg2(0) {}
  Message(int _what, int _arg1) : what(_what), arg1(_arg1), arg2(0) {}
  Message(int _what, int _arg1, int _arg2) : what(_what), arg1(_arg1), arg2(_arg2) {}
  virtual ~Message() {}

  int what;
  int arg1;
  int arg2;

  const static unsigned int MESSAGE_CLIENT_SOCKET_THREAD_CLOSED = 100;
};

#endif //SNOWDEER_MESSAGE_H


MessageQueue.h

#ifndef SNOWDEER_MESSAGEQUEUE_H
#define SNOWDEER_MESSAGEQUEUE_H

#include <queue>
#include <mutex>
#include <condition_variable>

using namespace std;

template<class T>
class MessageQueue {
 public:
  MessageQueue(void) : mQueue(), mMutex(), mCondition() {
    mIsLoop = true;
  }

  ~MessageQueue(void) {
  }

  void clear() {
    std::lock_guard<std::mutex> lock(mMutex);
    std::queue<T> emptyQueue;
    std::swap(mQueue, emptyQueue);
  }

  void enqueue(T t) {
    std::lock_guard<std::mutex> lock(mMutex);
    mQueue.push(t);
    mCondition.notify_one();
  }

  void destory() {
    mIsLoop = false;
    mCondition.notify_one();
  }

  T dequeue(void) {
    std::unique_lock<std::mutex> lock(mMutex);
    while((mIsLoop)&&(mQueue.empty())) {
      mCondition.wait(lock);
    }
    T val = mQueue.front();
    mQueue.pop();
    return val;
  }

 private:
  std::queue<T> mQueue;
  mutable std::mutex mMutex;
  std::condition_variable mCondition;
  bool mIsLoop;
};

#endif //SNOWDEER_MESSAGEQUEUE_H


MessageHandler.h

#ifndef SNOWDEER_MESSAGE_H
#define SNOWDEER_MESSAGE_H

class Message {
 public:
  Message(int _what) : what(_what), arg1(0), arg2(0) {}
  Message(int _what, int _arg1) : what(_what), arg1(_arg1), arg2(0) {}
  Message(int _what, int _arg1, int _arg2) : what(_what), arg1(_arg1), arg2(_arg2) {}
  virtual ~Message() {}

  int what;
  int arg1;
  int arg2;

  const static unsigned int MESSAGE_CLIENT_SOCKET_THREAD_CLOSED = 100;
};

#endif //SNOWDEER_MESSAGE_H


MessageHandler.cc

#include "MessageHandler.h"

MessageHandler::MessageHandler() {
  mIsRunning = false;
}

MessageHandler::~MessageHandler() {}

void MessageHandler::start() {
  mIsRunning = true;
  mLooper = std::thread(&MessageHandler::loop, this);
}

void MessageHandler::stop() {
  mIsRunning = false;
  if(mLooper.joinable()) {
    mLooper.join();
  }
  clear();
  mMessageQueue.destory();
}

void MessageHandler::sendMessage(shared_ptr<Message> message) {
  mMessageQueue.enqueue(message);
}

void MessageHandler::clear() {
  mMessageQueue.clear();
}

void MessageHandler::loop() {
  while(mIsRunning) {
    shared_ptr<Message> message = mMessageQueue.dequeue();

    if(mIsRunning == false) {
      break;
    }

    switch(message->what) {
      case 1:
        break;

      case 2:
        break;
    }
  }
}

프로세스 관리하기

|

리눅스 프로세스

용어 설명
PID (Process ID) 프로세스 고유 식별 번호
UID (User ID) 프로세스를 소유한 사용자 계정의 식별 번호
GID( Group ID) 프로세스가 속해있는 그룹의 식별 번호
File Descriptor 프로세스의 읽기/쓰기를 위해 어떤 파일의 어떤 위치를 열고 있는지 기록


#프로세스 확인

현재 실행중인 프로세스는 ps 명령어를 이용해서 확인할 수 있습니다. ps만 입력한 경우 현재 로그인한 사용자가 실행한 프로세스만 보여줍니다.

-a 옵션을 붙이게 되면 다른 사용자의 프로세스 상태도 표시하며, -x 옵션은 화면에 보이지 않는 프로세스까지 모두 표시합니다. -u 옵션을 붙이면 프로세스를 사용한 사용자가 누구인지, 그리고 실행 시간까지 표시합니다.

아래와 같은 형태로 3가지 옵션을 모두 적용할 수 있습니다.

ps -aux

-aux 옵션 대신 -ef 옵션을 붙이게 되면 PID(Process ID)로 정렬된 결과를 보여줍니다.


프로세스 전체적인 상태 조회

ps -aux 명령어 대신 top 명령어를 이용할 경우 실시간으로 메모리 점유율이나 CPU 사용율을 화면에 보여줍니다. ps 명령어가 개별 프로세스의 상태를 보여주는데 반해, top는 전체 프로세스 상태를 한 눈에 보기 좋게 출력합니다.


프로세스 종료하기

프로세스 종료는 kill 명령어를 이용해서 종료할 수 있습니다. 사용법은 다음과 같습니다.

kill -[시그널] [PID]

ex) kill -9 5678

kill은 프로세스의 종료만을 위해 사용되는 명령어는 아닙니다. 현재 실행중인 프로세스에 시그널(Signal)을 보내서 프로세스의 상태를 변경하는 것이 주 목적입니다.

아무 시그널 옵션도 주지 않은 상태로 kill 명령어를 수행하면 시그널의 기본값이 -15로 설정됩니다. 15SIGTERM으로 프로세스를 종료하라는 신호입니다. 대부분의 프로그램은 기본값으로 종료가 되지만 간혹 종료가 되지 않는 프로그램들도 있습니다. 이런 경우는 SIGKILL 시그널인 -9 옵션을 이용해서 프로세스를 강제로 종료하게 할 수 있습니다.