4

I am trying to generate a subprocess for a gui which will spawn a terminal. I want the data produced by this terminal (stdout and stderr) to be displayed on the window that appears as well as to a set log file. When I type the command directly in to a shell it works as intended, but when provided to a QProcess as a start command it doesn't actually write anything to the file.

For example: if the user doesn't have the binaries installed it should write to bin.log that the command was not found. I have set my environment for the spawned QProcess to be the same as the running parent process (so that it can find bash and anything else), and have set the working directory before calling QProcess.start() method. I wrote a test case which follows:

gnome-terminal --title 'Sub-Terminal' -e 'bash -c "foo [args to foo] |& tee foo.log"'

In Qt I do the following:

QProcess *child = new QProcess(this);
QString   cmd   = "gnome-terminal --title 'Sub-Terminal' -e 'bash -c \"foo [args to foo] |& tee foo.log\"'";
child->setProcessEnvironment(<process environment I have created before>);
child->setWorkingDirectory(<current working dir>);
child->start(cmd);
...

It generates the terminal but does not write any data to foo.log. I have also tried the following:

QProcess *child = new QProcess(this);
QString   prog  = "gnome-terminal"
QStringList args;
args << "-x" << "bash" << "foo" << "[foo's arguments]" << "|&" << "tee" << "foo.log";
// set the process env and working dir
child->start(prog, args);

Does anyone have any advice on how to solve this? I have tried redirecting stdout and stderr using QProcess.setStandardErrorFile(foo.log) and QProcess.setStandardOutputFile(foo.log), but it seems like that would be redirecting the stdout from the gnome-terminal itself (which isn't anything).

ElCraneo
  • 495
  • 1
  • 6
  • 11

1 Answers1

2

You have to provide the whole command to be executed in the terminal as one single argument to QProcess after "-e", as well as the command to be executed in bash as one single argument to bash:

args << "-e" << "bash -c 'foo [args to foo] |& tee foo.log'";

This basically executes

bash -c 'foo [args to foo] |& tee foo.log'

in the terminal, which by itself executes

foo [args to foo] |& tee foo.log

within bash.

You are right with your guess that reading the outputs from the gnome-terminal process doesn't work.

leemes
  • 44,967
  • 21
  • 135
  • 183
  • Sadly this doesn't seem to work. When replacing foo with ls (no arguments) I get the following error: failed to execute child process "bash -c 'ls |& tee tester.out'" (no such file or directory) – ElCraneo Dec 07 '12 at 20:51
  • 1
    Replacing the '-x' argument to the gnome-terminal with a '-e' argument causes everything to work fine! I'm not entirely sure what would cause this difference in behaviors. -x says that it executes the remainder of the command line whereas -e says it executes the argument as a string within the shell. Seeing as both arguments are the remainder of the line, I'm not sure what the difference is. – ElCraneo Dec 07 '12 at 21:13
  • @user1886389 This means for example: `gnome-terminal -x ls foo` executes `ls foo`, whereas `gnome-terminal -e ls foo` executes `ls` and it doesn't know what to do with the other argument `foo` (They are two arguments!) But `gnome-terminal -e "ls foo"` will execute `ls foo` (As it is a *single* argument). Thank you for the hint. I'm used to write `-e`, so I just didn't notice you have written `-x` in the other code snippet which behaves differently as we now know ;) If you are satisfied with this answer, please upvote and/or accept it. And by the way: Welcome to Stack Overflow! ;) – leemes Dec 07 '12 at 21:23