process - 生成异步进程无法与 pkexec 一起使用

标签 process glib stdio vala gio

我当前的 gksudo 命令适用于 Process.spawn_async_with_pipes。但是,如果我使用 pkexec 切换 gksudo,它不会显示 pkexec 窗口,而是在没有提示的情况下直接完成命令并且不返回任何内容。

当我将 Process.spawn_command_line_sync 与相同的 pkexec 命令一起使用时,它会弹出询问密码的提示,并且命令执行正常并返回结果。

我使用 pkexec 的主要原因是使用 polkit,而不是提示用户后续使用需要 root 权限的命令。

我的 Process.spawn_async_with_pipes 代码方法如下所示。

我需要帮助如何使 pkexec 作为后台进程工作,即提示应该阻止 gui,但一旦用户提供密码,它应该将控制权返回给 gui 并继续在后台执行。这正是 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]});

最佳答案

生成异步 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;
}

出现提示,生成的文件列表来 self 的“/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;
}

关于process - 生成异步进程无法与 pkexec 一起使用,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/40064862/

相关文章:

c++ - 如何使用 Glib(或任何其他库)列出目录中的所有文件?

c - 可以检索 glib 'event?' 上剩余的时间

c - C 输出中的随机字节

c - printf 不打印到屏幕

c - 父局部变量充当三个 child 之间的共享变量

c++ - 有什么区别。 C++ 中的 getpid 和 gettid 之间

gtk - G_BEGIN_DECLS 和 G_END_DECLS 是做什么用的?

scala - 来自标准 IO 的 Iteratee 输入

process - 什么是 "Fountain Development Model"?

c - 使用 execlp 的简单 shell 变得很奇怪