sftp couldn‘t stat remote file

本文讲述了如何将本地文件夹中的文件上传到服务器指定位置,包括在服务器创建同名文件夹、设置文件权限等步骤,遇到couldntstatremotefile错误后,通过chmod777解决权限问题。

从本地上传到服务器某个文件夹

本地地址:/1/2/3/4

服务器地址:/5/6

做法:1.在服务器建一个同名文件夹4,即/5/6/4

2. lcd /1/2/3

3. put -r 4 /5/6 无斜杠

4.显示couldn't stat remote file

5. 去服务器,给新建的/5/6/4解权限

chmod 777

#include "FtSshTool.h" #include <libssh2.h> #include "FtSshChannel.h" #include <libssh2.h> #include <libssh2_sftp.h> #ifdef WIN32 #include <windows.h> #include <winsock2.h> #else #include <sys/socket.h> #include <netinet/in.h> #include <unistd.h> #include <arpa/inet.h> #endif #include <sys/stat.h> #include <iostream> #include <string> #include <sys/types.h> #include <fcntl.h> #include <errno.h> #include <stdio.h> #include <ctype.h> #include <filesystem> #include <libssh2.h> #include <libssh2_sftp.h> #define _CRT_SECURE_NO_WARNINGS FtSshTool::FtSshTool(std::string srvIp, int srvPort) :m_srvIp(srvIp), m_srvPort(srvPort) { m_sock = -1; m_session = NULL; SetConsoleOutputCP(65001); //65001 是设置UTF编码 } FtSshTool::~FtSshTool(void) { Disconnect(); libssh2_exit(); } //void FtSshTool::S_KbdCallback(const char* name, int name_len, // const char* instruction, int instruction_len, // int num_prompts, // const LIBSSH2_USERAUTH_KBDINT_PROMPT* prompts, // LIBSSH2_USERAUTH_KBDINT_RESPONSE* responses, // void** abstract) //{ // (void)name; // (void)name_len; // (void)instruction; // (void)instruction_len; // if (num_prompts == 1) // { // // responses[0].text = strdup(s_password.c_str()); // // responses[0].length = (int)s_password.size(); // } // (void)prompts; // (void)abstract; //} bool FtSshTool::Connect(std::string userName, std::string userPwd) { //WSAData wsdData; //int wsaRes = WSAStartup(MAKEWORD(2, 2), &wsdData); //if (wsaRes != 0) //{ // printf("0000"); //} m_sock = socket(AF_INET, SOCK_STREAM, 0); sockaddr_in sin; sin.sin_family = AF_INET; sin.sin_port = htons(22); sin.sin_addr.s_addr = inet_addr(m_srvIp.c_str()); if (connect(m_sock, (sockaddr*)(&sin), sizeof(sockaddr_in)) != 0) { Disconnect(); return false; } // 初始化libssh2库 //flag 默认初始化选项 int rc = libssh2_init(0); m_session = libssh2_session_init(); if (libssh2_session_handshake(m_session, m_sock))//会话握手 { Disconnect(); return false; } // libssh2_session_set_blocking(m_session, 0); // 0非阻塞模式 1// 阻塞模式 int auth_pw = 0; std::string fingerprint = libssh2_hostkey_hash(m_session, LIBSSH2_HOSTKEY_HASH_SHA1); /* check what authentication methods are available */ std::string userauthlist = libssh2_userauth_list(m_session, userName.c_str(), (int)userName.size()); if (strstr(userauthlist.c_str(), "password") != NULL) { auth_pw |= 1; } if (strstr(userauthlist.c_str(), "keyboard-interactive") != NULL) { auth_pw |= 2; } if (strstr(userauthlist.c_str(), "publickey") != NULL) { auth_pw |= 4; } if (auth_pw & 1) { /* We could authenticate via password */ // 使用用户名和密码进行身份验证 if (libssh2_userauth_password(m_session, userName.c_str(), userPwd.c_str())) { Disconnect(); return false; } } else if (auth_pw & 2) { /* Or via keyboard-interactive */ // s_password = userPwd; /* if (libssh2_userauth_keyboard_interactive(m_session, userName.c_str(), &S_KbdCallback)) { Disconnect(); return false; }*/ } else { Disconnect(); return false; } return true; } int FtSshTool::Connect(std::string srvIp, std::string userName, std::string userPwd) { //WSAData wsdData; //int wsaRes = WSAStartup(MAKEWORD(2, 2), &wsdData); //if (wsaRes != 0) //{ // printf("0000"); //} m_sock = socket(AF_INET, SOCK_STREAM, 0); if (m_sock < 0) { std::cerr << "Cannot create socket" << std::endl; return -5; } sockaddr_in sin; sin.sin_family = AF_INET; sin.sin_port = htons(22); sin.sin_addr.s_addr = inet_addr(srvIp.c_str()); if (connect(m_sock, (sockaddr*)(&sin), sizeof(sockaddr_in)) != 0) { std::cout << "connect Failed " << std::endl; Disconnect(); return -3; } // 初始化libssh2库 //flag 默认初始化选项 int rc = libssh2_init(0); if (rc != 0) { Disconnect(); return -1; // 初始化失败 } // 创建SSH会话 m_session = libssh2_session_init(); if (!m_session) { Disconnect(); return -2; // 创建会话失败 } // 设置会话选项 libssh2_session_set_blocking(m_session, 1);// 0非阻塞模式 1// 阻塞模式 libssh2_session_set_timeout(m_session,30*1000); // 连接到远程主机 rc = libssh2_session_startup(m_session, m_sock); if (rc != 0) { // 连接失败 Disconnect(); return -3; } // 使用用户名和密码进行身份验证(用户名和密码) rc = libssh2_userauth_password(m_session, userName.c_str(), userPwd.c_str()); if (rc != 0) { // 身份验证失败 libssh2_session_disconnect(m_session, "Authentication failed"); libssh2_session_free(m_session); Disconnect(); return -4; } return 0; } int FtSshTool::Connect(std::string localIp, std::string srvIp, std::string userName, std::string userPwd) { // 很重要,否则m_sock 创建失败 //WSAData wsdData; //int wsaRes = WSAStartup(MAKEWORD(2, 2), &wsdData); //if (wsaRes != 0) //{ // printf("0000"); //} m_sock = socket(AF_INET, SOCK_STREAM, 0); sockaddr_in sin; sin.sin_family = AF_INET; sin.sin_port = htons(22); sin.sin_addr.s_addr = inet_addr(srvIp.c_str()); // 绑定客户端socket到特定的本地IP地址 struct sockaddr_in local_addr; memset(&local_addr, 0, sizeof(local_addr)); local_addr.sin_family = AF_INET; local_addr.sin_port = htons(0); // 随机选择一个可用的本地端口 local_addr.sin_addr.s_addr = inet_addr(localIp.c_str()); // 客户端的本地IP地址 if (bind(m_sock, (struct sockaddr*)&local_addr, sizeof(local_addr)) == SOCKET_ERROR) { // std::cerr << "Bind failed" << std::endl; perror("Bind "); //return 1; } else { std::cout << "Bind Success" << localIp<< std::endl; } if (connect(m_sock, (sockaddr*)(&sin), sizeof(sockaddr_in)) != 0) { perror("connect "); Disconnect(); return -3; } // 初始化libssh2库 //flag 默认初始化选项 int rc = libssh2_init(0); if (rc != 0) { Disconnect(); return -1; // 初始化失败 } // 创建SSH会话 m_session = libssh2_session_init(); if (!m_session) { Disconnect(); return -2; // 创建会话失败 } // 设置会话选项 libssh2_session_set_blocking(m_session, 1);// 0非阻塞模式 1// 阻塞模式 libssh2_session_set_timeout(m_session, 30 * 1000); // 连接到远程主机 rc = libssh2_session_startup(m_session, m_sock); if (rc != 0) { // 连接失败 Disconnect(); return -3; } // 使用用户名和密码进行身份验证(用户名和密码) rc = libssh2_userauth_password(m_session, userName.c_str(), userPwd.c_str()); if (rc != 0) { // 身份验证失败 libssh2_session_disconnect(m_session, "Authentication failed"); //libssh2_session_free(m_session); Disconnect(); return -4; } return 0; } bool FtSshTool::Disconnect(void) { //WSACleanup(); if (m_session) { libssh2_session_disconnect(m_session, "Bye bye, Thank you"); libssh2_session_free(m_session); m_session = NULL; } if (m_sock != -1) { #ifdef WIN32 closesocket(m_sock); #else close(m_sock); #endif m_sock = -1; } return true; } std::shared_ptr<Channel> FtSshTool::CreateChannel(const std::string& ptyType) { if (NULL == m_session) { return NULL; } LIBSSH2_CHANNEL* channel = NULL; /* Request a shell */ if (!(channel = libssh2_channel_open_session(m_session))) { return NULL; } /* Request a terminal with 'vanilla' terminal emulation * See /etc/termcap for more options */ if (libssh2_channel_request_pty(channel, ptyType.c_str())) { libssh2_channel_free(channel); return NULL; } /* Open a SHELL on that pty */ if (libssh2_channel_shell(channel)) { libssh2_channel_free(channel); return NULL; } std::shared_ptr < Channel> pChannel = std::make_shared<Channel>(channel); // Channel* ret = new Channel(channel); std::cout << pChannel->Read() << std::endl; return pChannel; } bool FtSshTool::Scp(std::string localfile, std::string remotefile) { FILE* local = NULL; int size = 0; try { struct stat file_info; size = std::filesystem::file_size(localfile); // Send the file struct stat file_status; // 获取文件状态 if (stat(localfile.c_str(), &file_status) == -1) { std::cerr << "Error: Unable to get file status for " << localfile << std::endl; return 1; } LIBSSH2_CHANNEL* channel = libssh2_scp_send64(m_session, remotefile.c_str(), 0644, size, file_status.st_mtime, file_status.st_atime); if (!channel) { char* errmsg; int errlen; int err = libssh2_session_last_error(m_session, &errmsg, &errlen, 0); fprintf(stderr, "Unable to open a session: (%d) %s\n", err, errmsg); } char mem[1024]; size_t nread; char* ptr; fprintf(stderr, "SCP session waiting to send file\n"); local = fopen(localfile.c_str(), "rb"); if (!local) { fprintf(stderr, "Cannot open local file %s\n", localfile.c_str()); return 1; } do { nread = fread(mem, 1, sizeof(mem), local); if (nread <= 0) { fclose(local); break; } ptr = mem; do { ssize_t nwritten; /* write the same data over and over, until error or completion */ nwritten = libssh2_channel_write(channel, ptr, nread); if (nwritten < 0) { fprintf(stderr, "ERROR %ld\n", (long)nwritten); break; } else { /* nwritten indicates how many bytes were written this time */ ptr += nwritten; nread -= (size_t)nwritten; } } while (nread); } while (1); if (local) fclose(local); libssh2_channel_send_eof(channel); fprintf(stderr, "Waiting for EOF\n"); libssh2_channel_wait_eof(channel); fprintf(stderr, "Waiting for channel to close\n"); libssh2_channel_wait_closed(channel); libssh2_channel_free(channel); channel = NULL; return true; } catch (...) { if (local) fclose(local); return false; } } bool FtSshTool::ScpAll(std::string localpath, std::string remotePath) { // 检查路径是否存在 if (!std::filesystem::exists(localpath)) { std::cerr << "Directory does not exist: " << localpath << std::endl; return false; } // 遍历文件夹中的所有项 for (const auto& entry : std::filesystem::directory_iterator(localpath)) { if (std::filesystem::is_directory(entry)) { } else { Scp(entry.path().string(), remotePath + "/"+ entry.path().filename().string()); } } return false; } bool FtSshTool::ScpDirectory(std::string localdirectory, std::string remotedirectory) { // 检查路径是否存在 if (!std::filesystem::exists(localdirectory)) { std::cerr << "Directory does not exist: " << localdirectory << std::endl; return false; } std::shared_ptr<Channel>pchannel = this->CreateChannel(); std::string cmd_cd = "mkdir -p " + remotedirectory; pchannel->Write(cmd_cd); // 遍历文件夹中的所有项 for (const auto& entry : std::filesystem::directory_iterator(localdirectory)) { if (std::filesystem::is_directory(entry)) { std::string cmd_cd = "mkdir -p " + remotedirectory + "/" + entry.path().filename().string(); pchannel->Write(cmd_cd); Scp(entry.path().string(), remotedirectory + "/" + entry.path().filename().string()); std::cout << cmd_cd << std::endl; } else { Scp(entry.path().string(), remotedirectory + "/" + entry.path().filename().string()); std::string cmd_cd = "cd "+ remotedirectory +"; chmod 777 -R ./*;"; pchannel->Write(cmd_cd); std::cout << cmd_cd << std::endl; } } return true; } bool FtSshTool::KillProcessByName(std::string processName) { // 构建完整的WinSCP命令 //std::string commandLine = mWinscpPath + " /command " // "open ssh://" + mUsername + ":" + mPassword + "@" + mHost + // "call ps -ef|grep " + processName + " |grep -v grep |awk '{print $2}'|xargs kill -2" // " /log=log.txt exit"; // 将执行结果保存到日志文件 //// 执行命令 //system(commandLine.c_str()); return true; } 是用scp方法的时候,libssh2_channel_write返回-39的错误原因
07-01
### 解决远程创建文件时权限不足的问题 当遇到 `remote create file operation not permitted` 错误时,这通常意味着当前用户或进程缺乏足够的权限来执行所需的操作。解决方案涉及多个方面: #### 权限配置调整 为了使远程操作成功,确保目标服务器上的目录具有适当权限设置。可以通过修改文件系统的访问控制列表 (ACLs) 或者更改特定路径下的读写权限实现这一点。 对于 Linux/Unix 系统而言,可以利用命令行工具如 `chmod` 和 `chown` 进行相应处理[^1]: ```bash sudo chown -R user:user /path/to/directory sudo chmod -R 755 /path/to/directory ``` 上述两条指令分别用于改变指定文件夹及其子项的所有权以及赋予其可读、可写和可执行属性给所有者;同时允许组内成员和其他人只读取内容而不做任何改动。 #### 使用安全协议传输数据 考虑到安全性,在通过网络连接另一台计算机并尝试在其上建立新文档之前,建议采用加密通信方式比如 SSH(Secure Shell),它不仅能够提供身份验证机制而且还能保护会话期间交换的信息免受窃听威胁。 借助于 OpenSSH 客户端程序包中的 sftp(secure file transfer protocol) 功能来进行这项工作是一个不错的选择: ```bash sftp username@hostname:/target/path/ put localfile.txt remotefile.txt exit ``` 这段脚本展示了如何登录到远端主机并将本地文件上传至那里保存下来的过程[^2]。 #### 脚本恢复权限方案设计 虽然具体实施细节被留作练习留给读者自行完成,但这里给出一些思路指导:编写一个 shell/python 脚本来遍历需要修复权限的目标位置,并针对不同类型的资源应用恰当的安全策略。例如,对于普通文件可能只需要简单地设定 rwx-r--r-- 的模式位即可满足大多数应用场景的需求;而对于某些特殊用途的服务端口,则要更加谨慎地考虑最小化授权原则以防止潜在风险的发生。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值