spawn асинхронный процесс не работает с pkexec

Моя текущая команда gksudo работает с Process.spawn_async_with_pipes. однако, если я переключаю gksudo с pkexec, он не показывает окно pkexec и напрямую завершает команду без приглашения и ничего не возвращает.

Когда я использую Process.spawn_command_line_sync с той же командой pkexec, она вызывает запрос пароля, и команды выполняются нормально и возвращают результат.

Моя основная причина использовать pkexec - использовать polkit, а не запрашивать у пользователя последующее использование команды, требующей прав root.

Мой метод для кода Process.spawn_async_with_pipes показан ниже.

Мне нужна помощь в том, как заставить pkexec работать в качестве фонового процесса, т.е. приглашение должно блокировать графический интерфейс, но как только пользователь предоставит пароль, он должен вернуть управление обратно в графический интерфейс и продолжить выполнение в фоновом режиме. Это именно то, что происходит с Gksudo.

заранее спасибо

Это асинхронный метод

public int execute_sync_multiarg_command_pipes(string[] spawn_args) {
        debug("Starting to execute async command: "+string.joinv(" ", spawn_args));
        spawn_async_with_pipes_output.erase(0, -1); //clear the output buffer
        MainLoop loop = new MainLoop ();
        try {
            string[] spawn_env = Environ.get();
            Pid child_pid;

            int standard_input;
            int standard_output;
            int standard_error;

            Process.spawn_async_with_pipes ("/",
                spawn_args,
                spawn_env,
                SpawnFlags.SEARCH_PATH | SpawnFlags.DO_NOT_REAP_CHILD,
                null,
                out child_pid,
                out standard_input,
                out standard_output,
                out standard_error);

            // capture stdout:
            IOChannel output = new IOChannel.unix_new (standard_output);
            output.add_watch (IOCondition.IN | IOCondition.HUP, (channel, condition) => {
                return process_line (channel, condition, "stdout");
            });

            // capture stderr:
            IOChannel error = new IOChannel.unix_new (standard_error);
            error.add_watch (IOCondition.IN | IOCondition.HUP, (channel, condition) => {
                return process_line (channel, condition, "stderr");
            });

            ChildWatch.add (child_pid, (pid, status) => {
                // Triggered when the child indicated by child_pid exits
                Process.close_pid (pid);
                loop.quit ();
            });
            loop.run ();
        } catch(SpawnError e) {
            warning("Failure in executing async command ["+string.joinv(" ", spawn_args)+"] : "+e.message);
            spawn_async_with_pipes_output.append(e.message);
        }
        debug("Completed executing async command["+string.joinv(" ", spawn_args)+"]...");
        return 0;
    }`

Вот как это называется:

execute_sync_multiarg_command_pipes({"pkexec", COMMAND_USING_SUDO[6]});

1 ответ

Решение

Создание асинхронной команды pkexec работает:

public static int main (string[] args) {
    MainLoop loop = new MainLoop ();
    try {
        string[] spawn_args = {"pkexec", "ls", "-l", "-h"};
        string[] spawn_env = Environ.get ();
        Pid child_pid;

        Process.spawn_async ("/",
            spawn_args,
            spawn_env,
            SpawnFlags.SEARCH_PATH | SpawnFlags.DO_NOT_REAP_CHILD,
            null,
            out child_pid);

        ChildWatch.add (child_pid, (pid, status) => {
            // Triggered when the child indicated by child_pid exits
            Process.close_pid (pid);
            loop.quit ();
        });

        loop.run ();
    } catch (SpawnError e) {
        stdout.printf ("Error: %s\n", e.message);
    }
    return 0;
}

Появится приглашение, и результирующий список файлов будет из моего каталога /root, как и ожидалось.

Так что проблема должна быть где-то еще.

Это также работает с трубами:

private static bool process_line (IOChannel channel, IOCondition condition, string stream_name) {
    if (condition == IOCondition.HUP) {
        stdout.printf ("%s: The fd has been closed.\n", stream_name);
        return false;
    }

    try {
        string line;
        channel.read_line (out line, null, null);
        stdout.printf ("%s: %s", stream_name, line);
    } catch (IOChannelError e) {
        stdout.printf ("%s: IOChannelError: %s\n", stream_name, e.message);
        return false;
    } catch (ConvertError e) {
        stdout.printf ("%s: ConvertError: %s\n", stream_name, e.message);
        return false;
    }

    return true;
}

public static int main (string[] args) {
    MainLoop loop = new MainLoop ();
    try {
        string[] spawn_args = {"pkexec", "ls", "-l", "-h"};
        string[] spawn_env = Environ.get ();
        Pid child_pid;

        int standard_input;
        int standard_output;
        int standard_error;

        Process.spawn_async_with_pipes ("/",
            spawn_args,
            spawn_env,
            SpawnFlags.SEARCH_PATH | SpawnFlags.DO_NOT_REAP_CHILD,
            null,
            out child_pid,
            out standard_input,
            out standard_output,
            out standard_error);

        // stdout:
        IOChannel output = new IOChannel.unix_new (standard_output);
        output.add_watch (IOCondition.IN | IOCondition.HUP, (channel, condition) => {
            return process_line (channel, condition, "stdout");
        });

        // stderr:
        IOChannel error = new IOChannel.unix_new (standard_error);
        error.add_watch (IOCondition.IN | IOCondition.HUP, (channel, condition) => {
            return process_line (channel, condition, "stderr");
        });

        ChildWatch.add (child_pid, (pid, status) => {
            // Triggered when the child indicated by child_pid exits
            Process.close_pid (pid);
            loop.quit ();
        });

        loop.run ();
    } catch (SpawnError e) {
        stdout.printf ("Error: %s\n", e.message);
    }
    return 0;
}

Даже это (которое теперь включает ваш фрагмент кода примера) работает:

StringBuilder spawn_async_with_pipes_output;

private static bool process_line (IOChannel channel, IOCondition condition, string stream_name) {
    if (condition == IOCondition.HUP) {
        stdout.printf ("%s: The fd has been closed.\n", stream_name);
        return false;
    }

    try {
        string line;
        channel.read_line (out line, null, null);
        stdout.printf ("%s: %s", stream_name, line);
    } catch (IOChannelError e) {
        stdout.printf ("%s: IOChannelError: %s\n", stream_name, e.message);
        return false;
    } catch (ConvertError e) {
        stdout.printf ("%s: ConvertError: %s\n", stream_name, e.message);
        return false;
    }

    return true;
}

public int execute_sync_multiarg_command_pipes(string[] spawn_args) {
        debug("Starting to execute async command: "+string.joinv(" ", spawn_args));
        spawn_async_with_pipes_output.erase(0, -1); //clear the output buffer
        MainLoop loop = new MainLoop ();
        try {
            string[] spawn_env = Environ.get();
            Pid child_pid;

            int standard_input;
            int standard_output;
            int standard_error;

            Process.spawn_async_with_pipes ("/",
                spawn_args,
                spawn_env,
                SpawnFlags.SEARCH_PATH | SpawnFlags.DO_NOT_REAP_CHILD,
                null,
                out child_pid,
                out standard_input,
                out standard_output,
                out standard_error);

            // capture stdout:
            IOChannel output = new IOChannel.unix_new (standard_output);
            output.add_watch (IOCondition.IN | IOCondition.HUP, (channel, condition) => {
                return process_line (channel, condition, "stdout");
            });

            // capture stderr:
            IOChannel error = new IOChannel.unix_new (standard_error);
            error.add_watch (IOCondition.IN | IOCondition.HUP, (channel, condition) => {
                return process_line (channel, condition, "stderr");
            });

            ChildWatch.add (child_pid, (pid, status) => {
                // Triggered when the child indicated by child_pid exits
                Process.close_pid (pid);
                loop.quit ();
            });
            loop.run ();
        } catch(SpawnError e) {
            warning("Failure in executing async command ["+string.joinv(" ", spawn_args)+"] : "+e.message);
            spawn_async_with_pipes_output.append(e.message);
        }
        debug("Completed executing async command["+string.joinv(" ", spawn_args)+"]...");
        return 0;
    }

public static int main (string[] args) {
    spawn_async_with_pipes_output = new StringBuilder ();
    execute_sync_multiarg_command_pipes ({"pkexec", "ls", "-l", "-h"});
    return 0;
}
Другие вопросы по тегам