ускорить процесс запуска су - PullRequest
0 голосов
/ 17 октября 2018

Я использую boost 1_65_1 и пытаюсь запустить процесс на MacOS.мой основной процесс выполняется от имени пользователя root, мне нужно запустить дополнительный запуск от имени обычного пользователя.Моя командная строка: su user_name -c "full Путь к исполняемому файлу".когда я запускаю командную строку в терминале от имени пользователя root, он работает.

Когда я пытаюсь запустить его с помощью Boost Process, процесс "su" выполняется, но сразу завершается с ошибкой 2.

Myкод для запуска процесса:

void RunProcess(std::string a_PathToExe, std::vector<std::string> a_Args, io_servicePtr a_pIoServicePtr,
                ProcessExitCallBack a_pProcessExitCallBack) {

    Error l_Error;
    std::stringstream l_ShellCommandLine;
    ProcessHandlePtr l_pProcess = NULL;
    boost::process::group l_Group;
    boost::shared_ptr<boost::process::async_pipe> l_PipeOutputStream =
        boost::shared_ptr<boost::process::async_pipe>(new boost::process::async_pipe(*(a_pIoServicePtr.get())));
    boost::shared_ptr<boost::process::async_pipe> l_PipeError =
        boost::shared_ptr<boost::process::async_pipe>(new boost::process::async_pipe(*(a_pIoServicePtr.get())));

    try {

        l_ShellCommandLine << "\"" << a_PathToExe << "\""
                           << " ";
        for (size_t i = 0; i < a_Args.size(); ++i) {
            l_ShellCommandLine << a_Args.at(i) << " ";
        }

        l_pProcess = ProcessHandlePtr(new boost::process::child(
            l_ShellCommandLine.str(), boost::process::std_in.close(),
            boost::process::std_out > *(l_PipeOutputStream.get()), boost::process::std_err > *(l_PipeError.get()),
            *(a_pIoServicePtr.get()), l_Group, boost::process::shell,
            boost::process::on_exit = [](int exit, const std::error_code &ec_in) {
                WRITE_INFO_LOG("The process exit with error %d %s", exit, ec_in.message().c_str());
            }));

        l_PID = l_pProcess->id();
        WaiteForProcessToExit(l_pProcess, l_PipeOutputStream, l_PipeError, a_pProcessExitCallBack);
    }

    catch (std::exception &e) {

    } catch (...) {
    }
    return;
}

void WaiteForProcessToExit(ProcessHandlePtr a_pProcessHandle,
                           boost::shared_ptr<boost::process::async_pipe> a_PipeOutputStream,
                           boost::shared_ptr<boost::process::async_pipe> a_PipeError,
                           ProcessExitCallBack a_pProcessExitCallBack) {

    std::array<char, 1024> buffer = std::array<char, 1024>{};
    a_PipeOutputStream->async_read_some(
        boost::process::buffer(buffer), [=](boost::system::error_code ec, size_t transferre) {
            if (transferre > 0) {
                std::string Line = std::string(buffer.data());
                WRITE_INFO_LOG("%s", Line.c_str());
            }

            if (ec != 0) {

                WRITE_INFO_LOG("The Process %d has exit with error code %d", a_pProcessHandle->id(), ec);
                if (a_pProcessExitCallBack != NULL) {
                    a_pProcessExitCallBack(a_pProcessHandle->id(), Error());
                }
            } else {
                WaiteForProcessToExit(a_pProcessHandle, a_PipeOutputStream, a_PipeError, a_pProcessExitCallBack);
            }
        });
}

почему подпроцесс не работает?Заранее спасибо

Ответы [ 2 ]

0 голосов
/ 18 октября 2018

Спасибо за воспроизведение.

моя проблема в том, что после запуска процесса "su", который я вижу в моей консоли Xcode, выводится следующая ошибка "nw_path_close_fd Не удалось закрыть защищенный necp fd 4 [9: Дескриптор плохого файла] "

в моем коде, мне нужно использовать async, потому что остальная часть моего приложения должна работать.

Я обнаружил, что" boost :: process :: async_system "выполняет свою работу, ноУ меня нет PID процесса.

0 голосов
/ 18 октября 2018

Во-первых, вы показываете недостаточно кода.

Во-вторых, если вы используете su, вам не нужно требовать bp::shell.

Треть всех, этот код выглядит так, будто компилятор C убежал от него.Почему так сложно?Почему все динамическое управление памятью?Зачем асинхронно, если все, что вы делаете, это ждете завершения?

Вот мой упрощенный дубль, который мне подходит.Возможно, вы сможете узнать детали поиска, которые вы делали по-другому:

Синхронный, C ++:

Live On Coliru

#include <iostream>
#include <boost/asio.hpp>
#include <boost/process.hpp>
#include <boost/process/async.hpp>

namespace bp = boost::process;

struct ProcessResult {
    std::string out, err;
    int exitcode;
};

ProcessResult RunProcess(std::string exe, std::vector<std::string> args, boost::asio::io_service& io) {
    std::future<std::string> out, err;
    bp::group group;

    bp::child child(
        bp::search_path(exe), args, bp::std_in.close(), bp::std_out > out, bp::std_err > err, io, group
    );

    child.wait();
    return { out.get(), err.get(), child.exit_code() };
}

int main() {
    boost::asio::io_service io;

    // keep work to avoid io.run to complete early
    auto work = boost::asio::make_work_guard(io);
    std::thread io_thread([&io] { io.run(); });

    auto pstree = RunProcess("su", { "sehe", "-c", "/usr/bin/free" }, io);

    std::cout << "Exitcode: " << pstree.exitcode << "\n";
    std::cout << "Output: " << pstree.out << "\n";
    std::cout << "Error: " << pstree.err << "\n";

    work.reset(); // allow service to complete
    io_thread.join();
}

Какие распечатки (при запуске от имени root):

Exitcode: 0
Output:               total        used        free      shared  buff/cache   available
Mem:       32832516    21846896     2486924     2963636     8498696     5595284
Swap:             0           0           0

Error: 

Когда не от имени root:

Exitcode: 1
Output: 
Error: su: must be run from a terminal

Асинхронная

Вывсе еще может комбинировать асинхронность со стилем C ++.См., Например,

...