SSH连接SFTP传输:如何使用libssh库在Linux环境下进行(文件、文件夹)传输到远端服务器

这篇具有很好参考价值的文章主要介绍了SSH连接SFTP传输:如何使用libssh库在Linux环境下进行(文件、文件夹)传输到远端服务器。希望对大家有所帮助。如果存在错误或未考虑完全的地方,请大家不吝赐教,您也可以点击"举报违法"按钮提交疑问。

建立SSH会话并连接远端服务器

  • target_host:远端主机IP
  • target_username:远端主机用户名
ssh_session session;

// 连接SSH会话
session = ssh_new();
if (!session) {
    fprintf(stderr, "Failed to create SSH session\n");
    return -1;
}

ssh_options_set(session, SSH_OPTIONS_HOST, target_host);
ssh_options_set(session, SSH_OPTIONS_USER, target_username);

//建立连接
if (ssh_connect(session) != SSH_OK) {
    fprintf(stderr, "Failed to connect to SSH session: %s\n", ssh_get_error(session));
    ssh_free(session);
    return -1;
}

ssh_options_set() 函数设置会话的选项。最重要的选项是:

  • SSH_OPTIONS_HOST:要连接到的主机的名称
  • SSH_OPTIONS_PORT:使用的端口(默认为端口 22)
  • SSH_OPTIONS_USER:要连接的系统用户
  • SSH_OPTIONS_LOG_VERBOSITY:打印的消息数量

SSH身份验证

密码验证

直接传输密码即可 target_password即密码

if (ssh_userauth_password(session, NULL, target_password) != SSH_AUTH_SUCCESS) {
        fprintf(stderr, "Failed to authenticate with password\n");
        ssh_disconnect(session);
        ssh_free(session);
        return -1;
    }

密钥验证

生成密钥

  • 基于ED25519算法,生成密钥对命令如下:
ssh-keygen -t ed25519 -C "<注释内容>"
  • 基于RSA算法,生成密钥对命令如下:
ssh-keygen -t rsa -C "<注释内容>"

默认回车即可

查看密钥

ED25519 算法

cat ~/.ssh/id_ed25519.pub

RSA 算法

cat ~/.ssh/id_rsa.pub

拷贝密钥

Windows(WSLGit Bash):

cat ~/.ssh/id_ed25519.pub | clip

Mac:

tr -d '\n' < ~/.ssh/id_ed25519.pub | pbcopy

GNU/Linux (requires xclip):

xclip -sel clip < ~/.ssh/id_ed25519.pub

复制到所需传入的服务器端的~/.ssh目录的authorized_keys文件里面

验证密钥是否正确

if (ssh_userauth_publickey_auto(session, NULL, NULL) != SSH_AUTH_SUCCESS) {
        fprintf(stderr, "Authentication failed: %s\n", ssh_get_error(session));
        ssh_disconnect(session);
        ssh_free(session);
        return -1;
    }

SFTP子系统构建

sftp_session sftp;

// 打开SFTP通道
sftp = sftp_new(session);
if (!sftp) {
    fprintf(stderr, "Failed to create SFTP session\n");
    ssh_disconnect(session);
    ssh_free(session);
    return -1;
}

if (sftp_init(sftp) != SSH_OK) {
    fprintf(stderr, "Failed to initialize SFTP session\n");
    sftp_free(sftp);
    ssh_disconnect(session);
    ssh_free(session);
    return -1;
}

传输普通文件

  • local_file_path:本地需传文件路径
  • remote_file_path:传送至远端服务器路径
int sftp_normal_upload(sftp_session sftp, const char* local_file_path, const char* remote_file_path)
{
    sftp_file file = sftp_open(sftp, remote_file_path, O_WRONLY | O_CREAT, S_IRUSR | S_IWUSR);
    if (!file) {
        fprintf(stderr, "Failed to open remote file: %s\n", remote_file_path);
        return -1;
    }

    FILE* local_file = fopen(local_file_path, "rb");
    if (!local_file) {
        fprintf(stderr, "Failed to open local file: %s\n", local_file_path);
        sftp_close(file);
        return -1;
    }

    // 上传文件内容
    char buffer[1024];
    size_t bytes_read;
    while ((bytes_read = fread(buffer, 1, sizeof(buffer), local_file)) > 0) {
        sftp_write(file, buffer, bytes_read);
    }

    fclose(local_file);
    sftp_close(file);
}

递归传输文件夹

sftp没有直接的传输文件夹的接口,我们需要递归目录来传输

假设有下面文件夹

           +-- file1
   +-- B --+
   |       +-- file2
   A        
   |       +-- file3
   +-- C --+
           +-- file4

打开目录 A -》进入子目录 B -》在 B 中创建文件 file1 -》在 B 中创建 file2 -》离开目录 B -》进入子目录 C -》在 C 语言中创建 file3 -》 在 C 语言中创建 file4 -》离开目录 C -》离开目录 A

本地遍历的时候,远端同时创建

  • local_path:本地路径
  • remote_path:远端路径
int sftp_recursive_upload(ssh_session session, sftp_session sftp,
				 const char* local_path, const char* remote_path) {
    // 打开本地目录
    DIR* local_dir = opendir(local_path);
    if (!local_dir) {
        fprintf(stderr, "Failed to open local directory: %s\n", local_path);
        return -1;
    }

    // 创建服务器目录
    sftp_mkdir(sftp, remote_path, S_IRWXU);

    // 遍历本地目录项
    struct dirent* entry;
    while ((entry = readdir(local_dir)) != NULL) {
        if (strcmp(entry->d_name, ".") == 0 || strcmp(entry->d_name, "..") == 0) {
            continue; // Skip "." and ".."
        }

        // 构造全路径
        char local_file_path[1024];
        snprintf(local_file_path, sizeof(local_file_path), "%s/%s", local_path, entry->d_name);
        char remote_file_path[1024];
        snprintf(remote_file_path, sizeof(remote_file_path), "%s/%s", remote_path, entry->d_name);

        // 如果本地条目是一个目录,递归上传它
        if (entry->d_type == DT_DIR) {
            sftp_recursive_upload(session, sftp, local_file_path, remote_file_path);
        }
        else { // 如果本地条目是一个普通文件,上传它
            sftp_normal_upload(sftp, local_file_path, remote_file_path);
        }
    }

    closedir(local_dir);
    return 0;
}

完整传输小demo

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <libssh/libssh.h>
#include <libssh/sftp.h>
#include <dirent.h>
#include <sys/stat.h>
#include <fcntl.h>

const char* target_host = "xxx.xx.xxx.xxx";
const char* target_username = "AMY";
const char* target_password = "xxxxx";

int sftp_normal_upload(sftp_session sftp, const char* local_file_path, const char* remote_file_path)
{
    sftp_file file = sftp_open(sftp, remote_file_path, O_WRONLY | O_CREAT, S_IRUSR | S_IWUSR);
    if (!file) {
        fprintf(stderr, "Failed to open remote file: %s\n", remote_file_path);
        return -1;
    }

    FILE* local_file = fopen(local_file_path, "rb");
    if (!local_file) {
        fprintf(stderr, "Failed to open local file: %s\n", local_file_path);
        sftp_close(file);
        return -1;
    }

    // 上传文件内容
    char buffer[1024];
    size_t bytes_read;
    while ((bytes_read = fread(buffer, 1, sizeof(buffer), local_file)) > 0) {
        sftp_write(file, buffer, bytes_read);
    }

    fclose(local_file);
    sftp_close(file);
}

int sftp_recursive_upload(ssh_session session, sftp_session sftp, const char* local_path, const char* remote_path) {
    // 打开本地目录
    DIR* local_dir = opendir(local_path);
    if (!local_dir) {
        fprintf(stderr, "Failed to open local directory: %s\n", local_path);
        return -1;
    }

    // 创建服务器目录
    sftp_mkdir(sftp, remote_path, S_IRWXU);

    // 遍历本地目录项
    struct dirent* entry;
    while ((entry = readdir(local_dir)) != NULL) {
        if (strcmp(entry->d_name, ".") == 0 || strcmp(entry->d_name, "..") == 0) {
            continue; // Skip "." and ".."
        }

        // 构造全路径
        char local_file_path[1024];
        snprintf(local_file_path, sizeof(local_file_path), "%s/%s", local_path, entry->d_name);
        char remote_file_path[1024];
        snprintf(remote_file_path, sizeof(remote_file_path), "%s/%s", remote_path, entry->d_name);

        // 如果本地条目是一个目录,递归上传它
        if (entry->d_type == DT_DIR) {
            sftp_recursive_upload(session, sftp, local_file_path, remote_file_path);
        }
        else { // 如果本地条目是一个普通文件,上传它
            sftp_normal_upload(sftp, local_file_path, remote_file_path);
        }
    }

    closedir(local_dir);
    return 0;
}

int main() {
    ssh_session session;
    sftp_session sftp;

    // 连接SSH会话
    session = ssh_new();
    if (!session) {
        fprintf(stderr, "Failed to create SSH session\n");
        return -1;
    }

    ssh_options_set(session, SSH_OPTIONS_HOST, target_host);
    ssh_options_set(session, SSH_OPTIONS_USER, target_username);

    if (ssh_connect(session) != SSH_OK) {
        fprintf(stderr, "Failed to connect to SSH session: %s\n", ssh_get_error(session));
        ssh_free(session);
        return -1;
    }

    // 身份验证
    if (ssh_userauth_password(session, NULL, target_password) != SSH_AUTH_SUCCESS) {
        fprintf(stderr, "Failed to authenticate with password\n");
        ssh_disconnect(session);
        ssh_free(session);
        return -1;
    }

    // 打开SFTP通道
    sftp = sftp_new(session);
    if (!sftp) {
        fprintf(stderr, "Failed to create SFTP session\n");
        ssh_disconnect(session);
        ssh_free(session);
        return -1;
    }

    if (sftp_init(sftp) != SSH_OK) {
        fprintf(stderr, "Failed to initialize SFTP session\n");
        sftp_free(sftp);
        ssh_disconnect(session);
        ssh_free(session);
        return -1;
    }


    // 得到当前 文件/目录 所在路径
    char local_dir[1024];
    getcwd(local_dir, sizeof(local_dir));
    printf("请输入所需传入的文件或目录的名字\n");
    int len = strlen(local_dir);
    local_dir[len] = '/';
    local_dir[len + 1] = '\0';

    char filename[100];
    scanf("%s", filename);
    strcat(local_dir, filename);

    struct stat file_stat;

    // 获取文件的详细信息
    if (stat(local_dir, &file_stat) != 0) {
        perror("stat");
        return -1;
    }

    printf("请输入所需传入远端路径\n");
    char target_path[1024];
    scanf("%s", target_path);

    // 判断文件类型

    //普通文件
    if (S_ISREG(file_stat.st_mode)) {
        sftp_normal_upload(sftp, local_dir, target_path);
    }
    //目录文件
    else if (S_ISDIR(file_stat.st_mode)) {
        // 递归上传本地目录到远程目录
        if (sftp_recursive_upload(session, sftp, local_dir, target_path) != 0) {
            fprintf(stderr, "Failed to recursively upload directory\n");
            sftp_free(sftp);
            ssh_disconnect(session);
            ssh_free(session);
            return -1;
        }
    }
    else {
        printf("%s 既不是普通文件,也不是目录,无法上传\n", local_dir);
    }

    // 释放
    sftp_free(sftp);
    ssh_disconnect(session);
    ssh_free(session);

    return 0;
}

libssh sftp,Linux开发小demo,服务器,ssh,linux,libssh,ubuntu文章来源地址https://www.toymoban.com/news/detail-850211.html

到了这里,关于SSH连接SFTP传输:如何使用libssh库在Linux环境下进行(文件、文件夹)传输到远端服务器的文章就介绍完了。如果您还想了解更多内容,请在右上角搜索TOY模板网以前的文章或继续浏览下面的相关文章,希望大家以后多多支持TOY模板网!

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处: 如若内容造成侵权/违法违规/事实不符,请点击违法举报进行投诉反馈,一经查实,立即删除!

领支付宝红包 赞助服务器费用

相关文章

  • LibSSH2简单入门-exec、sftp

    LibSSH2简单入门-exec、sftp 1、libssh2官方地址:libssh2 libssh2的官方文档和官方示例代码非常的棒,基本可以直接参考 官方文档:libssh2 docs 官方示例:libssh2 examples 2、推荐阅读两个示例,基本可以完成对libssh2的理解和使用了 2.1、ssh2_exec.c 通过libssh2在远端机器上执行指令,并获取

    2024年02月05日
    浏览(48)
  • 内网穿透的应用-如何在Termux 中使用SFTP 文件传输并结合内网穿透实现远程传输

    SFTP(SSH File Transfer Protocol)是一种基于SSH(Secure Shell)安全协议的文件传输协议。与FTP协议相比,SFTP使用了加密和身份验证机制来保护数据的安全性和完整性,可以在不安全的网络中传输文件,因此更加安全可靠,。 下面介绍如何在termux 中使用SFTP 文件传输并结合[cpolar内网映

    2024年02月08日
    浏览(48)
  • 【全面解析】Windows 如何使用 SSH 密钥远程连接 Linux 服务器

    创建密钥 创建 linux 服务器端的终端中执行命令 ssh-keygen ,之后一直按Enter即可,这样会在将在 ~/.ssh/ 路径下生成公钥(id_rsa.pub)和私钥(id_rsa) 注意:也可以在 windows 端生成密钥,只需要保证公钥在服务器端,私钥在本地端即可。 安装 在服务器端 ~/.ssh/ 路径下执行以下命令,在

    2024年02月16日
    浏览(57)
  • [linux] SFTP文件传输基本命令

    SFTP文件传输基本命令 - 木洒 - 博客园 (cnblogs.com) 1.sftp建立连接 [root@localhost ~]# sftp username@remote_ip(or remote host name),      # 连接root用户, 则可省略\\\"root@\\\".  [root@localhost ~]# sftp -o port=1000 username@remote_ip [root@localhost ~]# sftp root@68.56.32.159 2.sftp - 上传文件:如果上传/下载的是文件夹, 在

    2024年01月25日
    浏览(33)
  • 如何在Linux机器上使用ssh远程连接Windows Server服务器并使用rsync同步文件

       当前在研究goploy自动化开源部署工具,该工具部署在linux机器上,而要部署服务的目标服务器有一部分是windows server服务器,goploy自动化部署,使用rsync部署方式,底层依赖于ssh远程连接目标服务器,所以,要实现自动化部署,必须先实现ssh远程连接目标windows server服务器

    2024年02月05日
    浏览(67)
  • Pycharm 远程连接docker进行远程调试,ssh测试可连接,但是sftp连接不上的问题

    docker端口配置映射都正确,自己的xshell可以成功连接,使用Pycharm就是sftp连接不上,一直在等待。ssh解释器里显示是连接成功的,但是整个配置到sftp里却是连接失败。删除本机的known_hosts文件、删除重启pycharm、重启电脑、关机重开都不行,以为是sftp的问题,但是发现xftp软件

    2024年02月04日
    浏览(58)
  • vscode远程连接服务器(remote ssh)+上传本地文件到服务器(sftp)

    一、vscode远程连接服务器 1.点击vscode右边工具栏点击拓展,搜索remote ssh并安装 2.安装完成后,左边工具栏会出现一个电脑图标的远程资源管理器,点击后选择SSH TARGETS的设置 3.然后选择第一个..sshconfig 4.向服务器管理员索要服务器的连接信息并修改ssh config文件   5.设置完成

    2024年02月01日
    浏览(49)
  • 如何利用SFTP如何实现更安全的远程文件传输 ——【内网穿透】

    🎬 鸽芷咕 :个人主页  🔥 个人专栏 : 《高效编程技巧》《cpolar》 ⛺️生活的理想,就是为了理想的生活! SFTP(SSH File Transfer Protocol)是一种基于SSH(Secure Shell)安全协议的文件传输协议。与FTP协议相比,SFTP使用了加密和身份验证机制来保护数据的安全性和完整性,可以在

    2024年02月11日
    浏览(37)
  • Linux——如何使用sftp命令轻松上传和下载文件

    对于Linux用户来说,通过sftp命令进行文件上传和下载是一个非常常见的操作。SFTP是SSH File Transfer Protocol的简写,它是基于安全shell(SSH)协议的一种文件传输协议,可以实现加密传输,防止网络窃听和篡改。本文将向您介绍如何使用sftp命令轻松上传和下载文件。 一、安装和配

    2024年03月09日
    浏览(53)
  • 如何在 Linux 服务器上安装和使用 SFTP?

    SFTP 或 SSH 文件传输协议是一种在两台计算机之间安全传输数据的方法。它是运行在 SSH 协议之上并利用其安全性并完全支持其身份验证的 FTP。 现在,建议使用 SFTP 而不是旧的旧 FTP 或 FTP/S 协议。SFTP 默认是安全的,因为这就是 SSH 的工作方式。从安全的角度来看,SFTP 还可以

    2024年02月11日
    浏览(46)

觉得文章有用就打赏一下文章作者

支付宝扫一扫打赏

博客赞助

微信扫一扫打赏

请作者喝杯咖啡吧~博客赞助

支付宝扫一扫领取红包,优惠每天领

二维码1

领取红包

二维码2

领红包