카테고리 없음2025. 5. 14. 14:17

SLA, SLO, SLI는 서비스 품질 및 성능을 측정하고 관리하는 핵심 개념입니다. 각각의 의미를 이해하고 차이점을 비교해 보겠습니다.

1. 정의

  • SLA (Service Level Agreement, 서비스 수준 협약)
    • 서비스 제공자와 고객 간의 공식적인 계약으로, 서비스의 가용성, 성능, 지원 수준 등을 명확하게 정의함.
    • SLA가 충족되지 않으면 보상(환불, 크레딧 제공 등)이 발생할 수 있음.
  • SLO (Service Level Objective, 서비스 수준 목표)
    • SLA를 달성하기 위한 내부 목표로, 서비스의 성능 및 가용성을 측정하는 기준이 됨.
    • SLA보다 더 엄격한 목표를 설정하여 서비스 품질을 유지하는 데 도움을 줌.
  • SLI (Service Level Indicator, 서비스 수준 지표)
    • SLO를 평가하기 위한 측정 가능한 지표로, 서비스의 성능을 수치화하여 모니터링함.
    • 예: 응답 시간, 오류율, 가용성(%) 등

2. SLA, SLO, SLI 비교표

항목SLA (서비스 수준 협약)SLO (서비스 수준 목표)SLI (서비스 수준 지표)
목적 고객과의 계약 내부 목표 설정 성능 측정
대상 고객 내부 운영팀 기술팀, 모니터링 시스템
내용 서비스 가용성, 성능, 지원 수준 SLA를 달성하기 위한 목표 서비스 품질을 측정하는 지표
예시 "서비스 가용성 99.9% 보장" "서비스 가용성 99.95% 유지 목표" "지난 30일 동안의 실제 가용성 99.96%"
위반 시 영향 고객 보상 (환불, 크레딧 제공) 내부 개선 필요 모니터링 및 조치

3. 예제 시나리오

✅ SLA 예시 (고객과의 계약)

> "우리 서비스는 월간 99.9% 가용성을 보장합니다. 이를 충족하지 못하면 고객에게 크레딧을 제공합니다."

✅ SLO 예시 (내부 목표)

> "서비스의 가용성을 99.95% 이상 유지하는 것을 목표로 합니다."

✅ SLI 예시 (실제 측정 지표)

> "지난 30일 동안의 서비스 가용성은 99.96%였습니다."

4. 결론

  • SLA는 고객과의 계약이며, 서비스 품질을 보장하는 공식적인 약속입니다.
  • SLO는 SLA를 달성하기 위한 내부 목표로, 서비스 운영팀이 설정합니다.
  • SLI는 실제 서비스 성능을 측정하는 지표로, SLO가 잘 유지되고 있는지 확인하는 역할을 합니다.

👉 SLA → SLO → SLI 순서로 연결되며, 서비스 품질을 유지하고 개선하는 데 중요한 개념입니다!

반응형
Posted by 컴투
카테고리 없음2025. 5. 14. 12:01

Prometheus는 오픈소스 모니터링 및 경보 시스템으로, 주로 시계열 데이터(time-series data) 수집 및 분석에 사용됩니다. CNCF(Cloud Native Computing Foundation) 프로젝트이며, Kubernetes 환경에서 모니터링할 때 가장 널리 사용되는 도구 중 하나입니다.


🧭 Prometheus 정의

Prometheus는 메트릭 데이터를 Pull 방식으로 수집하며, 시계열 데이터 저장, 쿼리, 경고(Alerting)를 지원하는 모니터링 도구입니다.


🧩 Prometheus 구성요소

구성요소설명
Prometheus 서버 메트릭을 수집(Pull), 저장(TSDB), 쿼리(PromQL)
Exporter 애플리케이션/시스템에서 메트릭을 노출하는 HTTP 엔드포인트
Push Gateway 단기 작업(batch job)이 Push 방식으로 메트릭 전송 시 사용
Alertmanager 경고 조건이 발생했을 때 알림(이메일, 슬랙 등)을 전송
PromQL Prometheus 고유의 쿼리 언어로 메트릭을 필터링/분석
Service Discovery 동적으로 타겟을 찾아 메트릭을 수집 (ex. Kubernetes, Consul 등)
Storage (TSDB) 시계열 데이터 저장소 (내장 Time Series DB 사용)
 

🏗️ Prometheus 구조

lua
복사편집
+------------------+ | Web UI / API | +--------+---------+ | +-------v--------+ | Prometheus | ← 핵심 컴포넌트 | - TSDB | | - Scraper | | - PromQL | +-------+--------+ | +-----------+-------------+ | | +-------v--------+ +-------v--------+ | Exporter (Node)| ... | Exporter (App) | +----------------+ +----------------+ | +-------v-------+ | Alertmanager | +---------------+

주요 흐름:

  1. Prometheus는 **설정된 타겟(exporter)**에 주기적으로 접속하여 메트릭 데이터를 Pull.
  2. 수집된 데이터는 내부 TSDB에 저장됨.
  3. 사용자는 PromQL로 데이터를 조회하거나 시각화 도구(Grafana 등)와 연동.
  4. 사전 정의된 조건을 만족하는 경우 Alertmanager를 통해 경보 발생.

🔧 Exporter 예시

Exporter수집 대상
Node Exporter 리눅스 시스템 메트릭 (CPU, 메모리 등)
Blackbox Exporter 네트워크/HTTP 상태 확인 (ping, http)
MySQL Exporter MySQL DB 성능/상태
Custom Exporter 직접 작성한 앱에서 메트릭 노출
 

🛠️ 데이터 수집 방식: Pull vs Push

방식설명
Pull Prometheus가 메트릭을 주기적으로 가져옴 (기본 방식)
Push Push Gateway를 통해 수집 (주로 batch job용)
 

필요하시면 prometheus.yml 설정 예제나 Node Exporter 설치 방법도 도와드릴 수 있어요. 어떤 환경에서 Prometheus를 쓰시려 하나요? (예: 쿠버네티스, VM 등)

반응형
Posted by 컴투
카테고리 없음2025. 5. 14. 11:22

Prometheus는 오픈소스 모니터링 및 경보 시스템으로, 주로 시계열 데이터(time-series data) 수집 및 분석에 사용됩니다. CNCF(Cloud Native Computing Foundation) 프로젝트이며, Kubernetes 환경에서 모니터링할 때 가장 널리 사용되는 도구 중 하나입니다.


🧭 Prometheus 정의

Prometheus는 메트릭 데이터를 Pull 방식으로 수집하며, 시계열 데이터 저장, 쿼리, 경고(Alerting)를 지원하는 모니터링 도구입니다.


🧩 Prometheus 구성요소

구성요소설명
Prometheus 서버 메트릭을 수집(Pull), 저장(TSDB), 쿼리(PromQL)
Exporter 애플리케이션/시스템에서 메트릭을 노출하는 HTTP 엔드포인트
Push Gateway 단기 작업(batch job)이 Push 방식으로 메트릭 전송 시 사용
Alertmanager 경고 조건이 발생했을 때 알림(이메일, 슬랙 등)을 전송
PromQL Prometheus 고유의 쿼리 언어로 메트릭을 필터링/분석
Service Discovery 동적으로 타겟을 찾아 메트릭을 수집 (ex. Kubernetes, Consul 등)
Storage (TSDB) 시계열 데이터 저장소 (내장 Time Series DB 사용)
 

🏗️ Prometheus 구조

lua
복사편집
+------------------+ | Web UI / API | +--------+---------+ | +-------v--------+ | Prometheus | ← 핵심 컴포넌트 | - TSDB | | - Scraper | | - PromQL | +-------+--------+ | +-----------+-------------+ | | +-------v--------+ +-------v--------+ | Exporter (Node)| ... | Exporter (App) | +----------------+ +----------------+ | +-------v-------+ | Alertmanager | +---------------+

주요 흐름:

  1. Prometheus는 **설정된 타겟(exporter)**에 주기적으로 접속하여 메트릭 데이터를 Pull.
  2. 수집된 데이터는 내부 TSDB에 저장됨.
  3. 사용자는 PromQL로 데이터를 조회하거나 시각화 도구(Grafana 등)와 연동.
  4. 사전 정의된 조건을 만족하는 경우 Alertmanager를 통해 경보 발생.

🔧 Exporter 예시

Exporter수집 대상
Node Exporter 리눅스 시스템 메트릭 (CPU, 메모리 등)
Blackbox Exporter 네트워크/HTTP 상태 확인 (ping, http)
MySQL Exporter MySQL DB 성능/상태
Custom Exporter 직접 작성한 앱에서 메트릭 노출
 

🛠️ 데이터 수집 방식: Pull vs Push

방식설명
Pull Prometheus가 메트릭을 주기적으로 가져옴 (기본 방식)
Push Push Gateway를 통해 수집 (주로 batch job용)
 

필요하시면 prometheus.yml 설정 예제나 Node Exporter 설치 방법도 도와드릴 수 있어요. 어떤 환경에서 Prometheus를 쓰시려 하나요? (예: 쿠버네티스, VM 등)

반응형
Posted by 컴투
카테고리 없음2025. 5. 14. 11:21

OpenTelemetry와 Elasticsearch는 목적과 기능이 완전히 다르며, 직접적인 비교보다는 서로 보완적인 관계로 이해하는 것이 맞습니다. 아래는 두 기술의 역할과 차이점, 그리고 함께 사용하는 방식에 대한 설명입니다.


🔍 개요

항목OpenTelemetryElasticsearch
종류 Observability 도구 (오픈소스 표준) 검색 및 분석 엔진 (오픈소스)
목적 애플리케이션의 메트릭, 로그, 트레이싱 데이터 수집 수집된 데이터의 저장, 검색, 시각화
역할 데이터를 수집하고 전송 데이터를 저장, 검색, 분석
주요 사용처 분산 트레이싱, 성능 모니터링 로그 저장, Kibana 시각화, 검색 기능
연동 예시 OpenTelemetry Collector → Elasticsearch OpenTelemetry Exporter → Elasticsearch
 

🧩 주요 차이점

구분OpenTelemetryElasticsearch
데이터 수집 직접적으로 애플리케이션 코드에 붙어 동작 수집 기능 없음 (다른 도구 필요)
데이터 저장 저장 안 함 (전송만) 대규모 데이터 저장 및 인덱싱
데이터 처리 방식 실시간 스트리밍 (Collector, Exporter 구조) 쿼리 기반 분석 및 시각화
시각화 도구 없음 (외부 도구 필요) Kibana (Elasticsearch 공식 UI)
 

🔗 함께 사용하는 방식

OpenTelemetry를 Elasticsearch와 함께 사용할 수 있습니다.

예:

  1. OpenTelemetry SDK를 애플리케이션에 설정
  2. OpenTelemetry Collector에서 로그/메트릭/트레이스를 수집
  3. Exporter를 통해 데이터를 Elasticsearch로 전송
  4. Kibana를 통해 시각화
nginx
복사편집
App → OpenTelemetry SDK → Collector → Elasticsearch → Kibana

📝 선택 포인트

  • **OpenTelemetry는 ‘관측 데이터 수집 표준’**입니다. 다양한 백엔드로 데이터를 전송 가능 (예: Elasticsearch, Prometheus, Jaeger 등).
  • **Elasticsearch는 ‘데이터 저장소 및 검색 엔진’**이며, OpenTelemetry를 포함한 다양한 소스에서 수집된 데이터를 저장하고 분석할 수 있습니다.
반응형
Posted by 컴투
카테고리 없음2025. 5. 14. 11:15

GraphQL이란?

GraphQL은 API를 위한 쿼리 언어(Query Language)이자, 데이터를 효율적으로 요청하고 가져올 수 있도록 설계된 런타임(runtime)입니다. Facebook에서 2012년에 개발하여 2015년에 오픈소스로 공개되었습니다.

GraphQL의 주요 특징

  1. 클라이언트가 원하는 데이터만 요청 가능
    • REST API에서는 정해진 엔드포인트에서 고정된 데이터 구조를 반환하지만, GraphQL에서는 클라이언트가 필요한 데이터만 선택하여 요청할 수 있습니다.
  2. 단일 엔드포인트 (/graphql)
    • REST API는 여러 엔드포인트(/users, /posts 등)를 사용하지만, GraphQL은 하나의 엔드포인트에서 다양한 데이터를 요청할 수 있습니다.
  3. 계층적 데이터 구조
    • GraphQL은 JSON 형태로 데이터를 반환하며, 요청한 데이터의 구조와 동일한 형태로 응답을 받을 수 있습니다.
  4. 강력한 타입 시스템
    • GraphQL은 스키마(schema)를 기반으로 동작하며, 데이터 타입을 명확하게 정의할 수 있습니다.
  5. Over-fetching & Under-fetching 문제 해결
    • REST API에서는 불필요한 데이터를 가져오는 Over-fetching과 필요한 데이터가 부족한 Under-fetching 문제가 발생할 수 있지만, GraphQL에서는 이를 방지할 수 있습니다.

GraphQL vs REST API 비교

항목GraphQLREST API
데이터 요청 방식 필요한 데이터만 요청 가능 고정된 응답 구조
엔드포인트 단일 엔드포인트 (/graphql) 여러 개의 엔드포인트
데이터 구조 계층적 구조 개별 리소스 기반
Over-fetching 문제 해결 가능 발생 가능
Under-fetching 문제 해결 가능 발생 가능
타입 시스템 강력한 스키마 기반 일반적으로 없음

GraphQL 예제

1. 요청(Query)

클라이언트가 특정 사용자 정보를 요청할 때, 필요한 필드만 선택할 수 있습니다.

graphql
query {
  user(id: "1") {
    name
    email
    posts {
      title
      content
    }
  }
}

2. 응답(Response)

서버는 요청한 데이터만 반환합니다.

json
{
  "data": {
    "user": {
      "name": "Alice",
      "email": "alice@example.com",
      "posts": [
        {
          "title": "GraphQL 소개",
          "content": "GraphQL은 API를 위한 쿼리 언어입니다."
        }
      ]
    }
  }
}

GraphQL의 장점

유연한 데이터 요청 → 필요한 데이터만 가져올 수 있음 ✅ 네트워크 요청 감소 → 여러 리소스를 한 번에 가져올 수 있음 ✅ 강력한 타입 시스템 → API의 안정성을 높일 수 있음 ✅ 빠른 개발 속도 → 프론트엔드 개발자가 원하는 데이터를 쉽게 요청 가능

GraphQL의 단점

캐싱이 어렵다 → REST API처럼 HTTP 캐싱을 활용하기 어려움 ❌ 복잡한 쿼리 최적화 필요 → 잘못 설계하면 성능 저하 가능 ❌ 학습 곡선이 존재 → REST API보다 개념이 복잡할 수 있음

결론

GraphQL은 유연한 데이터 요청최적화된 API 설계가 필요한 경우 매우 유용한 기술입니다. 특히, 프론트엔드 개발자가 원하는 데이터를 효율적으로 가져올 수 있어 모바일 앱, SPA(Single Page Application) 개발에서 많이 사용됩니다.

반응형
Posted by 컴투
카테고리 없음2025. 5. 14. 11:08

FF(Backend for Frontend) vs. Materialized View 차이점 정리

정의

  • BFF(Backend for Frontend): 특정 프론트엔드 애플리케이션을 위해 맞춤형으로 설계된 백엔드 서비스로, 여러 마이크로서비스의 데이터를 조합하여 최적화된 API를 제공하는 역할을 함.
  • Materialized View: 데이터베이스에서 특정 쿼리 결과를 미리 저장하여 빠르게 조회할 수 있도록 하는 구조로, 성능 최적화를 위해 사용됨.

차이점 비교표

항목BFF (Backend for Frontend)Materialized View
개념 특정 프론트엔드를 위한 맞춤형 백엔드 서비스 미리 저장된 쿼리 결과를 제공하는 데이터베이스 객체
목적 프론트엔드 요청을 최적화하여 API 제공 데이터 조회 성능 향상
사용 위치 애플리케이션 백엔드 데이터베이스
주요 기능 API 조합, 데이터 가공, 성능 최적화 쿼리 결과 저장, 빠른 조회
갱신 방식 실시간 요청 처리 주기적으로 Refresh
성능 최적화 방식 네트워크 요청 감소, API 응답 최적화 복잡한 쿼리 결과를 미리 저장하여 조회 속도 향상

결론

  • BFF는 API 설계 및 데이터 제공 방식에 관한 것이고,
  • Materialized View는 데이터 저장 및 조회 최적화에 관한 것입니다.

즉, BFF는 애플리케이션 아키텍처에서 API를 최적화하는 역할을 하고, Materialized View는 데이터베이스에서 쿼리 성능을 향상시키는 역할을 합니다.

반응형
Posted by 컴투
프로그래밍/기타...2018. 3. 7. 09:45

참고 : https://blog.naver.com/powerms100/120008462157


자세한 설정내용은 위 블로그를 참고하셔도 좋습니다.


==========================================================================================

rem oracle backup 

@echo off

SET ORACLE_SID=ORAGEO

SET MONTH=%date:~5,2%

SET YEAR=%date:~0,4%

for %%a in (%date%) do SET day=%%a

md D:\DB백업\%YEAR%\%MONTH%\dmp

md D:\DB백업\%YEAR%\%MONTH%\log

C:\oracle\product\10.2.0\db_1\BIN\EXP 아이디/비번 file=D:\DB백업\%YEAR%\%MONTH%\dmp\%DAY%.dmp log=D:\DB백업\%YEAR%\%MONTH%\log\%DAY%backuplog.txt

rem 매일 새벽 5시에 export 받는 작업 예약하기

rem C:\> at 05:00 /every:Su,M,T,W,Th,F,S D:\bak\bat\oracle_exp.bat

==========================================================================================

사실 위와같은 내용으로 사용중에 오라클DB백업을 사용중에 있는것을 확인하였는데, 

인터넷을 검색하니 위 내용으로 예시가 올라와 있더라구요ㅎ 

배치파일은 위 내용을 포함하는 .bat 파일을 만들어 주면 됩니다. 

위 내용을 만들어진 만들어진 .bat 파일을 스케줄러에 등록해야하는데요 아래와 같이 등록을 합니다.


1. 윈도우 -> 실행 , 사진과같이 검색하여 '작업 스케줄러'를 살행




2. 실행 된 작업 스케줄러 '작업 스케줄러 라이브러리' 에 오른버튼을 이용하여 '작업만들기' 실행




3. '새 작업 만들기' 창이 뜨면 이름에 설정하고자 하는 내용을 기록



4.  트리커 탭에서 '새로 만들기' 선택



5. '새 트리가 만들기' 화면이 뜨면 '설정' 부분을 설정한다.

- 한번, 매일, 매주, 매월

- 시작 시간 설정



5. 동작 탭으로 이동하여 '새로 만들기' 선택



6. 실행 된 '새 동작 만들기' 창에서 '설정-찾아보기' 버튼을 이용하여 .bat 파일을 선택하고 '확인버튼' 선택



7. 아래와 같이 스케줄이 등록 된 것을 확인할 수 있다. 




8. 설정 된 시간에 dump 파일이 잘 생성됨을 확인 할 수 있음 . 끝~~~~~


반응형
Posted by 컴투
프로그래밍/C/C++2018. 3. 6. 11:05

부록 G. 도스(DOS) 배치 파일을 쉘 스크립트로 변환

아주 많은 프로그래머들은 PC 위에서 도는 도스에서 스크립트를 배웠습니다. 기능이 조금 떨어지는 도스 배치 파일 언어로도 꽤 강력한 스크립트나 어플리케이션을 작성할 수도 있지만 그렇게 하려면 아주 해박한 지식을 사용해 해결책을 찾거나 꽁수를 부려야 합니다. 가끔은 오래된 도스용 배치 파일을 유닉스 쉘 스크립트로 변환해서 써야될 경우가 생기지만 이렇게 하는것이 그렇게 어렵지만은 않습니다. 왜냐하면 도스 배치 파일 연산자들이 기능이 동일한 쉘 스크립트 연산자의 서브셋에 불과하기 때문입니다.

표 G-1. 배치 파일 키워드/변수/연산자 와 그에 해당하는 쉘 동의어

배치 파일 연산자쉘 스크립트 동의어
%$명령어줄 매개변수 접두사
/-명령어 옵션 플래그
\/디렉토리 패스 구분자
===(같음) 문자열 비교 테스트
!==!!=(다름) 문자열 비교 테스트
||파이프
@set +v현재 명령어를 에코하지 말 것
**파일명 "와일드 카드"
>>파일 재지향(덮어 쓰기)
>>>>파일 재지향(덧붙여 쓰기)
<<표준입력 재지향
%VAR%$VAR환경 변수
REM#주석
NOT!뒤에 나오는 테스트 부정
NUL/dev/null명령어 출력을 없애기 위한 "블랙홀"
ECHOecho에코 (Bash 에는 옵션이 많이 있음)
ECHO.echo빈 줄 에코
ECHO OFFset +v다음에 나오는 명령어를 에코하지 말 것
FOR %%VAR IN (LIST) DOfor var in [list]; do"for" 루프
:LABEL없음 (필요치 않음)라벨
GOTO없음 (대신 함수를 씀)스크립트의 다른 곳으로 건너 뜀
PAUSEsleep일정 간격을 두고 잠시 대기
CHOICEcase 나 select메뉴 선택
IFifif-test
IF EXIST FILENAMEif [ -e filename ]파일이 존재하는지 확인
IF !%N==!if [ -z "$N" ]변경가능한 매개변수인 "N"이 없다면
CALLsource 나 . (도트 연산자)다른 스크립트를 "포함"
COMMAND /Csource 나 . (도트 연산자)다른 스크립트를 "포함"(CALL과 동일)
SETexport환경 변수를 세트
SHIFTshift명령어줄 변수 목록을 왼쪽으로 이동(shift)
SGN-lt or -gt(정수) 부호(sign)
ERRORLEVEL$?종료 상태
CONstdin"콘솔"(표준입력)
PRN/dev/lp0(일반적인) 프린터 디바이스
LP1/dev/lp0첫번째 프린터 디바이스
COM1/dev/ttyS0첫번째 시리얼 포트

배치 파일은 대개 도스 명령어를 갖고 있습니다. 도스용 배치 파일이 쉘 스크립트로 변환되기 위해서는 이 명령어들은 꼭 동일한 유닉스 명령어로 변환되어야 합니다.

표 G-2. 도스 명령어와 동일한 유닉스 명령어

도스 명령어동일한 유닉스 명령어효과
ASSIGNln파일이나 디렉토리를 링크
ATTRIBchmod파일 퍼미션 변경
CDcd디렉토리 변경
CHDIRcd디렉토리 변경
CLSclear스크린 지우기
COMPcmp or diff파일 비교
COPYcp파일 복사
Ctl-CCtl-C정지(시그널)
Ctl-ZCtl-DEOF (end-of-file)
DELrm파일 삭제
DELTREErm -rf디렉토리의 하위 디렉토리까지 포함해서 삭제
DIRls -l디렉토리 보이기
ERASErm파일 삭제
EXITexit현재 프로세스 종료
FCcomm, cmp파일 비교
FINDgrep파일안에서 문자열 찾기
MDmkdir디렉토리 생성
MKDIRmkdir디렉토리 생성
MOREmore텍스트 파일 쪽단위(paging) 필터
MOVEmv이동
PATH$PATH실행파일들의 경로
RENmv이름 바꾸기(이동)
RENAMEmv이름 바꾸기(이동)
RDrmdir디렉토리 삭제
RMDIRrmdir디렉토리 삭제
SORTsort파일 정렬
TIMEdate시스템 시간 보여주기
TYPEcat파일을 표준출력으로 출력
XCOPYcp(확장) 파일 복사

참고: 사실 모든 유닉스, 쉘 연산자, 명령어들은 그들과 동일한 도스용보다 많은 옵션과 강력한 기능을 갖고 있습니다. 많은 배치 파일 스크립트들은 read의 불완전한 버전인 ask.com같은 외부 유틸리티에 의존합니다.

도스는 파일명 와일드 카드 확장에 대해서 오직 *과 ? 문자만을 인식하는 제한되고 부족한 서브셋을 지원합니다.

도스 배치 파일을 쉘 스크립트로 변환하는 것은 일반적으로 매우 간단하고 가끔은 변환된 쉘 스크립트가 원래 도스 배치 파일보다 더 이해하기 쉬운 경우도 있습니다.

예 G-1. VIEWDATA.BAT: 도스용 배치 파일

REM VIEWDATA

REM PAUL SOMERSON의 "DOS POWERTOOLS"의 예제에서 영감을 받아 작성


@ECHO OFF

IF !%1==! GOTO VIEWDATA
REM  명령어줄 인자가 없다면...
FIND "%1" C:\BOZO\BOOKLIST.TXT
GOTO EXIT0
REM  문자열이 일치하는 줄을 출력후 종료.

:VIEWDATA
TYPE C:\BOZO\BOOKLIST.TXT | MORE
REM  한 번에 한 쪽씩 전체 파일을 보여줌.

:EXIT0

스크립트 변환을 하면 기능이 다소 개량됩니다.

예 G-2. viewdata.sh: VIEWDATA.BAT 의 스크립트 버전

#!/bin/bash
# VIEWDATA.BAT 를 쉘 스크립트로 변환.

DATAFILE=/home/bozo/datafiles/book-collection.data
ARGNO=1

# @ECHO OFF       여기서 이 명령어는 필요없습니다.

if [ $# -lt "$ARGNO" ]    # IF !%1==! GOTO VIEWDATA
then
  less $DATAFILE          # TYPE C:\MYDIR\BOOKLIST.TXT | MORE
else
  grep "$1" $DATAFILE     # FIND "%1" C:\MYDIR\BOOKLIST.TXT
fi  

exit 0                    # :EXIT0

# GOTO, 라벨, 속임수, 엉터리 구문등이 필요없어졌죠.
# 원래 배치 파일보다 더 짧고, 더 쉽고, 더 깔끔합니다.



참고 : http://wiki.kldp.org/HOWTO/html/Adv-Bash-Scr-HOWTO/dosbatch.html

반응형
Posted by 컴투
프로그래밍/C/C++2013. 8. 13. 14:13

내가 만드는 프로그램을 항상 하나만 실행하도록 하려면 어떻게 해야 하나 ? 그리고 두 번째 실행시에는 먼저 실행되어 있던 프로그램을 앞으로 띄우고 싶다.

만일 프로그램의 캡션이 고정되어 있다든가 사용되는 윈도우의 클래스 이름을 알고 있다면 FindWindow 혹은 FindWindowEx를 사용하면 아주 손쉽게 문제를 해결할 수 있다. 하지만 윈도우의 캡션이 계속적으로 변한다든지 윈도우 클래스 이름을 모르는 경우에는 이것으로 해결책이 되지 못한다. MFC를 사용할 경우가 대표적인데 윈도우 클래스의 이름을 MFC 내부에서 만들어 사용하기 때문에 윈도우 클래스를 직접 등록하여 사용하는 고난도의 기술을 사용하기 이전에는 윈도우 클래스의 이름을 알 수가 없다. 해결책에는 여러 가지 방법이 있겠지만 파일 맵핑 객체를 이용하도록 하겠다. 원래 파일 맵핑 객체의 목적은 여러 프로세스간에 데이터를 주고 받기 위해 사용되며 사용 방식 자체는 기존의 동적 메모리 할당 방식과 흡사하다.
간단히 절차를 설명하면 다음과 같다. 처음 뜨는 프로그램이 정해진 이름의 파일 맵핑 객체(여기서는 이름은 My TestMap)를 만들어 놓는다. 그리고 나서 자신의 메인 윈도우의 핸들을 그 객체에 기록해 놓는다. 이 때 다시 그 프로그램을 실행시키면 이 이름의 파일 맵핑 객체가 있는지 살펴보고 있으면 실행을 중지한다. 그리고 파일 맵핑 객체에 기록되어 있는 윈도우의 핸들값을 읽어서 앞으로 띄워 버린다. 이것이 가능한 이유는 파일 맵핑 객체는 시스템 전역 객체이기 때문이다. 즉 한 프로세스에서 만들어도 다른 프로세스에서 접근할 수 있다. 먼저 항상 하나만 떠 있게 하는 방법을 알아보고 다음으로 기존의 프로그램을 앞으로 띄우는 코드를 알아보도록 하겠다. 사실 아래의 코드를 이해하려면 파일 맵핑 객체에 대해 알아야 하는데 그것 자체에 대한 설명은 생략하기로 하겠다.

항상 하나만 떠 있게 하는 방법
다음 코드를 애플리케이션 클래스의 InitInstance의 선두에 넣는다. 파일 맵핑 객체의 크기를 4바이트로 잡은 이유는 윈도우 핸들이 UINT이고 그 크기가 4바이트이기 때문이다. CreateFileMapping API는 파일 맵핑 객체를 생성할 때 사용되는데, 이름과 크기를 줄 수 있다. 이미 존재하는 이름으로 파일 맵핑 객체를 생성하려고 하면 GetLast Error라는 API를 호출했을 때 ERROR_ALREADY_ EXISTS라는 에러 코드가 리턴된다. 이것으로 먼저 실행된 프로그램이 있는지 알아낼 수 있다.

HANDLE hMapping;

// MyTestMap이란 이름으로 4바이트의 영역을 잡는다
hMapping = CreateFileMapping( (HANDLE) 0xffffffff, NULL,
PAGE_READWRITE, 0, 4, “MyTestMap” );
if (hMapping)
{
if (GetLastError() == ERROR_ALREADY_EXISTS)
// 같은 이름의 파일 맵핑 객체가 존재
{
// 프로그램이 이미 실행중임을 알리는 메시지를 띄운다.
MessageBox( NULL, “이미 실행 중입니다.”, “경고”, MB_OK );
return FALSE;
}
}
위의 코드는 하나의 실행파일을 실행할 수 있는 방법이지만 기존에 실행되어 있는 프로그램을 앞으로 띄우는 일까지 할 수는 없다. 그렇게 하고 싶다면 InitInstance의 코드의 끝 부분에 메인 윈도우의 핸들을 파일 맵핑 객체에 저장하는 코드를 추가한다. 아래의 예는 SDI(Single Document Interface) 혹은 MDI(Multiple Document Interface)형식의 프로젝트인 경우의 예이다. 만일 다이얼로그 기반의 프로젝트라면 아래의 코드는 메인 다이얼로그 클래스의 WM_CREATE 메시지나 OnInitDialog 함수에 추가되어야 한다. CreateFileMapping으로 생성된 파일 맵핑 객체는 MapViewOfFile이란 API를 통해 메모리 포인터로 변환할 수 있다. 즉 할당된 파일 맵핑 객체를 접근할 수 있는 메모리 포인터를 사용해 내용을 읽고 쓰고 할 수 있다.

LPDWORD lpDword;

// Dispatch commands specified on the command line
if (!ProcessShellCommand(cmdInfo))
return FALSE;
// ---------------------------------
// 이번에는 파일 맵핑 객체를 쓰기 모드로 오픈한다.
lpDword=(LPDWORD)MapViewOfFile(hMapping, FILE_MAP_WRITE, 0, 0, 4);
// 메인 윈도우의 핸들을 저장한다.
*lpDword = (DWORD)m_pMainWnd->m_hWnd;
UnmapViewOfFile(lpDword);
// ---------------------------------
m_pMainWnd->ShowWindow(SW_SHOW);
그러면 앞서 살펴보았던 두 번째로 뜨는 프로그램인지 체크하는 코드 부분을 보강해 보자. 두 번째 뜨는 프로그램일 경우에 원래 먼저 떴던 프로그램의 메인 윈도우를 앞으로 내세우는 코드를 추가해 보자.

hMapping = CreateFileMapping( (HANDLE) 0xffffffff, NULL,
PAGE_READWRITE, 0, 32, “MyTestMap” );
if (hMapping)
{
if (GetLastError() == ERROR_ALREADY_EXISTS)
// 같은 이름의 파일 맵핑 객체가 존재
{
// 프로그램이 이미 실행 중임을 알리는 메시지를 띄운다.
MessageBox( NULL, “이미 실행 중입니다.”, “경고”, MB_OK );

// 기존 파일 맵핑 객체를 연다. 기존 파일 맵핑 객체의 선두에 이전 프로그램
// 의 메인 윈도우 핸들이 들어있다. 뒷부분의 코드를 보면 알 것이다.
LPDWORD lpDword;
HWND hWnd;
// 파일 맵핑 객체를 읽기 모드로 오픈한다.
hMapping = OpenFileMapping(FILE_MAP_READ, FALSE,
“MyTestMap”);
// 파일 맵핑 객체 핸들로부터 포인터를 얻어낸다.
lpDword = (LPDWORD)MapViewOfFile(hMapping,
FILE_MAP_READ, 0, 0, 4);
// 저장되어 있던 윈도우 핸들을 얻어낸다.
hWnd = (HWND)*lpDword;

// 윈도우를 전면으로 내세우기 전에 먼저 아이콘 상태에 있을지도 모르는
// 윈도우를 원래 크기로 되돌린다. IsIconic 함수를 호출하여 아이콘 상태
// 여부를 확인해도 될 것이다.
ShowWindow(hWnd, SW_SHOW);
// 윈도우를 전면으로 내세운다.
SetForegroundWindow(hWnd);
// 파일 맵핑 객체를 닫는다.
UnmapViewOfFile(lpDword);
return FALSE;
}
위의 코드에서 윈도우를 전면으로 내세우는데 SetFore groundWindow라는 함수를 사용한다는 것을 기억해 두기 바란다. 이 함수의 인자로는 반드시 메인 윈도우의 핸들을 지정해야 한다. 지금까지 살펴보았던 코드를 다시 전체적으로 정리하면 다음과 같다.

HANDLE hMapping;

hMapping = CreateFileMapping( (HANDLE) 0xffffffff, NULL,
PAGE_READWRITE, 0, 32, “MyTestMap” );
if (hMapping)
{
if (GetLastError() == ERROR_ALREADY_EXISTS)
// 같은 이름의 파일 맵핑 객체가 존재
{
// 프로그램이 이미 실행 중임을 알리는 메시지를 띄운다.
MessageBox( NULL, “이미 실행 중입니다.”, “경고”, MB_OK );

// 기존 파일 맵핑 객체를 연다. 기존 파일 맵핑 객체의 선두에 이전 프로그램의
// 메인 윈도우 핸들이 들어있다. 뒷부분의 코드를 보면 알 것이다.
LPDWORD lpDword;
HWND hWnd;
// 파일 맵핑 객체를 읽기 모드로 오픈한다.
hMapping = OpenFileMapping(FILE_MAP_READ, FALSE,
“MyTestMap”);
// 파일 맵핑 객체 핸들로부터 포인터를 얻어낸다.
lpDword = (LPDWORD)MapViewOfFile(hMapping,
FILE_MAP_READ, 0, 0, 4);
// 저장되어 있던 윈도우 핸들을 얻어낸다.
hWnd = (HWND)*lpDword;

// 윈도우를 전면으로 내세우기 전에 먼저 아이콘 상태에 있을지도 모르는
// 윈도우를 원래 크기로 되돌린다. IsIconic 함수를 호출하여 아이콘
// 상태 여부를 확인해도 될 것이다.
ShowWindow(hWnd, SW_SHOW);
// 윈도우를 전면으로 내세운다.
SetForegroundWindow(hWnd);
// 파일 맵핑 객체를 닫는다.
UnmapViewOfFile(lpDword);

return FALSE;
}
// 이 뒤부터 ------ 까지는 원래 InitInstance 코드
.....
// Dispatch commands specified on the command line
if (!ProcessShellCommand(cmdInfo))
return FALSE;
// --------------
// 다음을 추가한다.
LPDWORD lpDword;

lpDword = (LPDWORD)MapViewOfFile(hMapping, FILE_MAP_WRITE,
0, 0, 4);
*lpDword = (DWORD)m_pMainWnd->m_hWnd;
UnmapViewOfFile(lpDword);
// 이 뒤로는 다시 원래 InitInstance의 코드
m_pMainWnd->ShowWindow(SW_SHOW);
m_pMainWnd->UpdateWindow();



출처 : www.codeland.co.kr

[펌]http://snslab.kangwon.ac.kr/home/?bo_table=openclass&doc=bbs/gnuboard.php&wr_id=132

반응형
Posted by 컴투
프로그래밍/C/C++2013. 7. 10. 08:59

원래 thread 함수 내부에서는 Updatedata를 사용할 수 없다.
하지만 Dlg클래스에 사용자 메시지를 등록하여
thread 함수에서 이에 접근하는 방법으로 사용가능하다.

 

1. 다음과 같이 Dialog class에 멤버함수로 UpdateData를 실행하는 함수를 만들어 준다.

LRESULT ___Dlg::OnUpdateDataFalse(WPARAM wParam, LPARAM lParam)
{
     return UpdateData(FALSE);
}


LRESULT ___Dlg::OnUpdateDataTrue(WPARAM wParam, LPARAM lParam)
{
     return UpdateData(TRUE);
}

 


2. stdafx.h 에 사용할 사용자 정의 메시지를 정의한다.

//사용자 정의 메시지
#define UM_UPDATEDATAFALSE (WM_USER+1)  //thread 에서 updatedata를 사용하기 위한 사용자 message
#define UM_UPDATEDATATRUE (WM_USER+2)

 

3. ___Dlg.cpp 의
   BEGIN_MESSAGE_MAP 에
   정의한 사용자 메시지를 등록해 준다.

BEGIN_MESSAGE_MAP(.......(생략) )
.......(생략)
 ON_MESSAGE(UM_UPDATEDATAFALSE, OnUpdateDataFalse) //thread 에서 updatedata 를 사용하기 위한 사용자메시지 처리
 ON_MESSAGE(UM_UPDATEDATATRUE, OnUpdateDataTrue)  //thread 에서 updatedata 를 사용하기 위한 사용자메시지 처리

END_MESSAGE_MAP()

 

4. thread를 시작할 때 현재 Dialog의 핸들을 인수로 넘겨주면서 시작한다.
   (-> 작업자 thread 함수는 전역 함수이므로(dialog의 멤버 함수가 아님))
   (-> Dialog class 의 멤버들을 사용할 수 있게 하기 위함.)

  AfxBeginThread(thread작업함수이름,this);

 

5. thread작업함수 에서 dialog class 의 멤버들을 가져다 쓰기위한 pointer 를 선언/할당 한다.

UINT ThreadDataSave(LPVOID pParam)
{
   ___Dlg* pDlg = (___Dlg*)pParam;

   ...(생략)
}

 

6. thread 에서 dialog class의 메시지에 접근하여 updatedata 를 실행한다.

UINT ThreadDataSave(LPVOID pParam)
{
   ___Dlg* pDlg = (___Dlg*)pParam;

   ...(생략)
   pDlg->PostMessage(UM_UPDATEDATAFALSE);
   pDlg->PostMessage(UM_UPDATEDATATURE);
}

출처 : http://bluebearworld.tistory.com/147

반응형
Posted by 컴투