如何在Qt中执行复杂的linux命令?(复制)

时间:2021-10-19 01:15:37

This question already has an answer here:

这个问题已经有了答案:

I want to restart the computer by running a command in linux using QProcess. I have hard-coded my root password in my application.

我想通过使用QProcess在linux中运行一个命令来重新启动计算机。我在应用程序中硬编码了根密码。

When i run the following in a terminal it works perfect:

当我在一个终端运行以下操作时,它是完美的:

echo myPass | sudo -S shutdown -r now 

When i put the command in a shell script and call it via QProcess it is also successful :

当我将命令放在shell脚本中并通过QProcess调用它时,它也是成功的:

QProcess process;
process.startDetached("/bin/sh", QStringList()<< "myScript.sh");

But i can not run it by directly passing to QProcess:

但是我不能直接通过QProcess来运行:

process.startDetached("echo myPass | sudo -S shutdown -r now ");

It will just print myPass | sudo -S shutdown -r now

它现在只打印myPass | sudo -S关机-r

How is it possible to run such relatively complex commands directly using QProcess. (Not putting in a shell script).

如何能够直接使用QProcess运行如此复杂的命令呢?(不放入shell脚本)。

3 个解决方案

#1


9  

The key methods that exist for this purpose established in QProcess:

在QProcess中建立的这个目的的关键方法是:

void QProcess::setProcessChannelMode(ProcessChannelMode mode)

空白QProcess:setProcessChannelMode(ProcessChannelMode模式)

and

void QProcess::setStandardOutputProcess(QProcess * destination)

空白QProcess:setStandardOutputProcess(QProcess *目的地)

Therefore, the following code snippet would be the equivalence of command1 | command2 without limiting yourself to one interpreter or another:

因此,下面的代码片段将是command1 | command2的等价性,而不限制您使用一个或另一个解释器:

QProcess process1
QProcess process2;

process1.setStandardOutputProcess(&process2);

process1.start("echo myPass");
process2.start("sudo -S shutdown -r now");
process2.setProcessChannelMode(QProcess::ForwardedChannels);

// Wait for it to start
if(!process1.waitForStarted())
    return 0;

bool retval = false;
QByteArray buffer;
// To be fair: you only need to wait here for a bit with shutdown,
// but I will still leave the rest here for a generic solution
while ((retval = process2.waitForFinished()));
    buffer.append(process2.readAll());

if (!retval) {
    qDebug() << "Process 2 error:" << process2.errorString();
    return 1;
}

You could drop the sudo -S part because you could run this small program as root, as well as setting up the rights. You could even set setuid or setcap for the shutdown program.

您可以删除sudo -S部分,因为您可以作为root运行这个小程序,并设置权限。您甚至可以为关机程序设置setuid或setcap。

What we usually do when building commercial Linux systems is to have a minimal application that can get setuid or setcap for the activity it is trying to do, and then we call that explicitly with system(3) or QProcess on Linux. Basically,

在构建商业Linux系统时,我们通常所做的是使用一个最小的应用程序来为它正在尝试的活动获取setuid或setcap,然后我们在Linux上使用system(3)或QProcess显式地调用它。基本上,

I would write that small application to avoid giving full root access to the whole application, so to restrict the access right against malicious use as follows:

我将编写这个小应用程序以避免对整个应用程序提供完全的根访问权限,从而限制对恶意使用的访问权:

sudo chmod u+s /path/to/my/application

#2


2  

First, you could configure sudo to avoid asking you the password. For instance by being member of the sudo group and having the line

首先,您可以配置sudo以避免向您询问密码。例如,作为sudo组的成员并拥有行

 %sudo  ALL=NOPASSWD:  ALL

in your /etc/sudoers file. Of course not asking the password lowers the security of your system.

在你/etc/sudoers文件。当然,不询问密码会降低系统的安全性。

To answer your question about Qt, remember that bash(1), like all Posix shells, hence /bin/sh, accept the -c argument with a string (actually system(3) is forking a /bin/sh -c). So just execute

要回答关于Qt的问题,请记住,bash(1)和所有Posix shell一样,也就是/bin/sh,接受带有字符串的-c参数(实际上系统(3)是forking a /bin/sh -c)。就执行

 process.startDetached("/bin/sh", QStringList()<< "-c" 
                       << "echo myPass | sudo -S shutdown -r now");

As AntiClimacus answered, puting your root password inside an executable is a bad idea.

正如AntiClimacus回答的那样,在可执行文件中输入根密码是个坏主意。

#3


1  

You must put your command in a shell script and execute sh or bash with QProcess with your shell script as argument, because your command contains |, which must be interpreted by sh or bash.

您必须将您的命令放在shell脚本中,并使用您的shell脚本作为参数执行sh或bash,因为您的命令包含|,这必须由sh或bash来解释。

However, it's just my opinion, but: I don't think it is a good solution to do what you are doing, i.e. include your root password in an executable.

然而,这只是我的观点,但是:我不认为这是一个很好的解决方案去做你正在做的事情,例如在可执行文件中包含你的根密码。

#1


9  

The key methods that exist for this purpose established in QProcess:

在QProcess中建立的这个目的的关键方法是:

void QProcess::setProcessChannelMode(ProcessChannelMode mode)

空白QProcess:setProcessChannelMode(ProcessChannelMode模式)

and

void QProcess::setStandardOutputProcess(QProcess * destination)

空白QProcess:setStandardOutputProcess(QProcess *目的地)

Therefore, the following code snippet would be the equivalence of command1 | command2 without limiting yourself to one interpreter or another:

因此,下面的代码片段将是command1 | command2的等价性,而不限制您使用一个或另一个解释器:

QProcess process1
QProcess process2;

process1.setStandardOutputProcess(&process2);

process1.start("echo myPass");
process2.start("sudo -S shutdown -r now");
process2.setProcessChannelMode(QProcess::ForwardedChannels);

// Wait for it to start
if(!process1.waitForStarted())
    return 0;

bool retval = false;
QByteArray buffer;
// To be fair: you only need to wait here for a bit with shutdown,
// but I will still leave the rest here for a generic solution
while ((retval = process2.waitForFinished()));
    buffer.append(process2.readAll());

if (!retval) {
    qDebug() << "Process 2 error:" << process2.errorString();
    return 1;
}

You could drop the sudo -S part because you could run this small program as root, as well as setting up the rights. You could even set setuid or setcap for the shutdown program.

您可以删除sudo -S部分,因为您可以作为root运行这个小程序,并设置权限。您甚至可以为关机程序设置setuid或setcap。

What we usually do when building commercial Linux systems is to have a minimal application that can get setuid or setcap for the activity it is trying to do, and then we call that explicitly with system(3) or QProcess on Linux. Basically,

在构建商业Linux系统时,我们通常所做的是使用一个最小的应用程序来为它正在尝试的活动获取setuid或setcap,然后我们在Linux上使用system(3)或QProcess显式地调用它。基本上,

I would write that small application to avoid giving full root access to the whole application, so to restrict the access right against malicious use as follows:

我将编写这个小应用程序以避免对整个应用程序提供完全的根访问权限,从而限制对恶意使用的访问权:

sudo chmod u+s /path/to/my/application

#2


2  

First, you could configure sudo to avoid asking you the password. For instance by being member of the sudo group and having the line

首先,您可以配置sudo以避免向您询问密码。例如,作为sudo组的成员并拥有行

 %sudo  ALL=NOPASSWD:  ALL

in your /etc/sudoers file. Of course not asking the password lowers the security of your system.

在你/etc/sudoers文件。当然,不询问密码会降低系统的安全性。

To answer your question about Qt, remember that bash(1), like all Posix shells, hence /bin/sh, accept the -c argument with a string (actually system(3) is forking a /bin/sh -c). So just execute

要回答关于Qt的问题,请记住,bash(1)和所有Posix shell一样,也就是/bin/sh,接受带有字符串的-c参数(实际上系统(3)是forking a /bin/sh -c)。就执行

 process.startDetached("/bin/sh", QStringList()<< "-c" 
                       << "echo myPass | sudo -S shutdown -r now");

As AntiClimacus answered, puting your root password inside an executable is a bad idea.

正如AntiClimacus回答的那样,在可执行文件中输入根密码是个坏主意。

#3


1  

You must put your command in a shell script and execute sh or bash with QProcess with your shell script as argument, because your command contains |, which must be interpreted by sh or bash.

您必须将您的命令放在shell脚本中,并使用您的shell脚本作为参数执行sh或bash,因为您的命令包含|,这必须由sh或bash来解释。

However, it's just my opinion, but: I don't think it is a good solution to do what you are doing, i.e. include your root password in an executable.

然而,这只是我的观点,但是:我不认为这是一个很好的解决方案去做你正在做的事情,例如在可执行文件中包含你的根密码。