それでは、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);
}
それは何をしますか?
- の3番目のパラメータは(指定された)型
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にします。 - 何も開いたりなりすましたりしません。しかし、。最後の2つの関数は、単に
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という2つのmakefile操作を使用します。 addopenは通常と似ていますopen()
が、すでに開いている場合は自動的に閉じるファイル記述子を指定します(ここでは1、stdout)。 addup2には、dup2()
1が2にコピーされる前にターゲットファイル記述子(ここでは2、stderr)が自動的に閉じるのと同じ効果があります。これらの操作は、で作成された子孫のみ、posix_spawn
つまり指定されたコマンドが実行される前に実行されます。
同様に、fork()
すぐに親項目に戻りますposix_spawn()
。posix_spawnp()
したがって、waitid()
またはを使用して明示的に終了をwaitpid()
待つ必要があります。child_pid