รับเอาต์พุตของ "posix_spawn"


9

ดังนั้นฉันจึงสามารถเรียกใช้กระบวนการใน Unix / Linux โดยใช้ POSIX แต่มีวิธีที่ฉันสามารถจัดเก็บ / เปลี่ยนเส้นทางทั้ง 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

นี่คือตัวอย่างเล็กน้อยของการปรับเปลี่ยน file descriptors ของกระบวนการ spawned บันทึกเป็น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(aka stdout)
  • จากนั้นเราposix_spawn_file_actions_adddup2fd 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*อย่าตั้ง 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()แต่คุณยังระบุ file descriptor ซึ่งจะถูกปิดโดยอัตโนมัติถ้าเปิดอยู่แล้ว (ที่นี่ 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.