stdout을 redirection하려면?

thisrule의 이미지

C/C++ 언어를 이용한 프로그램을 작성 중입니다.
제가 작성한 프로그램에서 stdout, stderr로 출력되는 모든 내용을 다른 file handle에 연결하고 싶습니다.
어떻게 해야하나요?

처음엔 dup() 함수를 사용할까 생각했는데, 그건 좀 의도와 맞질 않는것 같습니다.
고수님들의 조언 바랍니다.

익명 사용자의 이미지

from "man bash"

   Redirecting Standard Output and Standard Error
       Bash allows both the standard output (file descriptor 1) and the  stan‐
       dard  error  output  (file  descriptor  2) to be redirected to the file
       whose name is the expansion of word with this construct.

       There are two formats for  redirecting  standard  output  and  standard
       error:

              &>word
       and
              >&word

       Of the two forms, the first is preferred.  This is semantically equiva‐
       lent to

              >word 2>&1
thisrule의 이미지

freopen()이란 함수는 처음 알았습니다.
그런데 다소 제가 원하는 의도가 아닌지라 제 의도를 명확히 밝히면...

2개의 process A와 B가 있습니다.
두 프로세스는 socket 통신을 하는데, 프로세스 A의 출력을 B로 보내고자 합니다.
프로세스 A는 background로 돌고, B는 GUI가 있기때문입니다.
현재 두 프로세스간 socket 연결하여 통신하는 부분까지는 프로그래밍 되었습니다.
이제 socket을 열어두고, A의 stdout을 해당 socket descriptor로 연결하고자 합니다.
그렇게 하면 A의 출력이 B의 화면에 나오겠지요.

이렇게 할 수 있는 가장 좋은 방법을 조언 바랍니다.

sangwoo의 이미지

fdopen으로 소켓의 파일 디스크립터를 파일 스트림의 포인터(FILE *)로 연결하시구요. printf부분을 모두 fprintf로 바꾸어 주시면 되겠네요. 물론 fprintf의 첫번째 argument로는 fdopen에서 얻으신 파일 스트림의 포인터를 사용하셔야 하겠습니다.

추가적인 루틴을 넣으셔서, output을 stdout으로 보낼지 소켓으로 보낼지를 선택할 수 있게 하면 더 편리하게 디버깅하실 수 있을 것 같습니다. :-)

----
Let's shut up and code.

jongwooh의 이미지

thisrule wrote:

이제 socket을 열어두고, A의 stdout을 해당 socket descriptor로 연결하고자 합니다.
그렇게 하면 A의 출력이 B의 화면에 나오겠지요.

질문이 잘 이해가 안 가는군요. A를 직접 작성하신다면 A의 출력방향과 내용을 항상 원하시는 대로 조정하실 수 있지 않습니까? 소켓이 열려 있으면 소켓으로 출력하고 그렇지 않으면 stdout으로 출력하게끔 출력루틴을 작성하고 그걸 부르시면 될듯 한데요.

어쨋든 비슷한 사례가 필요하신듯한데 이를테면 두개의 독립된 프로그램들이 stdout/stderr 와 stdin으로 작성되었음에도 불구하고 경우에 따라 서로 네트워크 통신을 하게끔 작성된 소프트웨어가 있으므로 그것을 분석하시면 될 것 같습니다.

그 소프트웨어는 qmail 입니다. qmail은 여러개의 작은 독립된 프로그램들로 이루어져 있습니다. 이 프로그램들이 또 작은 리디렉팅 프로그램으로 inet 소켓으로 서로 연결되게끔 되어 있습니다.

you must know the power of dark side.

sangwoo의 이미지

jwhan님 말씀대로, formatted output이 꼭 필요한 게 아니라면 write() 계열 함수를 사용하시는 게 훨씬 나을 거 같습니다. 아니면 최소한 unbuffered로 사용하셔야겠죠..

----
Let's shut up and code.

thisrule의 이미지

답변 주신 분들 정말 감사합니다.
답변의 내용을 보니 제가 얼마나 멍청하게 질문했는지를 잘 알겠습니다.

위 내용에 이어 더 부연설명 드리자면, A에는 커다란 다른 library를 포함하고 있습니다. 그 library source가 있기는 하지만 다 뜯어고치기엔 어렵구요...
암튼 그 라이브러리 내에 무수히 많은 printf 문이 있는데 거기서 출력하는 걸
process B로 넘기고 싶습니다.

전 사실 이게 쉬울줄 알았습니다. file descriptor만 어떻게 조작하면 될줄 알았는데...
그렇담 제가 하려는게 힘들단 말씀이신가요?
한번만 더 도움을 부탁드립니다.

철이^^v의 이미지

저위의 "손님"분의 답변처럼 process_A 와 process_B 의 프로세스가 한 머신에서 도는 거라만 간단히,
sh> process_A | process_B
이런식으로 해서 A 의 stdout 을 process_B 의 stdin 에서 읽으면 될것 같은데요?

혹시 process_A 와 process_B 가 같이 수행되는것이 문제라면,
stdin 을 읽어서 socket 으로 출력하는, 그런 간단한 프로그램을 만들어서,
sh> process_A | sock_redirect &
와 같이 A 와 B 를 각각 독립적으로 수행하면 되지 않나요?

sangwoo의 이미지

thisrule wrote:
답변 주신 분들 정말 감사합니다.
답변의 내용을 보니 제가 얼마나 멍청하게 질문했는지를 잘 알겠습니다.

위 내용에 이어 더 부연설명 드리자면, A에는 커다란 다른 library를 포함하고 있습니다. 그 library source가 있기는 하지만 다 뜯어고치기엔 어렵구요...
암튼 그 라이브러리 내에 무수히 많은 printf 문이 있는데 거기서 출력하는 걸
process B로 넘기고 싶습니다.

전 사실 이게 쉬울줄 알았습니다. file descriptor만 어떻게 조작하면 될줄 알았는데...
그렇담 제가 하려는게 힘들단 말씀이신가요?
한번만 더 도움을 부탁드립니다.

시간이 되시면, 그 라이브러리를 좀더 깔끔하게 위에서 말씀드린대로 고치시는 게 최선이겠구요. 만일 시간이 없다면, stdin에서 데이터를 받아들여서 소켓으로 내보내는 C라는 프로그램을 하나 만들고, A | C 형식으로 실행시키는 방법 밖에는 없지 않을까요? :-)

----
Let's shut up and code.

thisrule의 이미지

terry93 wrote:
저위의 "손님"분의 답변처럼 process_A 와 process_B 의 프로세스가 한 머신에서 도는 거라만 간단히,
sh> process_A | process_B
이런식으로 해서 A 의 stdout 을 process_B 의 stdin 에서 읽으면 될것 같은데요?

혹시 process_A 와 process_B 가 같이 수행되는것이 문제라면,
stdin 을 읽어서 socket 으로 출력하는, 그런 간단한 프로그램을 만들어서,
sh> process_A | sock_redirect &
와 같이 A 와 B 를 각각 독립적으로 수행하면 되지 않나요?


결정적으로 process A가 remote에서 수행될 수 있습니다.
process A가 socket server 역할을 수행합니다.

그렇다면 방법이 전혀 없단 말씀이신가요...?!? :cry:

sangwoo의 이미지

thisrule wrote:
terry93 wrote:
저위의 "손님"분의 답변처럼 process_A 와 process_B 의 프로세스가 한 머신에서 도는 거라만 간단히,
sh> process_A | process_B
이런식으로 해서 A 의 stdout 을 process_B 의 stdin 에서 읽으면 될것 같은데요?

혹시 process_A 와 process_B 가 같이 수행되는것이 문제라면,
stdin 을 읽어서 socket 으로 출력하는, 그런 간단한 프로그램을 만들어서,
sh> process_A | sock_redirect &
와 같이 A 와 B 를 각각 독립적으로 수행하면 되지 않나요?


결정적으로 process A가 remote에서 수행될 수 있습니다.
process A가 socket server 역할을 수행합니다.

그렇다면 방법이 전혀 없단 말씀이신가요...?!? :cry:

terry93 님께서 두번째 말씀하신 대로 하면 될텐데요. :-(
간단히 말씀드리면, 다음과 같은 프로그램을 만드시면 됩니다. (대충 적습니다)

int
main(...)
{
    fd = socket() /* B에 연결 */
    fp = popen(프로그램A)
    while (fp를 읽고, 데이터를 읽었음) {
        send(fd, 읽은 데이터)
    }
}

이런 식으로 wrapper를 만드시든지, 아니면 redirect하는 프로그램을 만드셔서, terry93님께서 말씀하신 두번째 방법으로 실행하시든지 하면 될 거 같습니다.

----
Let's shut up and code.

thisrule의 이미지

sangwoo wrote:
이런 식으로 wrapper를 만드시든지, 아니면 redirect하는 프로그램을 만드셔서, terry93님께서 말씀하신 두번째 방법으로 실행하시든지 하면 될 거 같습니다.

원래 그렇게 wrapper용 프로그램이 있었습니다.
그런데 제가 이 프로그램을 인계받으면서 GUI 부분을 Qt library로 대폭 수정 중에 있는데, 언뜻 보기에 2개의 프로그램만 있으면 될거같은 생각에
말씀하신 wrapper용 프로그램과 위에 언급한 process A를 통합하려고 시도하다가, stdout redirection 하는 부분 때문에 고민하고 있었습니다.

원래 프로그램은 wrapper용 프로그램과 순수 process A는 shared memeory 통신기법을 사용하고, wrapper용 프로그램과 process B는 socket 통신기법을 사용하고 있는데, 프로그램 maintenance상 프로그램 개수를 줄여볼까 하는 의도였습니다.

답변 주신 분들께 감사드리며, 안되는 걸로 알겠습니다. 흑흑...

cppig1995의 이미지

와~ 뽀로로다!
(이 물체는 한밭도서관 국산캐릭터 전시때 목격한 물체)

Real programmers /* don't */ comment their code.
If it was hard to write, it should be /* hard to */ read.

thisrule의 이미지

cppig1995 wrote:
와~ 뽀로로다!
(이 물체는 한밭도서관 국산캐릭터 전시때 목격한 물체)

좋은 답변이 올라온 줄 알았네요.
전 심각한데 장난하시는군요.
익명 사용자의 이미지

이렇게 해보세요. 뽀로로~ ㅎㅎㅎ

sock = socket(...);
dup2(sock, STDOUT_FILENO);
dup2(sock, STDIN_FILENO);
close(fd); //만일 fd를 close하지 않으면, fd로도 소켓데이터를 주고받을 수 있다는....
printf(); --> 소켓으로 나감
write(); 이거야 원하는 파일 디스크립터로 보낼 수 있으니....
read(); scanf() -> socket에서 읽음

아 당연히 연결(소켓)이 되어야 하며, read에러나 write에러는(시그널 파이프에 유의) 소켓(연결)단절이 될 수 있습니다.

그럼 . 뽀로로~

익명 사용자의 이미지

참 읽을때 파일포인터(FILE *가 아니라...파일의 포인터)를 잘 ~ 조작해주세요.

lseek()이 왜 있는지 잘 알아보시고.

임재정의 이미지

등록된 답글이 없습니다.

익명 사용자의 이미지

댓글 달기

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
이것은 자동으로 스팸을 올리는 것을 막기 위해서 제공됩니다.