- 基于libssh2,使用层次遍历的方式,从远端拷贝文件到本地目录,支持所有目录(等同于ssh -r效果)
#include <string>
#include <QString>
#include <libssh2.h>
#include <libssh2_sftp.h>
static QString sourceDir = "";
static std::queue<QString> que;
static std::vector<QString> vec;
int sftp_hierarchical_traversal() {
std::queue<QString> emptyQue;
std::swap(que, emptyQue);
vec.clear();
que.push(sourceDir);
const char* username = "";
const char* password = "";
std::string clientAddress = "";
const char* hostname = "";
const char* remote_path = "";
const char* local_path = "";
int port = 22;
struct sockaddr_in sin;
unsigned long hostaddr;
int rc = libssh2_init(0);
if (rc != 0) {
fprintf(stderr, "Failed to initialize libssh2\n");
return 1;
}
LIBSSH2_SESSION* session = libssh2_session_init();
if (!session) {
fprintf(stderr, "Failed to create SSH session\n");
libssh2_exit();
return 1;
}
hostaddr = inet_addr(hostname);
sin.sin_family = AF_INET;
sin.sin_port = htons(22);
sin.sin_addr.s_addr = hostaddr;
int sock = socket(AF_INET, SOCK_STREAM, 0);
if (sock == -1) {
std::cerr << "Failed to create socket" << std::endl;
return 1;
}
if (::connect(sock, (struct sockaddr*)(&sin),
sizeof(struct sockaddr_in)) != 0) {
fprintf(stderr, "failed to connect!\n");
return -1;
}
libssh2_session_set_blocking(session, 1);
rc = libssh2_session_handshake(session, sock);
if (rc) {
fprintf(stderr, "Failed to connect to %s:%d\n", hostname, port);
libssh2_session_disconnect(session, "Failed to connect");
libssh2_session_free(session);
libssh2_exit();
return 1;
}
if (libssh2_userauth_password(session, username, password)) {
fprintf(stderr, "Authentication by password failed\n");
libssh2_session_disconnect(session, "Authentication failed");
libssh2_session_free(session);
libssh2_exit();
return 1;
}
LIBSSH2_SFTP* sftp_session = libssh2_sftp_init(session);
if (!sftp_session) {
fprintf(stderr, "Failed to initialize SFTP session\n");
libssh2_session_disconnect(session, "Failed to initialize SFTP session");
libssh2_session_free(session);
libssh2_exit();
return 1;
}
while (!que.empty()) {
QString remotePath = que.front();
LIBSSH2_SFTP_HANDLE* sftp_handle;
sftp_handle = libssh2_sftp_opendir(sftp_session, remotePath.toLocal8Bit().constData());
if (!sftp_handle) {
return 0;
}
char buffer[512];
while (1) {
LIBSSH2_SFTP_ATTRIBUTES attrs;
const char* filename;
int rc = libssh2_sftp_readdir(sftp_handle, buffer, sizeof(buffer), &attrs);
if (rc <= 0) {
break;
}
if (strcmp(buffer, ".") == 0 || strcmp(buffer, "..") == 0) {
continue;
}
filename = buffer;
QString remoteFile = remotePath + "/" + filename;
if (LIBSSH2_SFTP_S_ISDIR(attrs.permissions)) {
que.push(remoteFile);
}
else {
vec.push_back(remoteFile);
LIBSSH2_SFTP_ATTRIBUTES attrs;
libssh2_sftp_stat(sftp_session, remoteFile.toLocal8Bit().constData(), &attrs);
if (attrs.flags & LIBSSH2_SFTP_ATTR_PERMISSIONS && LIBSSH2_SFTP_S_ISREG(attrs.permissions)) {
QString local_file = remoteFile;
local_file.replace(sourceDir, stateCache_imageDir);
QFileInfo fileInfo(local_file);
QDir directory = fileInfo.dir();
if (!directory.exists()) {
QDir().mkpath(directory.absolutePath());
}
FILE* local_fp = fopen(local_file.toLocal8Bit().constData(), "wb");
LIBSSH2_SFTP_HANDLE* remote_handle = libssh2_sftp_open(sftp_session, remoteFile.toLocal8Bit().constData(), LIBSSH2_FXF_READ, 0);
size_t nread;
char buffer[1024];
do {
nread = libssh2_sftp_read(remote_handle, buffer, sizeof(buffer));
if (nread > 0) {
fwrite(buffer, 1, nread, local_fp);
}
} while (nread > 0);
fclose(local_fp);
libssh2_sftp_close(remote_handle);
}
}
}
que.pop();
}
}
- 直接调用ssh可执行文件的方式(需要在本机上生成公钥私钥,把公钥放到远端主机的.ssh目录下):
QString appPath = QCoreApplication::applicationDirPath();
QString program = "scp.exe";
QStringList arguments;
arguments << "-r" << QString::fromLocal8Bit("-i") << QString(appPath + "/id_rsa") << QString("-o") << QString("StrictHostKeyChecking no") << QString("root\@:/source ")) << stateCache_imageDir;
qDebug() << appPath + "/id_rsa";
QProcess process;
process.start(program, arguments);
process.waitForFinished(-1);
QByteArray output = process.readAllStandardOutput();
QByteArray error = process.readAllStandardError();
LOG_ERROR(QString("Output : %1.").arg(QString(output)));
LOG_ERROR(QString("Error : %1.").arg(QString(error)));