したがって、POSIXを使用してUnix/Linuxでプロセスを実行できますが、プロセスのSTDOUTとSTDERRの両方をファイルに保存/リダイレクトできる方法はありますか? _spawn.h
_ヘッダーには、関連があるように見える_posix_spawn_file_actions_adddup2
_の減速が含まれていますが、その使用方法はよくわかりません。
プロセスが生成します:
posix_spawn(&processID, (char *)"myprocess", NULL, NULL, args, environ);
出力ストレージ:
_...?
_
_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
_の3番目のパラメーターは、タイプ_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_adddup2
_ fd _2
_(aka 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 fileアクションの正しいリストを定義することは、間違いなく進むべき道です。
例:
#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()
のようなものを使用する必要があります。
2つのspawn fileアクションを使用します:addopenとaddup2。 addopenは通常のopen()
に似ていますが、既に開いている場合(ここでは1、つまりstdout)に自動的に閉じられるファイル記述子も指定します。 addup2はdup2()
と同様の効果があります。つまり、ターゲットファイル記述子(ここでは2、つまりstderr)は、1が2に複製される前にアトミックに閉じられます。これらのアクションは、posix_spawn
によって作成された子でのみ実行されます。つまり、右指定されたコマンドを実行する前。
fork()
と同様に、posix_spawn()
およびposix_spawnp()
はすぐに親に戻ります。したがって、child_pid
の終了を明示的に待機するには、waitid()
またはwaitpid()
を使用する必要があります。