获取`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

Answers:


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(也称为stdout)。
  • 然后我们将posix_spawn_file_actions_adddup2fd 2(aka stderr)转换为fd 1。
  • 需要注意的是什么已经打开或欺骗还没有。最后两个函数只是更改了child_fd_actions对象,以指出将要执行这些操作。
  • 最后,我们使用posix_spawnchild_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函数未设置errno,与大多数其他UNIX函数不同,它们返回错误代码。因此,我们不能使用,perror()而必须使用strerror()

我们使用两个生成文件操作:addopen和addup2。addopen与正常情况类似,open()但是您还可以指定一个文件描述符,如果该文件描述符已经打开,则会自动关闭(此处为1,即stdout)。addup2的效果与相似dup2(),即在将1复制到2之前,原子关闭了目标文件描述符(此处为2,即stderr)。这些操作仅在创建的子级中执行posix_spawn,即在其执行指定命令之前。

就像fork()posix_spawn()posix_spawnp()立即返回父级。因此,我们必须使用waitid()waitpid()明确等待child_pid的终止。

By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.