"posix_spawn"의 출력을 가져옵니다.

"posix_spawn"의 출력을 가져옵니다.

그렇다면 POSIX를 사용하여 Unix/Linux에서 프로세스를 실행할 수 있지만 프로세스의 STDOUT 및 STDERR을 파일에 저장/리디렉션할 수 있는 방법이 있습니까? 헤더에 spawn.h관련성이 있어 보이는 감속이 포함되어 있지만 posix_spawn_file_actions_adddup2이를 사용하는 방법을 잘 모르겠습니다.

프로세스는 다음을 생성합니다.

posix_spawn(&processID, (char *)"myprocess", NULL, NULL, args, environ);

출력 저장:

...?

답변1

다음은 생성 프로세스의 파일 설명자를 수정하는 최소한의 예입니다 foo.c.

#include <stdio.h>
#include <stdlib.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <spawn.h>

int main(int argc, char* argv[], char *env[])
{
    int ret;
    pid_t child_pid;
    posix_spawn_file_actions_t child_fd_actions;
    if (ret = posix_spawn_file_actions_init (&child_fd_actions))
        perror ("posix_spawn_file_actions_init"), exit(ret);
    if (ret = posix_spawn_file_actions_addopen (&child_fd_actions, 1, "/tmp/foo-log", 
            O_WRONLY | O_CREAT | O_TRUNC, 0644))
        perror ("posix_spawn_file_actions_addopen"), exit(ret);
    if (ret = posix_spawn_file_actions_adddup2 (&child_fd_actions, 1, 2))
        perror ("posix_spawn_file_actions_adddup2"), exit(ret);

    if (ret = posix_spawnp (&child_pid, "date", &child_fd_actions, NULL, argv, env))
        perror ("posix_spawn"), exit(ret);
}

그것은 무엇을 합니까?

  • 의 세 번째 매개변수는 (지정한 ) posix_spwan유형의 포인터입니다 . 호출 프로세스에서 상속된 파일 설명자는 개체에 지정된 대로 열리거나 닫히거나 복사됩니다 .posix_spawn_file_actions_tNULLposix_spawnposix_spawn_file_actions_t
  • 그래서 우리는 posix_spawn_file_actions_t객체( chiild_fd_actions)로 시작하고 이를 로 초기화합니다 posix_spawn_file_actions_init().
  • 이제 이러한 함수를 사용하여 각각 파일 설명자( 및 함수 posix_spawn_file_actions_{addopen,addclose,addup2}뒤)를 열거나 닫거나 복사할 수 있습니다 .open(3)close(3)dup2(3)
  • 그래서 우리는 파일 설명자 (표준 출력이라고도 함) 에 posix_spawn_file_actions_addopen파일을 넣습니다./tmp/foo-log1
  • 그런 다음 posix_spawn_file_actions_adddup2fd 2(일명 stderr)를 fd 1로 만듭니다.
  • 아무것도 열리거나 스푸핑되지 않습니다.하지만. 마지막 두 함수는 단순히 child_fd_actions이러한 작업을 설명하기 위해 객체를 변경합니다.
  • 마지막으로 우리는 객체 posix_spawn로 작업합니다.child_fd_actions

테스트를 받아보세요:

$ make foo
cc     foo.c   -o foo
$ ./foo
$ cat /tmp/foo-log 
Sun Jan  3 03:48:17 IST 2016
$ ./foo +'%F %R'  
$ cat /tmp/foo-log
2016-01-03 03:48
$  ./foo -d 'foo'  
$ cat /tmp/foo-log
./foo: invalid date ‘foo’

보시다시피 생성 프로세스의 stdout과 stderr은 모두 /tmp/foo-log.

답변2

그래 넌 할수있어. posix makefile 작업의 올바른 목록을 정의하는 것이 확실히 좋은 방법입니다.

예:

#include <errno.h>
#include <fcntl.h>
#include <spawn.h>
#include <stdio.h>
#include <string.h>    
#define CHECK_ERROR(R, MSG) do { if (R) { fprintf(stderr, "%s: %s\n",
        (MSG), strerror(R)); return 1; } } while (0)    
extern char **environ;   
int main(int argc, char **argv)
{
    if (argc < 3) {
        fprintf(stderr, "Call: %s OUTFILE COMMAND [ARG]...\n", argv[0]);
        return 2;
    }
    const char *out_filename = argv[1];
    char **child_argv = argv+2;
    posix_spawn_file_actions_t as;
    int r = posix_spawn_file_actions_init(&as);
    CHECK_ERROR(r, "actions init");
    r = posix_spawn_file_actions_addopen(&as, 1, out_filename,
            O_CREAT | O_TRUNC | O_WRONLY, 0644);
    CHECK_ERROR(r, "addopen");
    r = posix_spawn_file_actions_adddup2(&as, 1, 2);
    CHECK_ERROR(r, "adddup2");
    pid_t child_pid;
    r = posix_spawnp(&child_pid, child_argv[0], &as, NULL,
            child_argv, environ);
    CHECK_ERROR(r, "spawnp");
    r = posix_spawn_file_actions_destroy(&as);
    CHECK_ERROR(r, "actions destroy");
    return 0;
}

컴파일 및 테스트:

$ cc -Wall -g -o spawnp spawnp.c
$ ./spawnp log date -I
$ cat log
2018-11-03
$ ./a.out log dat 
spawnp: No such file or directory

posix_spawn함수는 대부분의 다른 UNIX 함수와 달리 errno를 설정하지 않으며 오류 코드를 반환합니다. 그래서 우리는 perror()그런 것을 사용할 수는 없지만 사용해야 합니다 strerror().

우리는 addopen과 addup2라는 두 가지 makefile 작업을 사용합니다. addopen은 일반과 비슷 open()하지만 이미 열려 있는 경우 자동으로 닫히는 파일 설명자를 지정합니다(여기서는 1, stdout). addup2는 dup2()1이 2로 복사되기 전에 대상 파일 설명자(여기서는 2, stderr)가 자동으로 닫히는 비슷한 효과를 갖습니다 . 이러한 작업은 에서 만든 하위 항목에서만 posix_spawn, 즉 지정된 명령이 실행되기 전에 수행됩니다.

마찬가지로 fork()즉시 상위 항목으로 돌아갑니다 posix_spawn(). posix_spawnp()따라서 waitid()또는 를 사용하여 명시적으로 종료를 waitpid()기다려야 합니다.child_pid

관련 정보