[완료]popen시 명령어 수행

yangsee의 이미지

간단한 프로그램 작성시 오류가 있어서 질문드립니다.

system call을 호출할 때 popen을 사용합니다.
for문에서 tar 파일 16개를 popen으로 풀도록 했습니다.(1개가 25M, 1개 tar = 888개 파일 포함)
16개의 tar가 다 풀리고 나서, 888 * 16 개의 파일의 압축해제(gzip -d *.gz)도 수행하게 하였습니다.

문제는 tar가 제대로 안 풀린다는 것입니다.
각 tar파일의 초반에 있는 파일만 풀리고 나머지는 파일이 미생성됩니다.
프로그램상의 오류메시지도 없습니다.
자원문제인가?

직접 쉘에서 수행할 때는 문제가 없었습니다.

도움 부탁드립니다.

ymir의 이미지

코드를 어떻게 작성하셨는지 모르니, 의견 드리기가 애매합니다만..

popen() 이후에 곧바로 pclose() 가 호출된다면..
stream 이 닫히고 프로세스는 진행상태와 무관하게 바로 종료됩니다.
(보충 : fork 된 녀석이 pipe 에 데이터를 쓰는 경우에만, EPIPE 를 찍고 종료됨)

tar 가 풀릴 만큼의 충분한 시간적 여유를 두고 sleep 하거나.. (근데 이건 예측 불가..)
fp 가 NULL 을 return 할 때까지 fgets 를 호출해 주어야..
tar 가 성공한 것으로 간주 할 수 있습니다.

tar 가 찍어내는 메시지가 필요한 경우라 아니라면...
그냥 system() 함수를 쓰는 편이 나을 것 같습니다.

추가)
(이런 경우에 굳이 popen 을 써야 할 이유는 없겠지만...)
popen() 을 쓸 때, 명령의 stdout 을 > /dev/null 로 날려버리면..
popen() 직후에 pclose() 를 호출하더라도, 명령이 완전히 수행된 후에 종료되는군요.

되면 한다! / feel no sorrow, feel no pain, feel no hurt, there's nothing gained.. only love will then remain.. 『 Mizz 』

되면 한다! / feel no sorrow, feel no pain, feel no hurt, there's nothing gained.. only love will then remain.. 『 Mizz 』

yangsee의 이미지

코드는 다음과 같습니다.
popen시 &를 안주면 Broken Pipe 오류가 납니다.
&를 주면 pclose전에 sleep을 주어도 완전히 파일을 풀지 못합니다.
(50%정도만 풀리고 다음파일로 넘어갑니다.)
쉘에서 직접 명령을 주면 5초면 풀리는데, sleep은 2분을 주어도 tar가 끝나지 않네요. --;

for(hour=0; hour<25; hour++)
{
sprintf(strTemp, "tar xvf %s/%08d%02d.tar &", dir, day, hour);
printf("%s\n", strTemp); //test
if((pfp = popen(strTemp, "r")) == NULL)
printf("** %s:%d ** popen == NULL",__FILE__,__LINE__);
else
pclose(pfp);
}

ymir의 이미지

popen 에서 EPIPE 가 떨어진다는 뜻인가요..?
popen() 후에, fork 된 프로세스가 tar 의 결과를 pipe 에 쓰려는데..
pclose() 가 바로 호출되면서, pipe 가 사라지니까 EPIPE 를 리턴할 텐데요.. ;;
(popen 은 정상적으로 수행될 것 같다는 뜻)
흠.. popen 에서 호출하는 shell 과 관련이 있는 건지는 확실히 모르겠군요.

아래는 fedora, bash 에서 테스트한 코드입니다.
첫번째는.. stdout 을 /dev/null 로 날려버리면 pipe 에 쓸 데이터가 없으니..
EPIPE 가 안 떨어지므로 프로세스가 계속해서 수행될 것이고..
두번째는 프로세스가 정상적으로 종료할 때까지.. pipe 의 내용을 읽어들이는 코드입니다.

#include &lt;stdio.h&gt;
 
static void do_tar1(const char *opt, const char *path)
{
        FILE *fp = NULL;
        char cmd[BUFSIZ];
 
        snprintf(cmd, sizeof(cmd), "/bin/tar %s %s > /dev/null", opt, path);
        fp = popen(cmd, "r");
        if (fp)
                pclose(fp);
}
 
static void do_tar2(const char *opt, const char *path)
{
        FILE *fp = NULL;
        char cmd[BUFSIZ];
 
        snprintf(cmd, sizeof(cmd), "/bin/tar %s %s", opt, path);
        fp = popen(cmd, "r");
        if (fp)
        {
                while (fgets(cmd, sizeof(cmd), fp));
                pclose(fp);
        }
}
 
int main(int argc, char *argv[])
{
        if (argc != 2)
                return -1;
 
        do_tar1("xvf", argv[1]);
 
        return 0;
}

되면 한다! / feel no sorrow, feel no pain, feel no hurt, there's nothing gained.. only love will then remain.. 『 Mizz 』

되면 한다! / feel no sorrow, feel no pain, feel no hurt, there's nothing gained.. only love will then remain.. 『 Mizz 』

yangsee의 이미지

저는 sunOS에서 테스트를 했습니다.

말씀해주신 2가지 경우 모두 잘 됩니다.

제가 적은 방법으로는 popen이 제대로 수행이 안되더라는. --;

감사합니다.

yangsee의 이미지

> /dev/null 을 달아주니 금새 정상동작 합니다.
감사드립니다.

system은 호출시마다 인자가 틀려져서 popen을 사용하였습니다.

댓글 달기

Filtered HTML

  • 텍스트에 BBCode 태그를 사용할 수 있습니다. URL은 자동으로 링크 됩니다.
  • 사용할 수 있는 HTML 태그: <p><div><span><br><a><em><strong><del><ins><b><i><u><s><pre><code><cite><blockquote><ul><ol><li><dl><dt><dd><table><tr><td><th><thead><tbody><h1><h2><h3><h4><h5><h6><img><embed><object><param><hr>
  • 다음 태그를 이용하여 소스 코드 구문 강조를 할 수 있습니다: <code>, <blockcode>, <apache>, <applescript>, <autoconf>, <awk>, <bash>, <c>, <cpp>, <css>, <diff>, <drupal5>, <drupal6>, <gdb>, <html>, <html5>, <java>, <javascript>, <ldif>, <lua>, <make>, <mysql>, <perl>, <perl6>, <php>, <pgsql>, <proftpd>, <python>, <reg>, <spec>, <ruby>. 지원하는 태그 형식: <foo>, [foo].
  • web 주소와/이메일 주소를 클릭할 수 있는 링크로 자동으로 바꿉니다.

BBCode

  • 텍스트에 BBCode 태그를 사용할 수 있습니다. URL은 자동으로 링크 됩니다.
  • 다음 태그를 이용하여 소스 코드 구문 강조를 할 수 있습니다: <code>, <blockcode>, <apache>, <applescript>, <autoconf>, <awk>, <bash>, <c>, <cpp>, <css>, <diff>, <drupal5>, <drupal6>, <gdb>, <html>, <html5>, <java>, <javascript>, <ldif>, <lua>, <make>, <mysql>, <perl>, <perl6>, <php>, <pgsql>, <proftpd>, <python>, <reg>, <spec>, <ruby>. 지원하는 태그 형식: <foo>, [foo].
  • 사용할 수 있는 HTML 태그: <p><div><span><br><a><em><strong><del><ins><b><i><u><s><pre><code><cite><blockquote><ul><ol><li><dl><dt><dd><table><tr><td><th><thead><tbody><h1><h2><h3><h4><h5><h6><img><embed><object><param>
  • web 주소와/이메일 주소를 클릭할 수 있는 링크로 자동으로 바꿉니다.

Textile

  • 다음 태그를 이용하여 소스 코드 구문 강조를 할 수 있습니다: <code>, <blockcode>, <apache>, <applescript>, <autoconf>, <awk>, <bash>, <c>, <cpp>, <css>, <diff>, <drupal5>, <drupal6>, <gdb>, <html>, <html5>, <java>, <javascript>, <ldif>, <lua>, <make>, <mysql>, <perl>, <perl6>, <php>, <pgsql>, <proftpd>, <python>, <reg>, <spec>, <ruby>. 지원하는 태그 형식: <foo>, [foo].
  • You can use Textile markup to format text.
  • 사용할 수 있는 HTML 태그: <p><div><span><br><a><em><strong><del><ins><b><i><u><s><pre><code><cite><blockquote><ul><ol><li><dl><dt><dd><table><tr><td><th><thead><tbody><h1><h2><h3><h4><h5><h6><img><embed><object><param><hr>

Markdown

  • 다음 태그를 이용하여 소스 코드 구문 강조를 할 수 있습니다: <code>, <blockcode>, <apache>, <applescript>, <autoconf>, <awk>, <bash>, <c>, <cpp>, <css>, <diff>, <drupal5>, <drupal6>, <gdb>, <html>, <html5>, <java>, <javascript>, <ldif>, <lua>, <make>, <mysql>, <perl>, <perl6>, <php>, <pgsql>, <proftpd>, <python>, <reg>, <spec>, <ruby>. 지원하는 태그 형식: <foo>, [foo].
  • Quick Tips:
    • Two or more spaces at a line's end = Line break
    • Double returns = Paragraph
    • *Single asterisks* or _single underscores_ = Emphasis
    • **Double** or __double__ = Strong
    • This is [a link](http://the.link.example.com "The optional title text")
    For complete details on the Markdown syntax, see the Markdown documentation and Markdown Extra documentation for tables, footnotes, and more.
  • web 주소와/이메일 주소를 클릭할 수 있는 링크로 자동으로 바꿉니다.
  • 사용할 수 있는 HTML 태그: <p><div><span><br><a><em><strong><del><ins><b><i><u><s><pre><code><cite><blockquote><ul><ol><li><dl><dt><dd><table><tr><td><th><thead><tbody><h1><h2><h3><h4><h5><h6><img><embed><object><param><hr>

Plain text

  • HTML 태그를 사용할 수 없습니다.
  • web 주소와/이메일 주소를 클릭할 수 있는 링크로 자동으로 바꿉니다.
  • 줄과 단락은 자동으로 분리됩니다.
댓글 첨부 파일
이 댓글에 이미지나 파일을 업로드 합니다.
파일 크기는 8 MB보다 작아야 합니다.
허용할 파일 형식: txt pdf doc xls gif jpg jpeg mp3 png rar zip.
CAPTCHA
이것은 자동으로 스팸을 올리는 것을 막기 위해서 제공됩니다.