우분투에서 어떠한 기능을 서비스로 돌리기 위해 systemd에 등록할 수 있다.
## service 파일 등록
/etc/systemd/system 위치에 파일명 {service name}.service 로 아래와 같이 생성 후 저장한다.
[Unit]
Description=My Test Service
[Service]
Type=simple
WorkingDirectory=/home/yunikim/dev/study/cpp_testing/cmake-build-debug
ExecStart=/home/yunikim/dev/study/cpp_testing/cmake-build-debug/ipc_exam_server
StandardOutput=tty
TTYPath=/dev/pts/0
[Install]
WantedBy=multi-user.target
기본적으로 systemd에 등록한 서비스가 출력하는 로그들은 journal에 저장되고, 아래 명령으로 확인할 수 있다.
$ journalctl -u service-name
하지만, 위의 예제에서는 ssh를 통해 접속한 terminal에서의 출력을 위한 stdout 변경을 위해 StandardOutput 과 TTYPath 설정을 추가하였다. (man systemd.exec에서 해당 옵션에 대해 확인할 수 있다.)
현재의 terminal tty 정보는 아래 명령으로 알 수 있다.
## systemctl을 통한 서비스 제어
systemd 서비스 제어를 위한 주요 명령어는 다음과 같다.
# systemd configuration reload
systemctl daemon-reload
# show service status
systemctl status {service name}
# start/restart/stop service
systemctl start/restart/stop {service name}
# enable/disable service
# 자동으로 서비스가 실행되도록 설정
systemctl enable/disable {service name}
## 서비스 프로그램 예제
아래는 지난 글에서 소개했던 예제에서 C++의 std::thread를 사용하여 약간 변경한 예제이다.
#include <iostream>
#include <thread>
#include <mutex>
#include <sys/ipc.h>
#include <sys/msg.h>
#define MAX_TEXT 100
struct msg_buffer {
[[maybe_unused]] long msg_type;
char msg_text[MAX_TEXT];
};
volatile bool g_aborted = false;
volatile bool g_print = false;
int msgid;
char output_char = 'A'; // default output character
void message_receiver();
int main() {
key_t key;
std::cout << "start test server !!" << std::endl;
// Generate unique key for IPC
if ((key = ftok(".", 173)) == -1) {
perror("ftok");
exit(EXIT_FAILURE);
}
// Create message queue
if ((msgid = msgget(key, 0666 | IPC_CREAT)) == -1) {
perror("msgget");
exit(EXIT_FAILURE);
}
std::thread receiver { message_receiver };
//receiver.detach();
// Main thread: Output the current char every second
while (not g_aborted) {
if (g_print)
std::cout << output_char << std::endl;
std::this_thread::sleep_for(std::chrono::milliseconds(1000));
}
if (receiver.joinable())
receiver.join();
std::cout << "exit test server !!" << std::endl;
return EXIT_SUCCESS;
}
void message_receiver() {
struct msg_buffer msg {};
while (true) {
// Receive message from client
if (msgrcv(msgid, &msg, sizeof(msg.msg_text), 1, 0) == -1) {
perror("msgrcv");
exit(1);
}
// Update output character
output_char = msg.msg_text[0];
if (output_char == 'Z') {
g_aborted = true;
break;
}
else if (output_char == 'P') {
g_print = not g_print;
}
}
std::cout << "exit message receiver" << std::endl;
}
service 파일의 StandardOutput을 변경하지 않은 경우(아마, journel인 경우)에는, 서비스를 종료하고 status 확인했을때 아래와 같이 journal의 로그도 함께 확인해 볼 수 있다.
반응형
'프로그래밍 > etc' 카테고리의 다른 글
[C++] simple IPC, pthread example for ubuntu (0) | 2024.07.18 |
---|---|
맥 잠자기 방지 cmd (0) | 2024.05.05 |
mosquitto "Connection error: Connection Refused: identifier rejected." 오류 (0) | 2024.02.21 |
Mac 주요 단축키 모음 (0) | 2023.11.25 |
nvidia GPU 정보 확인 (ubuntu) (0) | 2023.07.06 |