How to make QProcess "interactive" ?
-
Alternatively pipe whatever is that you want to run as root through
pkexec
, which is a small utility that prompts for root password before executing what you pass on the command line (i.e. command line arguments). -
@AnneRanch said in How to make QProcess "interactive" ?:
why it this code
frankly, there is more wrong with this code than correct. (I'm Dutch, sorry we're blunt).
You've missed the async nature of Qt, for starters. You should NEVER call methods like "wait for" in a callback from the UI.
As others indicated, sudo is specifically designed to not allow this. The structural solution is policyKit, as generally it's a bad approach to make a button press start an admin process.
Which then leads to the point that QProcess is not meant for this kind of thing either. Good examples of QProcess are a front-end for Git that calls git commands behind the scenes. Bad examples are anything that requires any type of interaction. It's not impossible, just not a good idea.
Bottom line; use policyKit, or its newer version polkit.
-
@TomZ OK, you can be blunt, but I cannot...
Here it the minimal explanation for my need for interactive QProcess...I am writing Bluetooth application for my own use - hence I am not concerned about the use or misuse of "sudo'-- end of story.
I started by using Qt Bluetooth code to find out it has "few holes" .. the main one - it does not always physically scan for devices - it uses RANDOM unknown data from past...So I switched to using fundamental Linux commands , hence I really need interactive code.
I understand "interactive " can be done using output redirection or "native window"... and I am heading that direction.
-
@AnneRanch thank you for taking my message in stride :-)
I just want to first up state that the reason I suggested to not use sudo interactively is not because I'm playing the responsible parent or anything.
The reason I'm saying this is because the sudo authors went out of their way to make it very hard to do this. Again, sudo and interactively..If you need to use sudo, make sure you can do this non-interactively. Which means to do so passwordless for those commands you need executed as root.
You can get started with that here:
https://help.ubuntu.com/community/Sudoers
Now, you write your bluetooth app requires you to do things interactively, presumably with commandline tools. Not sure if I got that part. Things like lsusb don't require sudo, so your example didn't enlighten me.
As I wrote, you can make qprocess be interactive.
You want to write a class that owns it and work in async manner (using signals and slots) without any
wait
type of methods. Ideally your apps that run as root never touch stderr, which makes it much easier and you'll be able to find and use any type of QIODevice based tutorial on how to interactively send and receive data. -
@TomZ Thanks for reply.
Allow me to modify this discussion.
Here is my FULL TEST code.
MainWindow::MainWindow(QWidget *parent) : QMainWindow(parent) , ui(new Ui::MainWindow) { ui->setupUi(this); QProcess *QP = new QProcess(); QP->start( "/usr/bin/gnome-terminal", QStringList() << " lsusb "); //QP->write("lsusb"); } MainWindow::~MainWindow() { delete ui; }
here is FULL run output
the "start" HAS option "lsusb" there is NO " sudo" required
AND there is no " lsusb" output
BUT I can input "lsusb" manually and get expected data .
however I desire to have interactive ( read/ write ) code.PS the doc clearly states this is
how QPocess should work."The QProcess class is used to start external programs and to communicate with them."
The question remains - what is missing in code ?
-
@AnneRanch
Because it is not runninglsusb
? Your command is/usr/bin/gnome-terminal lsusb
. I don't think that is right, did you try copying and pasting that onto a command line to test? If it's not right there it won;t be right fromQProcess
. From what I can see you might need any of these:/usr/bin/gnome-terminal --command lsusb /usr/bin/gnome-terminal --exec lsusb /usr/bin/gnome-terminal -e lsusb /usr/bin/gnome-terminal -x lsusb /usr/bin/gnome-terminal -- lsusb
Look at https://manpages.ubuntu.com/manpages/xenial/en/man1/gnome-terminal.1.html or try
man gnome-terminal
orgnome-terminal --help
on your system. -
@AnneRanch said in How to make QProcess "interactive" ?:
Here is my FULL TEST code.
... your full test code doesn't read the standard output of the started process.
-
@AnneRanch said in How to make QProcess "interactive" ?:
"The QProcess class is used to start external programs and to communicate with them."
You misinterpret the documentation.
QProcess
starts external programs and communicates with them. What you want to do, is to start an external program, let the user communicate with it in a defined manner and read back the result. As said before: Not possible in Qt and I wouldn't know of any well known tool, that is suitable for such a contained user interaction.And just on a side note: Your full test code leaks a
QProcess
- an eye catching antipattern. -
@kshegunov , @Axel-Spoerl
Your comments are, of course, quite correct, However, I would remind you and OP that, as per my first reply, the command being issued is/usr/bin/gnome-terminal lsusb
. This is an incorrect command line for/usr/bin/gnome-terminal
. The trailinglsusb
is simply ignored in this case, it is not run, and instead an interactive terminal is simply opened, just as the screenshot shows.Furthermore, as also discussed in the past, a terminal such as
/usr/bin/gnome-terminal
(with or without the correct arguments to cause it to run a command) simply does not produce any output on the stdout, so nothing can be read fromQProcess
from it. Consider the following:gnome-terminal -- find / -print
[We have to call something which produces voluminous output, else the terminal window opens, runs the command and closes so quickly that you do not see anything.] You see the output running by in the opened terminal, till it concludes. Now try
jon@ubuntu-22:~$ gnome-terminal -- find / -print > output jon@ubuntu-22:~$ ls -l output -rw-rw-r-- 1 jon jon 0 Feb 16 09:47 output
Same behaviour as without the attempted redirection: the output appears in the opened terminal window, and at the end nothing has been written into
output
file, i.e. redirection from calling program captures nothing.Terminals such as
gnome-terminal
(and the others, e..gxterm
) start by creating a window and attaching their stdout to that (pseudo-tty). You cannot get at their output via the normal redirection which would work on a command without running it in a terminal. I have said this to OP in the past for just this question. -
@JonB said in How to make QProcess "interactive" ?:
the output appears in the opened terminal window,
Please explain the above - if it is is NOT "'stdxx" what is it ?
... and why QProcess does not pass the "lsusb" at all?
is it not passed as an "option"? -
@AnneRanch
Anne, I explained both of these above. You ask for clarification but what can I say further to what In have written? Summary:-
The command you are issuing,
gnome-terminal lsusb
, is not and never has been the correct syntax to askgnome-terminal
to run a command. It ignores thelsusb
completely and simply runsgnome-terminal
. So you see an interactive terminal window sitting there instead. For Ubuntu the command should begnome-terminal -- lsusb
. That will open the window, runlsusb
and close the window when that finishes. Which happens so quickly in milliseconds that you simply won't see anything, the window will open and close faster than you can see. Which is why I said if you were to rungnome-terminal -- find / -print
you will get to see what actually is happening. You can try these outside of your Qt program from a terminal. -
If you invoke
gnome-terminal
, or any other "terminal" such asxterm
, to run a command (such aslsusb
) the terminal will attach its stdout to the window it opens. That means no matter what your calling program --- a Linux shell or a Qt application --- it will not receive or be able to access any output the command (lsusb
or whatever) produces e.g. on its stdout. That will go to the terminal window and cannot be seen by the calling application.
As per when we discussed this a year or two ago and I said then, if you want to be able to read back the output from, say,
lsusb
you must run it directly (as the command you tellQProcess
to start) and not invoke anygnome-terminal
orxterm
or other terminal to run it. -