在qt5.12.6中想使用QProcess类进行ssh连接,显示总是连接成功返回值为空,这个为什么?怎么解决?或者说应该怎么写?(已经在终端和用putty测试了ssh可以正常连接而且打印正常,都是root/)
编译输出结果如下:
[Krn64.dll][25024][25844][INFO] [ProcessInject::HookCreateProcessW] [NULL], [ssh root@192.168.234.100] is not cmd process, no need remote inject
QProcess::start: Process is already running
QProcess: Destroyed while process ("ssh") is still running.
Exit code: 62097
Exit status: QProcess::CrashExit
Output: ""
Error: ""
Process crashed. Error: "Process crashed"
subWidgetSwitched QMdiSubWindow(0x5be2600)
// 创建一个QProcess对象
QProcess process;
QStringList command;
process.setProcessChannelMode(QProcess::SeparateChannels);
command << "root@192.168.234.100" <<"pwd";
process.start("ssh", command);
if (process.waitForStarted())
{
process.closeWriteChannel();
QObject::connect(&process, &QProcess::readyReadStandardOutput, [&](){
qDebug() << "Output: " << process.readAllStandardOutput();
});
QObject::connect(&process, &QProcess::readyReadStandardError, [&](){
qDebug() << "Error: " << process.readAllStandardError();
});
// 异步等待命令执行完成
QObject::connect(&process, QOverload<int, QProcess::ExitStatus>::of(&QProcess::finished), [&](int exitCode, QProcess::ExitStatus exitStatus){
QByteArray result = process.readAllStandardOutput();
QByteArray error = process.readAllStandardError();
qDebug() << "Exit code:" << exitCode;
qDebug() << "Exit status:" << exitStatus;
qDebug() << "Output:" << result;
qDebug() << "Error:" << error;
if (exitStatus == QProcess::CrashExit) {
qDebug() << "Process crashed. Error: " << process.errorString();
}
});
}
else
{
qDebug() << "Failed to start the command.";
}
ssh参数给的有问题,不能这么给用户名和密码,所以链接错误。
#include <QProcess>
int main(int argc, char *argv[])
{
QProcess process;
process.start("ssh", QStringList() << "root@192.168.234.100" << "pwd");
if (process.waitForStarted()) {
process.closeWriteChannel();
QObject::connect(&process, &QProcess::readyReadStandardOutput, [this] {
qDebug() << "Output: " << process.readAllStandardOutput();
});
QObject::connect(&process, &QProcess::readyReadStandardError, [this] {
qDebug() << "Error: " << process.readAllStandardError();
});
QObject::connect(&process, &QProcess::finished, [this, exitCode] {
if (exitCode == QProcess::CrashExit) {
qDebug() << "Process crashed. Error: " << process.errorString();
}
emit finished(exitCode);
});
} else {
qDebug() << "Failed to start the command.";
}
return 0;
}
参考
(1) Building Qt 5 from Git https://wiki.qt.io/Building_Qt_5_from_Git
(2) QProcess Class | Qt Core 6.5.1. https://doc.qt.io/qt-6/qprocess.html
(3) Qt QSsh 使用 windows Qt实现ssh客户端 https://blog.csdn.net/qq_41673920/article/details/103687644
Qt_QSsh 使用 windows Qt实现ssh客户端
CConnectionForSshClient.h
#ifndef CCONNECTIONFORSSHCLIENT_H
#define CCONNECTIONFORSSHCLIENT_H
/* Func:以用户密码的形式连接ssh服务器 发送命令到shell执行 需加\n
* Note:定时检查连接状态的逻辑是 连接成功关闭定时器检查
* 连接断开 开启定时器检查并尝试重连 直至连接成功
* 即关闭定时器检查
* Use:绑定两个信号
* 检测状态:sigConnectStateChanged(bState,strIp,nPort);
* 接收信息:sigDataArrived(QString strMsg,QString strIp, int nPort);
* 绑定一个槽
* 发送信息:void slotSend(QString strMsg);
*/
#include <sshconnection.h>
#include <sshremoteprocess.h>
#include <sftpchannel.h>
#include <QTimer>
#include <QHostAddress>
#include <QThread>
#define RECONNET_SPAN_TIME (1000*10) //连接状态心跳
class CConnectionForSshClient : public QObject
{
Q_OBJECT
public:
explicit CConnectionForSshClient(QString strIp, int nPort = 22,QString strPwd = "17909",QString strUser = "root");
void init();
void unInit();
~CConnectionForSshClient();
private:
QThread *m_pThread = nullptr;
bool m_bConnected = false;
bool m_bIsFirstConnect = true;
bool m_bSendAble = false;
QTimer *m_pTimer;
QString m_strIp = "";
int m_nPort = -1;
QString m_strUser;
QString m_strPwd;
QString m_strIpPort;
QSsh::SshConnectionParameters m_argParameters;
QSsh::SshConnection *m_pSshSocket = nullptr;
QSharedPointer<QSsh::SshRemoteProcess> m_shell;
signals:
void sigInitForClild();
void sigConnectStateChanged(bool bState,QString strIp,int nPort);
void sigDataArrived(QString strMsg,QString strIp, int nPort);
private:
int send(QString strMessage);
QString getIpPort(){return m_strIp + ":" + QString::number(m_nPort);}
public slots:
void slotResetConnection(QString strIpPort);
void slotSend(QString strIpPort,QString strMessage);
void slotSend(QString strMsg);
void slotSendByQByteArray(QString strIpPort,QByteArray arrMsg);
void slotDisconnected();
void slotDataReceived();
private slots:
void slotInitForClild();
void slotCreateConnection();
void slotConnected();
void slotThreadFinished();
void slotSshConnectError(QSsh::SshError sshError);
void slotShellStart();
void slotShellError();
};
#endif // CCONNECTIONFORSSHCLIENT_H
CConnectionForSshClient.cpp
#include "CConnectionForSshClient.h"
#include <QDebug>
CConnectionForSshClient::CConnectionForSshClient(QString strIp, int nPort, QString strPwd, QString strUser)
{
m_strIp = strIp;
m_nPort = nPort;
m_strUser = strUser;
m_strPwd = strPwd;
m_strIpPort = m_strIp + ":" + QString::number(m_nPort);
}
void CConnectionForSshClient::init()
{
m_pThread = new QThread();
connect(m_pThread,SIGNAL(finished()),this,SLOT(slotThreadFinished()));
this->moveToThread(m_pThread);
m_pThread->start();
//之后的逻辑都得通过信号和槽接通
connect(this,SIGNAL(sigInitForClild()),this,SLOT(slotInitForClild()));
emit sigInitForClild();
}
void CConnectionForSshClient::unInit()
{
m_pThread->quit();
}
int CConnectionForSshClient::send(QString strMessage)
{
qDebug()<<"CConnectionForSshClient ssh send "<<strMessage;
int nSize = 0;
if(m_bConnected && m_bSendAble){
nSize = m_shell->write(strMessage.toLatin1().data());
}else{
qDebug()<<"CConnectionForSshClient::send() ssh未连接 或 shell未连接:"<<getIpPort();
}
return nSize;
}
CConnectionForSshClient::~CConnectionForSshClient()
{
if(nullptr != m_pSshSocket){
delete m_pSshSocket;
m_pSshSocket = nullptr;
}
}
void CConnectionForSshClient::slotResetConnection(QString strIpPort)
{
if(this->getIpPort() == strIpPort){
this->slotDisconnected();
}
}
void CConnectionForSshClient::slotSend(QString strIpPort, QString strMessage)
{
if(0 != m_strIpPort.compare(strIpPort)){
return;
}
send(strMessage);
}
void CConnectionForSshClient::slotSendByQByteArray(QString strIpPort, QByteArray arrMsg)
{
if(0 != m_strIpPort.compare(strIpPort)){
return;
}
if(m_bConnected){
m_shell->write(arrMsg);
}else{
qDebug()<<"CConnectionForSshClient::send(QString strMessage) 发送失败 未建立连接:"<<getIpPort();
}
}
void CConnectionForSshClient::slotInitForClild()
{
m_argParameters.port = m_nPort;
m_argParameters.userName = m_strUser;
m_argParameters.password = m_strPwd;
m_argParameters.host = m_strIp;
m_argParameters.timeout = 10;
m_argParameters.authenticationType =
QSsh::SshConnectionParameters::AuthenticationTypePassword; //密码方式连接
slotCreateConnection(); //连接
m_pTimer = new QTimer(this);
m_pTimer->setInterval(RECONNET_SPAN_TIME);
connect(m_pTimer,SIGNAL(timeout()),this,SLOT(slotCreateConnection()));
m_pTimer->start();//启动心跳定时器,每隔一段时间进入slotCreateConnection判断是否需要重连
}
void CConnectionForSshClient::slotCreateConnection()
{
qDebug()<<"CConnectionForSshClient::slotCreateConnection检查连接" ;
if(true == m_bConnected)
return;
if(nullptr == m_pSshSocket){
m_pSshSocket = new QSsh::SshConnection(m_argParameters);
connect(m_pSshSocket,SIGNAL(connected()),SLOT(slotConnected()));
connect(m_pSshSocket,SIGNAL(error(QSsh::SshError)),SLOT(slotSshConnectError(QSsh::SshError)));
}
m_pSshSocket->connectToHost();
qDebug()<<"CConnectionForSshClient::slotCreateConnection() 以ssh方式 尝试连接:"<<getIpPort();
}
void CConnectionForSshClient::slotConnected()
{
qDebug()<<"CConnectionForSshClient::slotConnected ssh已连接到:"<<getIpPort();
m_pTimer->stop();
m_shell = m_pSshSocket->createRemoteShell();
connect(m_shell.data(), SIGNAL(started()), SLOT(slotShellStart()));
connect(m_shell.data(), SIGNAL(readyReadStandardOutput()), SLOT(slotDataReceived()));
connect(m_shell.data(), SIGNAL(readyReadStandardError()), SLOT(slotShellError()));
m_shell.data()->start();
m_bConnected = true;
emit sigConnectStateChanged(m_bConnected,m_strIp,m_nPort);
}
void CConnectionForSshClient::slotDisconnected()
{
m_pSshSocket->disconnectFromHost();
}
void CConnectionForSshClient::slotThreadFinished()
{
m_pThread->deleteLater();
this->deleteLater();
}
void CConnectionForSshClient::slotSshConnectError(QSsh::SshError sshError)
{
m_bSendAble = false;
m_bConnected = false;
emit sigConnectStateChanged(m_bConnected,m_strIp,m_nPort);
m_pTimer->start();
switch(sshError){
case QSsh::SshNoError:
qDebug()<<"slotSshConnectError SshNoError"<<getIpPort();
break;
case QSsh::SshSocketError:
qDebug()<<"slotSshConnectError SshSocketError"<<getIpPort(); //拔掉网线是这种错误
break;
case QSsh::SshTimeoutError:
qDebug()<<"slotSshConnectError SshTimeoutError"<<getIpPort();
break;
case QSsh::SshProtocolError:
qDebug()<<"slotSshConnectError SshProtocolError"<<getIpPort();
break;
case QSsh::SshHostKeyError:
qDebug()<<"slotSshConnectError SshHostKeyError"<<getIpPort();
break;
case QSsh::SshKeyFileError:
qDebug()<<"slotSshConnectError SshKeyFileError"<<getIpPort();
break;
case QSsh::SshAuthenticationError:
qDebug()<<"slotSshConnectError SshAuthenticationError"<<getIpPort();
break;
case QSsh::SshClosedByServerError:
qDebug()<<"slotSshConnectError SshClosedByServerError"<<getIpPort();
break;
case QSsh::SshInternalError:
qDebug()<<"slotSshConnectError SshInternalError"<<getIpPort();
break;
default:
break;
}
}
void CConnectionForSshClient::slotShellStart()
{
m_bSendAble = true;
qDebug()<<"CConnectionForSshClient::slotShellStart Shell已连接:"<<getIpPort();
}
void CConnectionForSshClient::slotShellError()
{
qDebug()<<"CConnectionForSshClient::slotShellError Shell发生错误:"<<getIpPort();
}
void CConnectionForSshClient::slotSend(QString strMessage)
{
send(strMessage);
}
void CConnectionForSshClient::slotDataReceived()
{
QByteArray byteRecv = m_shell->readAllStandardOutput();
QString strRecv = QString::fromUtf8(byteRecv);
// if(strRecv.contains("password for")){
// m_shell->write(m_strPwd.toLatin1().data());
// }
if(!strRecv.isEmpty()) //过滤空行
emit sigDataArrived(strRecv, m_strIp, m_nPort);
}
我觉得应该是你传递参数的问题,首先要确保在连接ssh时输入了正确的用户名密码等参数,才能连接到SSH。你现在看起是连接成功了,但是返回为空,有可能是还没有正确连接到所以才会出现为空的现象。
具体实现可以参考:
封装一个类,名称为CSSHPROCESS,类的作用为实现SSH与远程机器交互:https://qt.0voice.com/?id=32
传递参数格式不对吧
检查一下传参是否正确
根据你提供的代码,问题可能出在以下几个方面:
SSH连接参数不正确:确认SSH连接的参数是否正确,包括SSH用户名、IP地址和端口号等。确保这些参数与你在终端或Putty中测试成功的参数一致。
QProcess命令参数不正确:在你的代码中,你将目标IP地址作为命令参数传递给SSH命令。但是SSH命令需要指定SSH连接的目标主机,而不是直接的IP地址。正确的SSH命令应该是ssh root@192.168.234.100
,而不仅仅是root@192.168.234.100
。因此,你需要将SSH命令和目标主机作为两个参数传递给process.start()
方法。
修改后的代码应该类似于:
QStringList command;
command << "ssh" << "root@192.168.234.100";
process.start("ssh", command);
QProcess::finished
信号连接到一个lambda函数,并在该函数中读取输出和错误信息。然而,这些读取操作应该在QProcess::readyReadStandardOutput
和QProcess::readyReadStandardError
信号的槽函数中完成。因此,你需要将输出和错误信息的读取操作移到对应的槽函数中。修改后的代码应该类似于:
QObject::connect(&process, &QProcess::readyReadStandardOutput, [&]() {
qDebug() << "Output: " << process.readAllStandardOutput();
});
QObject::connect(&process, &QProcess::readyReadStandardError, [&]() {
qDebug() << "Error: " << process.readAllStandardError();
});
// 异步等待命令执行完成
QObject::connect(&process, QOverload<int, QProcess::ExitStatus>::of(&QProcess::finished), [&](int exitCode, QProcess::ExitStatus exitStatus) {
QByteArray result = process.readAllStandardOutput();
QByteArray error = process.readAllStandardError();
qDebug() << "Exit code:" << exitCode;
qDebug() << "Exit status:" << exitStatus;
qDebug() << "Output:" << result;
qDebug() << "Error:" << error;
});
请注意,为了能够正确接收到输出和错误信息,建议将process.setProcessChannelMode(QProcess::SeparateChannels)
设置放在process.start()
之前。
希望这些修改能够解决你的问题!如果还有其他疑问,请随时提问。