`posix_spawn`의 출력을 얻습니다


9

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

프로세스 스폰 :

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

출력 스토리지 :

...?


1
의 세 번째 매개 변수는 posix_spwan유형의 포인터입니다 posix_spawn_file_actions_t(하나는로 제공됨 NULL). 객체가 posix_spawn지정한 호출 프로세스에서 상속 된 파일 디스크립터를 열거 나 닫거나 복제 posix_spawn_file_actions_t합니다. 이 posix_spawn_file_actions_{addclose,adddup2}함수는 어떤 fd에서 어떤 일이 발생하는지 나타내는 데 사용됩니다.
muru

@muru-실제 예제를 추가 할 수 있다고 생각하십니까? 함수 간의 상호 작용은 "파일 작업"에 의해 수행된다는 것을 이해했지만 이것이 정확히 어떻게 일치하는지 또는 fd 위치가 정의되어 있는지는 확실하지 않습니다.
nbubis

답변:


16

다음은 생성 된 프로세스의 파일 디스크립터를 수정하는 최소한의 예입니다 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_t(하나는로 제공됨 NULL). 객체가 posix_spawn지정한 호출 프로세스에서 상속 된 파일 디스크립터를 열거 나 닫거나 복제 posix_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-log파일 기술자 1(일명 표준 출력).
  • 그런 다음 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.


참고 posix_spawn*errno를 설정하지 마십시오. 따라서을 사용할 수 없습니다 perror(). fprintf(stderr, "...: %s\n", strerror(ret))대신 비슷한 것을 사용하십시오 . 또한 주 함수에 return 0문 이 없습니다 .
maxschlepzig

1

그래 넌 할수있어. posix 스폰 파일 작업의 올바른 목록을 정의하는 것이 확실합니다.

예:

#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를 사용합니다. addopen은 일반과 비슷 open()하지만 이미 열려 있으면 자동으로 닫히는 파일 디스크립터도 지정합니다 (여기서 1, stdout). addup2는 1과 dup2()2가 복제되기 전에 대상 파일 디스크립터 (여기서 2, 즉 stderr)가 원자 적으로 닫힙니다 posix_spawn.

마찬가지로 fork(), posix_spawn()posix_spawnp()즉시 부모에게 돌아갑니다. 따라서 우리는 종료를 사용 waitid()하거나 waitpid()명시 적으로 기다려야 child_pid합니다.

당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.