Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

How to attach() to container and capture output of running function? #3566

Open
xfbs opened this issue Oct 27, 2020 · 0 comments
Open

How to attach() to container and capture output of running function? #3566

xfbs opened this issue Oct 27, 2020 · 0 comments

Comments

@xfbs
Copy link

xfbs commented Oct 27, 2020

Dear all,
I'm trying to use the attach() function to attach to a container and run a function inside it, capturing the output. My idea was to create a pipe() of two file descriptors, and set the lxc_attach_options standard output file descriptor to the write end of the pipe, and read from the read end of it. However, that doesn't work, as this code here demonstrates. Compile it with

gcc -o lxctest lxctest.c -llxc

and run it with

sudo ./lxctest running_container_name

How can I make this work and actually capture data from the running function? Any help would be appreciated.

#include <lxc/lxccontainer.h>
#include <lxc/attach_options.h>
#include <errno.h>                                                                                                                                                                                                                                                                   [0/89]
#include <string.h>
#include <assert.h>
#include <unistd.h>

// Run a function inside the container and capture the output.
void run_function(struct lxc_container *container, lxc_attach_exec_t function, void *data) {
    // default options and PID
    lxc_attach_options_t options = LXC_ATTACH_OPTIONS_DEFAULT;
    pid_t pid;

    // create a pipe to collect stdout
    int pipefd[2];
    assert(0 == pipe(pipefd));
    options.stdout_fd = pipefd[1];
    //options.attach_flags |= LXC_ATTACH_TERMINAL;

    // attach to container, run function
    assert(0 == container->attach(container, function, data, &options, &pid));
    //close(pipefd[1]);

    // read in data
    size_t buffer_size = 1024;
    size_t buffer_pos = 0;
    char *buffer = malloc(buffer_size);

    while(true) {
        if(!(buffer_size - buffer_pos)) {
            buffer_size *= 2;
            buffer = realloc(buffer, buffer_size);
            assert(buffer);
        }
        ssize_t ret = read(pipefd[0], buffer + buffer_pos, buffer_size - buffer_pos);
        assert(ret >= 0);
        printf("just read something\n");

        // read end of file
        if(!ret) {
            break;
        } else {
            buffer_pos += ret;
        }
    }

    buffer[buffer_pos] = 0;
    printf("Read size: %zu\n", buffer_pos);
    printf("Read: %s\n", buffer);
}

int hello_world(void *data) {
    printf("Hello, World!\n");
}

int main(int argc, char *argv[]) {
    if(argc != 2) {
        printf("Usage: %s <container>\n", argv[0]);
        return 0;
    }

    char **names;
    struct lxc_container **containers;
    int amount = list_all_containers("/var/lib/lxc", &names, &containers);

    assert(amount > 0);
    size_t i;
    for(i = 0; i < amount; i++) {
        if(0 == strcmp(argv[1], names[i])) {
            break;
        }
    }

    assert(i < amount);

    run_function(containers[i], hello_world, NULL);

    return 0;
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Development

No branches or pull requests

1 participant