Computer >> 컴퓨터 >  >> 프로그래밍 >> C++

C++에서 POSIX popen으로 셸 명령 실행 후 출력 결과 받아오는 방법

C++ 프로그램 내부에서 운영체제의 셸 명령을 실행하고 그 결과(출력)를 코드 안에서 직접 받아와야 하는 경우가 종종 있습니다. 예를 들어 ls 같은 시스템 명령의 결과를 문자열로 가져와 가공해야 할 때가 대표적입니다.

이럴 때 POSIX 계열 시스템(Linux, macOS 등)에서는 popenpclose 함수를 사용하면 간단하게 해결할 수 있습니다.

popen과 pclose란?

popen() 함수는 파이프(pipe)를 생성하고, 프로세스를 포크(fork)한 뒤, 지정한 명령을 셸(shell)을 통해 실행합니다. 이렇게 열린 파이프는 파일 스트림처럼 다룰 수 있어서, 명령의 표준 출력(stdout)을 일반 파일을 읽듯이 읽어올 수 있습니다.

명령 실행이 끝나면 반드시 pclose()를 호출하여 파이프를 닫고 프로세스가 종료될 때까지 기다려야 합니다.

구현 방법

핵심 아이디어는 다음과 같습니다.

  1. popen()으로 명령을 실행하고 읽기 모드("r")로 파이프를 엽니다.
  2. 버퍼를 사용해 표준 출력의 내용을 끝까지 읽으면서 결과 문자열에 계속 덧붙입니다.
  3. pclose()로 파이프를 닫고, 누적된 결과 문자열을 반환합니다.

예제 코드

#include <iostream>
#include <stdexcept>
#include <stdio.h>
#include <string>

using namespace std;

string exec(string command) {
    char buffer[128];
    string result = "";

    // 명령을 실행하고 파이프 열기
    FILE* pipe = popen(command.c_str(), "r");
    if (!pipe) {
        return "popen failed!";
    }

    // 프로세스 출력이 끝날 때까지 읽기
    while (!feof(pipe)) {

        // 버퍼로 읽어서 결과에 추가
        if (fgets(buffer, 128, pipe) != NULL)
            result += buffer;
    }

    pclose(pipe);
    return result;
}

int main() {
    string ls = exec("ls");
    cout << ls;
}

실행 결과

위 프로그램을 컴파일하고 실행하면 현재 디렉터리의 파일 목록이 다음과 같이 출력됩니다.

a.out
hello.cpp
hello.py
hello.o
hydeout
my_file.txt
watch.py

주의 사항

  • popen()은 내부적으로 셸을 호출하므로, 사용자 입력을 그대로 명령 문자열에 넣으면 명령 삽입(command injection) 보안 취약점이 발생할 수 있습니다. 외부 입력은 반드시 검증하거나 제거해야 합니다.
  • 이 방법은 표준 출력만 읽을 수 있으며, 표준 에러(stderr)는 별도 처리가 필요합니다.
  • Windows 환경에서는 _popen/_pclose라는 이름으로 유사한 기능을 제공하지만, 완전히 동일하게 동작하지 않을 수 있으므로 플랫폼별 확인이 필요합니다.