生成异步进程不适用于 pkexec

spawn async process not working with pkexec

我当前的 gksudo 命令适用于 Process.spawn_async_with_pipes。但是,如果我用 pkexec 切换 gksudo,它不会显示 pkexec window 并在没有提示的情况下直接完成命令并且 return 什么都没有。

当我将 Process.spawn_command_line_sync 与相同的 pkexec 命令一起使用时,它会弹出要求输入密码的提示,命令执行正常,结果是 return。

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

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

我需要帮助如何使 pkexec 作为后台进程工作,即提示应该阻止 gui,但是一旦用户提供密码,它应该 return 控制回 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;
}

出现提示,结果文件列表来自我的“/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;
}