SIGTERM이란?

  • 유닉스 기반의 프로세스 종료 신호
  • SIG_KILL과 반대
  1. 정의와 목적:
    • SIGTERM은 프로세스에게 정상적으로 종료할 것을 요청하는 신호.
    • 프로세스가 자원을 정리하고 안전하게 종료할 수 있도록 하는 "부드러운" 종료 방식이다.
  2. 신호 번호:
    • SIGTERM의 표준 신호 번호는 15이다.
  3. 동작 방식:
    • 프로세스는 SIGTERM을 받으면 정리 작업을 수행한 후 종료
    • 프로세스는 이 신호를 무시하거나 다르게 처리하도록 프로그래밍될 수 있다.
  4. 사용 사례:
    • 시스템 종료 시: 운영 체제가 종료될 때 실행 중인 프로세스들에게 SIGTERM을 보냅니다.
    • 프로세스 관리: 관리자나 사용자가 프로세스를 정상적으로 종료하고자 할 때 사용합니다.
    • 컨테이너 환경: Docker나 Kubernetes에서 컨테이너를 정상 종료할 때 SIGTERM을 사용합니다.
  5. SIGKILL과의 차이:
    • SIGTERM은 프로세스가 정리 작업을 수행할 기회를 제공하지만, SIGKILL(신호 번호 9)은 즉시 강제 종료한다.
    • SIGTERM은 프로세스가 무시할 수 있지만, SIGKILL은 무시할 수 없다.
  6. 프로그래밍에서의 처리:
    • 프로그래머는 SIGTERM 핸들러를 구현하여 프로세스가 이 신호를 받았을 때의 동작을 정의할 수 있습니다.
    • 일반적으로 열린 파일을 닫고, 네트워크 연결을 정리하고, 임시 파일을 삭제하는 등의 작업을 수행합니다.
  7. 시스템 동작:
    • 프로세스가 SIGTERM을 받고 일정 시간 내에 종료되지 않으면, 시스템은 SIGKILL을 보내 강제 종료할 수 있습니다.
  8. 명령어 사용:
    • Unix/Linux 시스템에서 'kill' 명령어를 사용하여 SIGTERM을 보낼 수 있습니다. (예: kill -15 [PID] 또는 단순히 kill [PID])
  9. 그레이스풀 셧다운(Graceful Shutdown):
    • SIGTERM은 그레이스풀 셧다운을 구현하는 데 주로 사용됩니다. 이는 프로세스가 진행 중인 작업을 완료하고 리소스를 정리한 후 종료되도록 합니다.

SIGTERM은 프로세스를 안전하게 종료하기 위한 표준적인 방법으로, 시스템 관리와 애플리케이션 개발에서 중요한 역할을 합니다.

간단한 코드로 수행해 보기

코드

import signal
import time
import sys

def signal_handler(signum, frame):
    print("Received SIGTERM. Cleaning up...")
    # 여기에 정리 작업을 수행하는 코드를 작성합니다.
    # 예: 파일 닫기, 네트워크 연결 종료 등
    print("Cleanup finished. Exiting.")
    sys.exit(0)

def main():
    # SIGTERM 신호에 대한 핸들러 등록
    signal.signal(signal.SIGTERM, signal_handler)

    print("Process started. PID:", os.getpid())
    print("Press Ctrl+C to exit")

    try:
        # 무한 루프로 프로세스 실행 상태 유지
        while True:
            time.sleep(1)
    except KeyboardInterrupt:
        print("Received KeyboardInterrupt. Exiting.")

if __name__ == "__main__":
    main()

결과

  • kill -TERM <PID>를 수행한 경우 (-15도 가능하다.)

  • kill -9 <PID> 를 수행한 경우

SIGTERM 무시 및 다른 대안으로 교체

SIGTERM을 무시하거나 다른 작업을 수행하도록 만들어보는 경우에 다음 명령을 사용할 수 있다.

import signal

# SIGTERM 신호를 무시하도록 설정
signal.signal(signal.SIGTERM, signal.SIG_IGN)
import signal
import sys

def sigterm_handler(signum, frame):
    print("SIGTERM 신호를 받았지만, 프로그램을 계속 실행합니다.")

signal.signal(signal.SIGTERM, sigterm_handler)

참고

SIGKILL vs SIGTERM 리눅스 종료 신호

 

SIGKILL vs SIGTERM 리눅스 종료 신호

우리가 만든 서버 프로그램은 리눅스 서버의 한 프로세스로 동작 합니다.고로, 프로세스로 구동하는 모든 프로그램들, 예) 도커, nginx, node.js, Mysql 등의 종료에 관한 메커니즘을 이해 한다면, 장

velog.io

블로그 내용을 위해서 간단하더라도 양을 많이 채워보자라는 느낌으로 글들을 작성했다.

생각보다 더 조회수는 나오지 않았고, 특정 포스팅에 조회가 몰리는 현상이 발생했다.

 

또한 글을 작성하면서 만족스럽지 못한 퀄리티에 실망했던 적도 많았다.(특히 TIL)

 

TIL이 무슨 소용일까 어차피 매일 공부하고 기록하는데

차라리 블로그에는 알찬 정보들로 구성해서 내가 두고두고 다시 보아도 도움이 되는 글들을 만들어 놓는 것이 좋을 것이라 판단했다.

특히 TIL의 경우 카테고리 선정이 꽤나 힘들었고 자료를 다시 찾는 과정도 불편했다.

 

이제는 포스팅 주기는 길지만 알찬 포스팅으로 준비해보려한다.

어차피 공부용 블로그지만 다른 분들도 좋은 포스팅을 함께 보는 게 더 낫지 않을까 싶다.

'Others > 일상' 카테고리의 다른 글

Snowflake ascent 참가 후기  (0) 2024.04.25
기존 블로그 주소  (0) 2024.04.24
Data Engineering Zoomcamp  (0) 2024.03.18
일상?  (0) 2024.03.15

요즘 SQL 문제를 많이 풀고있다. 맞춰서 게시글도 자주 올리는 편이다.

그래서 자동화를 해보면 어떨까..? 라는 생각이 들었는데 마침? llama3가 떠버렸고,

qwen2라는 알리바바의 더 좋은 모델이 있다길래 한번 적용해서 진행하게 되었다. (...???)

 

우선 프로젝트를 어떻게 진행했는지 소개하려한다.

프로젝트 진행 순서

1. llama3 & qwen2 을 사용하기

우선 핵심적인 부분을 진행하기로했다.

바로 llama3나 qwen2를 로컬에서 사용해보는 것이다. 오..

이를 위해서 ollama를 사용하는 방법에 대해서 찾게 되었고, 매우 편하게 llm 모델을 실행할 수 있게 되었다.

설치 과정에 대해서는 좋은 블로그글이 많아서 따로 적지는 않으려한다. (아래는 참고)

https://brunch.co.kr/@b2439ea8fc654b8/28

 

Ollama + Llama 3 사용법

ollama  + llama3 를 통해서 나만의 노래가사를 만드는 챗봇 | 기업이 생성형 AI를 도입하는 데 있어 가장 우려하는 것은 바로 비용과 보안 문제입니다. 로컬에서 LLM을 실행함으로써 기업들은

brunch.co.kr

 

2. 내 SQL 코드 리뷰해줘.

처음 사용방식이 chat 방식이여서 이것을 그대로 사용할수는 없겠다 라는 생각이 들었다.

그래서? API로 접근하는 방식을 채용했다. request 모듈을 활용하였는데 코드는 다음과 같다.

# Ollama API 서버의 URL
url = 'http://localhost:11434/api/generate'

# 요청에 사용할 데이터
data = {
    "model": "qwen2",
    "prompt":""
    }
# HTTP POST 요청 보내기 (스트리밍 응답 받기)
response = requests.post(url, json=data, stream=True)

# 응답 본문을 한 줄씩 처리
translated_text = ""

try:
    for line in response.iter_lines():
        if line:
            # 각 줄을 JSON으로 파싱
            line_data = json.loads(line.decode('utf-8'))
            # 응답에서 'response' 키의 값을 추가
            translated_text += line_data.get('response', '')
except json.JSONDecodeError as e:
    print("JSON decode error:", e)

 

답변을 받아서 파일로 저장하는 방식으로 진행했다.

그래서 적절한 프롬프트를 작성하였는데.. 이게 이렇게 어려울줄은 몰랐다. 아무래도 프롬프트 엔지니어링 책을 읽어봐야할 듯 싶다.

결과는 성공! 내 SQL에 대해서 꽤나 괜찮은 리뷰를 받을 수 있었다.

 

3. Github내 코드 가져오기

현재 LeetHub를 사용해서 내가 풀이한 것이 정답이면 github에 자동으로 commit되도록 진행하고있다.

커밋된 내용에는 내가 풀이한 SQL 코드와 문제에 대한 간단한 내용이 담겨있다.

그럼 이제 무엇을 해야할까?

바로 가장 최신 커밋을 찾아서 파일을 가져오는 것이다. 이를 프롬프트에 넣고 결과값을 md파일로 출력하면된다.

코드는 다음과 같다.

def get_latest_commit_sha(repo_owner, repo_name):
    url = f"https://api.github.com/repos/{repo_owner}/{repo_name}/commits"
    params = {'per_page': 1}  # 최근 커밋 하나만 가져오기 위한 파라미터

    try:
        response = requests.get(url, params=params)
        response.raise_for_status()  # HTTP 요청 오류 확인

        commit_data = response.json()[0]
        sha = commit_data['sha']
        return sha
        
    except requests.exceptions.RequestException as e:
        print(f"Error fetching data from GitHub API: {e}")
        return None
    
def get_latest_commit_file(repo_owner, repo_name):
    latest_sha = get_latest_commit_sha(repo_owner, repo_name)
    url = f"https://api.github.com/repos/{repo_owner}/{repo_name}/commits/{latest_sha}"
    try:
        response = requests.get(url)
        response.raise_for_status()  # HTTP 요청 오류 확인

        commit_data = response.json()
        files = commit_data['files']
        if files:
            latest_file_name = files[0]['filename']
            return latest_file_name
        else:
            return None  # 커밋에 파일이 없는 경우
        
    except requests.exceptions.RequestException as e:
        print(f"Error fetching data from GitHub API - sha: {e}")
        return None

owner = 'poriz'
repo_name = 'leetcode'
latest_file = get_latest_commit_file(owner,repo_name)
# 예시: 'owner'와 'repo_name'을 실제 레포지토리의 소유자와 이름으로 변경해야 합니다.

level = re.search(r'LeetCode/(.*?)/', latest_file).group(1)
pattern = rf'{level}\/(.*?)\/'
problem_num = re.search(pattern, latest_file).group(1)

# warning!!
token = 'your_git_token'
headers = {'Authorization': 'token ' + token}
# warning!!
# input leetcode data
git_md = f'https://raw.githubusercontent.com/{owner}/leetcode/main/LeetCode/{level}/{problem_num}/README.md'
res = requests.get(git_md,headers=headers)
description = BeautifulSoup(res.content, 'html.parser')

solved_codes = f'https://raw.githubusercontent.com/{owner}/leetcode/main/LeetCode/{level}/{problem_num}/{problem_num}.sql'
res = requests.get(solved_codes,headers=headers)
my_code = BeautifulSoup(res.content, 'html.parser')

 

중간에 warning은 github accesstoken 때문에 사용하였다. (키값 주의!)

코드에 대해서 간단하게 설명한다면..?

github-api를 이용해서 첫 커밋의 sha를 가져온다. 이 sha를 이용해서 commit에 무슨일이 있었는지를 확인 가능한데

다시 api에 이 sha를 넣어 호출해보면 file 정보를 가져올 수 있다.

 

자 이제 file 정보에 level과 문제의 이름이 있기 때문에 이를 자동으로 파싱해서 request에 적당한 url로 넣어주면된다.

코드를 가져가셔서 사용하신다면 변수에 주의해주세요~

 

전체 코드는 깃헙에 올려두었습니다.

https://github.com/poriz/leetcode_blog_auto/blob/main/sql_model1.py

 

leetcode_blog_auto/sql_model1.py at main · poriz/leetcode_blog_auto

Contribute to poriz/leetcode_blog_auto development by creating an account on GitHub.

github.com

 


아직은 프롬프트도 조금 문제고 보완해야할 문제가 많다. 가능하다면 commit을 감지해서 md파일 생성도 자동으로 진행하고 싶었지만, llm모델이 돌아가기에는 약간의 금전적 이슈가있어 로컬로 진행하였다.

그리고 이제 당분간 SQL 리뷰의 경우에는 LLM으로 생성된 버전이 같이 올라갈 것이다. 쉬운 문제의 경우에는 이를 적극 활용할것이고, 조금 어렵거나 배울 것이 많은 문제의 경우에는 별도 포스팅 혹은 내용적으로 추가가 들어갈 계획이다.

snowflake ascent - korea에 참가했다.

snowflake에 대해서 막연하게만 알고있었는데

많은 것들을 경험할 수 있었던 좋은 기회였다.

 

Snowflake free trial을 이용해서 다양한 실습을 진행하고 배워보는 시간이였는데

과거 snowflake를 간단하게 사용한 기억을 되짚어가면서 기초를 다시한번 다질 수 있었다.

 

간단하게 snowflake 소개(당연..?)부터 Role을 지정하고, 스키마생성, 데이터 적재, Staging을 해보고

정형 데이터 뿐 아니라 반정형 데이터도 다루어보는 시간을 가졌다.

 

Json을 올리는 과정이 신기했는데 Glue Script를 이용해서 중첩된 Json을 Spark로 풀어봤던 과정을

간단하게 SQL을 이용하면서 진행하는 것이 인상깊었다.

 

생각보다 일상글은 가운데 정렬이 보기 편한 느낌이다.

이번에 이런 행사를 처음 접해봤는데 정말 재미있었다.

중간에 점심도 제공해줘서 이거 정말 갈만한걸?

조금 많이 찾아보고 참석해봐야겠다. 새로운 것들을 배워가는 재미가 쏠쏠하다.

 

'Others > 일상' 카테고리의 다른 글

블로그의 방향성 재조정  (0) 2024.09.06
기존 블로그 주소  (0) 2024.04.24
Data Engineering Zoomcamp  (0) 2024.03.18
일상?  (0) 2024.03.15

+ Recent posts