PDA

View Full Version : QProcess, plink, mysql



tpf80
8th October 2008, 10:44
Hi, I am attempting to create a scenario where my program uses plink to create a ssh tunnel, and once it knows the tunnel is up, then log in to a mysql database. The pertinent piece of code that does this is as follows:


bool programMain::serverConnect() {
//make the tunnel channel display:
tunnel.setProcessChannelMode(QProcess::SeparateCha nnels);
tunnel.setReadChannel(QProcess::StandardOutput);
//spawn the SSH tunnel:
tunnel.start("c:/progra~1/PuTTY/plink.exe -l user -ssh -pw password -C -v -N -L 9999:111.111.111.111:9999 remotecomputer.domain.com");
//open SSH tunnel
if (!tunnel.waitForStarted(20000)) {
QMessageBox::critical(0, qApp->tr("Could not open SSH Tunnel"),
qApp->tr("Unable to create secure ssh tunnel!\n\n")+ qApp->tr("\n\nClick Cancel to exit."), QMessageBox::Cancel,
QMessageBox::NoButton);
return false;
}
//hold the database login until the tunnel has responded with a login message:
if (!tunnel.waitForReadyRead(20000)) {
QMessageBox::critical(0, qApp->tr("SSH connection not responding!"),
qApp->tr("SSH response timed out!\n\n")+ qApp->tr("\n\nClick Cancel to exit."), QMessageBox::Cancel,
QMessageBox::NoButton);
return false;
}

//connect to the server:
if (!createConnection(login.serveraddy, login.databasename, login.username, login.password, login.port)) {
return false;
}
return true;
}


The results are as follows:

-If I run the code as-is, it will give me the "SSH connection not responding!" message, because for some reason ReadyRead never is triggered.

-If i remove the "if (!tunnel.waitForReadyRead(20000)) {" piece, then it creates the ssh tunnel fine, however it does not wait to try to connect to the database after plink is started *and* plink is done connecting, so the database connection fails.

This was what I was hoping to accomplish with the "if (!tunnel.waitForReadyRead(20000)) {" code, to make it wait till plink spit out the login successful text, and then continue on to log in to MySql.

if I change "tunnel.setProcessChannelMode(QProcess::SeparateCha nnels);" to "tunnel.setProcessChannelMode(QProcess::ForwardedCh annels);", i can see the terminal showing the login process going through fine, so I can only assume that there is some problem with the wait code.

I could put some kind of timer to wait until most likely the tunnel should be created, but I would like the program to start logging in to mysql as soon as it can after ssh is done, for the best user experience.

any tips on how I could do this?

tpf80
9th October 2008, 02:28
Basically what I think I need to figure out, is how do I read the output of the process properly. If I can read what plink outputs, and then do some handling with it then I would be ok, but I am not totally understanding how to:
1) tell if a QProcess is sending any output
2) how to capture that output

yuriry
9th October 2008, 02:42
If tunnel is an instance of QProcess then you can read from/write to it as with any QIODevice.

tpf80
9th October 2008, 11:43
tunnel is a QProcess.

do you have an example of reading from/writing to a QProcess? (reading from the process is what i'm most interested in) It seems most of the examples here are using start detached rather than actually controlling the process.

yuriry
9th October 2008, 17:57
In the attached example I use QTextStream::readAll() for simplicity. You can pass a process name from as a command line argument, /bin/ls is a default value.

tpf80
10th October 2008, 03:26
Thanks for the helpful code, although i did not solve my problem quite yet, It seems that I am close.

I compiled the example you gave me on a test machine and put in:


QString cmd = "cmd.exe";
m_p->start(cmd);

as a test and I got "Microsoft Windows XP [Version 5.1.2600] (C) Copyright 1985-2001 Microsoft Corp." to spit out, so I know your code is working how expected.

I then changed the code to run plink as follows:


QString cmd = "c:/progra~1/PuTTY/plink.exe -l username -ssh -pw \"password\" -C -v -N -L 9999:111.111.111.111:9999 server.somewhere.com";
m_p->start(cmd);


what is interesting, is that when I use plink in the QProcess, the program spits out no text. I do know plink is working though because I can see in the task manager that process.exe and plink.exe are running, and the ssh tunnel is working. If I type that command on the command line, i get a very verbose chunk of text output from plink.

So, it seems my problem is that for whatever reason, plink's output does not trigger the "readyReadStandardOutput()" signal in QProcess. Any clue as to why that could happen?

tpf80
10th October 2008, 03:28
ah I found it!

plink for some reason writes all it's output to the error channel. so changing "readyReadStandardOutput()" to "readyReadStandardError()" for the signal, made it work.

thanks again for your help!