头文件代码如下所示:
#ifndef CSSHPROCESS_H
#define CSSHPROCESS_H
#include <QObject>
#include <QStringList>
#include <QProcess>
#include <QList>
struct FileDetail {
QString path;
QString type; // d for directory, f for file
};
class CSSHProcess : public QObject
{
Q_OBJECT
public:
explicit CSSHProcess(QString username, QString host, QString password, QObject *parent = nullptr);
~CSSHProcess();
void copyFiles(QList<FileDetail> files, QString remotePath); // Copy files from local to remote or vice versa
void deleteFiles(QList<FileDetail> files); // Delete files on remote machine
void backupFiles(QList<FileDetail> files, QString backupPath); // Backup files to specified location before modifying them
void restoreFiles(QList<FileDetail> files); // Restore files from backup location
QList<FileDetail> listDirectory(QString path); // List files in specified directory on remote machine
void disconnect(); // Disconnect from remote machine and close terminal
private:
QString m_username; // Remote machine username
QString m_host; // Remote machine IP address or hostname
QString m_password; // Remote machine login password
QProcess *m_process; // Terminal process for interacting with remote machine
QString m_tempDir; // Temporary directory for storing backup files
bool m_isConnected; // Flag for whether the connection has been established
void runCommand(QString command); // Run command on the remote machine using SSH and Expect scripts
QStringList generateExpectCommands(QStringList commands); // Generate Expect commands based on the input SSH commands
QString getFileNameFromPath(QString path); // Get the filename from a full file path
void printTerminalOutput(); // Print the output of the terminal process to qDebug
};
#endif // CSSHPROCESS_H
源文件代码如下所示:
#include "csshprocess.h"
#include <QDir>
#include <QDebug>
CSSHProcess::CSSHProcess(QString username, QString host, QString password, QObject *parent)
: QObject(parent), m_username(username), m_host(host), m_password(password), m_process(new QProcess(this)), m_isConnected(false)
{
// Create temporary directory for backup files
m_tempDir = QDir::tempPath() + "/sshbackup";
QDir temp(m_tempDir);
if (!temp.exists()) {
temp.mkpath(".");
}
// Run command to connect to remote machine using SSH and Expect scripts
QStringList sshCommands = {"ssh", m_username + "@" + m_host};
QStringList expectCommands = generateExpectCommands(sshCommands);
runCommand(expectCommands.join(" && "));
// Set up signal-slot connection to print terminal output
connect(m_process, &QProcess::readyReadStandardOutput, this, &CSSHProcess::printTerminalOutput);
connect(m_process, &QProcess::readyReadStandardError, this, &CSSHProcess::printTerminalOutput);
}
CSSHProcess::~CSSHProcess()
{
// Disconnect from remote machine and close terminal
disconnect();
}
void CSSHProcess::copyFiles(QList<FileDetail> files, QString remotePath)
{
QString scpCommand;
QString sourcePath;
QString destinationPath;
// Loop through each file and add SCP command to the list of commands to run on the remote machine
foreach (FileDetail file, files) {
sourcePath = file.path;
if (file.type == "d") {
sourcePath += "/";
}
destinationPath = remotePath + "/" + getFileNameFromPath(file.path);
scpCommand = "scp -r " + sourcePath + " " + m_username + "@" + m_host + ":" + destinationPath;
runCommand(scpCommand);
}
}
void CSSHProcess::deleteFiles(QList<FileDetail> files)
{
QString rmCommand;
// Loop through each file and add RM command to the list of commands to run on the remote machine
foreach (FileDetail file, files) {
rmCommand = "rm -r " + file.path;
runCommand(rmCommand);
}
}
void CSSHProcess::backupFiles(QList<FileDetail> files, QString backupPath)
{
QString mkdirCommand;
QString cpCommand;
QString sourcePath;
QString destinationPath;
QDir tempDir(m_tempDir);
// Create backup directory
mkdirCommand = "mkdir -p " + backupPath;
runCommand(mkdirCommand);
// Loop through each file and copy it to the temporary backup directory
foreach (FileDetail file, files) {
sourcePath = file.path;
if (file.type == "d") {
sourcePath += "/";
}
destinationPath = m_tempDir + "/" + getFileNameFromPath(file.path);
cpCommand = "cp -r " + sourcePath + " " + destinationPath;
runCommand(cpCommand);
}
// Copy backup directory to specified location on remote machine
scpCommand = "scp -r " + m_tempDir + "/* " + m_username + "@" + m_host + ":" + backupPath;
runCommand(scpCommand);
// Clean up temporary backup directory
tempDir.removeRecursively();
}
void CSSHProcess::restoreFiles(QList<FileDetail> files)
{
QString cpCommand;
QString sourcePath;
QString destinationPath;
// Loop through each file and copy it from the backup directory to its original location on the remote machine
foreach (FileDetail file, files) {
sourcePath = getFileNameFromPath(file.path);
if (file.type == "d") {
destinationPath = file.path + "/";
} else {
destinationPath = file.path;
}
cpCommand = "cp -r " + m_tempDir + "/" + sourcePath + " " + destinationPath;
runCommand(cpCommand);
}
}
QList<FileDetail> CSSHProcess::listDirectory(QString path)
{
QString lsCommand = "ls -l " + path;
QStringList outputList;
QStringList fileList;
QList<FileDetail> fileDetails;
// Run LS command on remote machine and capture output
runCommand(lsCommand);
// Parse output into list of file paths and types
while (m_process->canReadLine()) {
QString line = QString(m_process->readLine()).trimmed();
outputList.append(line);
}
for (int i = 1; i < outputList.size(); i++) { // Skip first line as it's just the total file size
QString line = outputList.at(i);
QStringList parts = line.split(QRegExp("\\s+"), Qt::SkipEmptyParts);
if (parts.size() >= 9) {
QString filePath = parts.at(8);
QString fileType = parts.at(0).left(1); // Get first character of permission string to determine file or directory
FileDetail file = {filePath, fileType};
fileDetails.append(file);
}
}
return fileDetails;
}
void CSSHProcess::disconnect()
{
if (m_isConnected) {
runCommand("exit");
m_process->waitForFinished();
m_isConnected = false;
}
}
void CSSHProcess::runCommand(QString command)
{
// Write command to terminal process and wait for it to finish
m_process->write(command.toUtf8() + "\r\n");
m_process->waitForBytesWritten();
m_process->waitForReadyRead(-1);
m_isConnected = true;
}
QStringList CSSHProcess::generateExpectCommands(QStringList commands)
{
QStringList expectCommands;
// Generate command to connect to remote machine using SSH and Expect scripts
expectCommands.append("spawn " + commands.at(0));
expectCommands.append("expect \"assword:\"");
expectCommands.append("send \"" + m_password + "\\r\"");
expectCommands.append("interact");
return expectCommands;
}
QString CSSHProcess::getFileNameFromPath(QString path)
{
QFileInfo fileInfo(path);
return fileInfo.fileName();
}
void CSSHProcess::printTerminalOutput()
{
// Print terminal output to qDebug
while (m_process->canReadLine()) {
QString line = QString(m_process->readLine()).trimmed();
qInfo() << line;
}
}
脚本文件代码如下所示:
#!/usr/bin/expect -f
# Turn off output buffering
set timeout -1
# Connect to remote machine using SSH
spawn ssh $argv
# Expect password prompt and send password
expect "assword:"
send [lindex $argv 1]"\\r"
# Allow interaction with terminal session
interact
注意:上述代码仅供参考,可能需要根据具体情况进行修改和优化。