`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
の3番目のパラメーターposix_spwanは、型のポインターposix_spawn_file_actions_t(として指定したものNULL)です。オブジェクトposix_spawnによって指定された呼び出しプロセスから継承されたファイル記述子を開く、閉じる、または複製しますposix_spawn_file_actions_tposix_spawn_file_actions_{addclose,adddup2}関数がどのFDに何が起こるかを示すために使用されています。
muru

@muru-実用的な例を追加できると思いますか?関数間の相互作用が「ファイルアクション」によって行われることを理解しましたが、これがどのように正確に適合するか、またはfdの場所が定義されている場所は明確ではありません。
nbubis 2016年

回答:


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);
}

それは何をするためのものか?

  • の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(別名stdout)にファイルを置きます。
  • 次に、posix_spawn_file_actions_adddup2fd 2(別名stderr)をfd 1に変換します。
  • まだ何も開かれていないか、またはだまされていないことに注意してください。最後の2つの関数は単に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 2018年

1

はい、できます。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()すぐに親に戻ります。したがって、を使用するwaitid()waitpid()child_pidの終了を明示的に待機する必要があります。

弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.