因此,我可以使用 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_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_adddup2
fd2
(又名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 生成文件操作列表绝对是正确的方法。
例子:
#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()
,即目标文件描述符(此处为 2,即 stderr)在 1 复制到 2 之前自动关闭。这些操作仅在由 所创建的子级中执行posix_spawn
,即在执行指定命令之前。
喜欢fork()
,posix_spawn()
立即posix_spawnp()
返回给父级。因此,我们必须使用waitid()
orwaitpid()
显式等待child_pid
的终止。