首页 » PHP教程 » phplibssh2技巧_基于libssh2的ssh远程实行sftp传输C库pssh

phplibssh2技巧_基于libssh2的ssh远程实行sftp传输C库pssh

duote123 2024-11-10 0

扫一扫用手机浏览

文章目录 [+]

平时掩护一大堆linux做事器,如何无需交互带密码远程实行命令?实在之前也调研过几种方案,比如直接调用plink获取其结果--后来创造这玩意非线程安全,无法多线程利用且bug很多。
又比如QT自带的QSSH代码,我搞下来试了一下,一是也是非线程安全,二是这货是非壅塞式调用,门槛比较高,难熬痛苦的很,以是放弃了,终极选定了libssh2。

不用脚本纯代码的话,libssh2无疑是一个好的选择。
但这个库对新手不是很友好,网络上的例子也都是把官方给的几个例子抄来抄去毫无新意,不但繁琐而且有很多缺陷,总结几个如下:

phplibssh2技巧_基于libssh2的ssh远程实行sftp传输C库pssh

纯C库,用起来不是那么方便非线程安全,无法线程实行连接/实行没有断线重连功能sftp传输没有上传/下载文件夹的功能sftp传输没有短点续传的功能windows与linux之间sftp传输不支持路径以及文件名含有中文以及空格问题远程实行返回You have mail/You have new mail的问题ssh命令过长偶尔导致\b \b \b..乱码的问题

phplibssh2技巧_基于libssh2的ssh远程实行sftp传输C库pssh
(图片来自网络侵删)

等一系列问题,实在无法知足我想大略粗暴壅塞式实行命令以及传输文件、目录的需求,于是自己花了几个月封装了一个跨平台pssh库,致力于办理这些问题,紧张功能以及更新记录如下:

增加了带空格的目录以及文件名支持增加了中文支持对断点续传上传和下载文件增加速率提示功能增加了下载文件/上传文件/下载目录/上传目录的断点续传功能已改造windows上传文件,下载文件,上传目录,下载目录,支持回调函数,目录支持进度传输干系要从windows下psshsingle考,从linux考来的不对,由于有中文问题已改造为单线程断线重连,不要卡住,目前实现思路是,send失落败后,只重连一次,失落败再返回,由于xsh一样平常都不是只实行一次,多次实行,上一次失落败的话,重连一次,这次失落败,下一次就会成功本版本是多个channel版本,往后多线程用这个作为模板,原来的套一个pssh太臃肿,每次要写两遍函数修正了recv处理,兼容centos系和ubuntu系列,ubuntu系列没有[,可连接127.0.0.1单线程重连版,紧张是为了防止线程过多,线程重连如果pssh多的话2倍线程,而且稳定一些xsh是send失落败直接壅塞重连,recv由于有参数返回,以是还是返回值,在xsh里面壅塞重连xshlastinng是成功考试测验多个channel,在循环lastting的时候用statuschannel判断壅塞重连已经改造了close,xsh和xshlasting都可以closetrue已经改造了xshlasting,可以做到closetrue后再open依然可以已经改造了xsh,可以做到closetrue后再open依然可以办理了深度openssl线程安全问题增加了获取是否天生core文件功能,增加在/etc/profile增加配置等功能增加切换目录,获取当前目录,查看远程进程,获取根目录利用比例是否在等常用功能增加获取远程core文件"Core文件"<<"做事器地址"<<"所属进程"<<"天生韶光"的list信息增加了远程ini模式配置文件的增编削查功能增加了给/etc/profile添加配置功能,内置判断是否已有配置增加了close(true)功能,true情形下关闭自动重连,彻底关闭(两种模式);修复了在高延迟情形下判断远程文件是否存在韶光过长的bug(不再用sftp模式获取,利用ssh模式直接ll获取)增加xshlasting模式自动重连功能,利用另一个xsh一贯发送pwd探测,如果断开,则线程自动重连,重连成功后连续返回精确结果增加了自动重连的功能,如果连接断开,则当时xsh返回缺点,线程自动重连,如果下次已经连接上则下次获取精确结果增加了与做事器连接断开时返回缺点的功能,不会一贯卡住壅塞调用,xsh等结果获取完成才返回增加了上传文件/下载文件/上传目录/下载目录功能修复了xsh有时会返回You have mail/You have new mail的问题,过滤修复了xsh有时命令过长会涌现结果返回\b\b\b..乱码的问题,过滤修正了xsh功能,任务缺点都字符串返回#fail,包括连接断开修正了connect,增加了连接超时功能,默认超时时间1秒,原来是20秒太长增加了同一个ssh close再open功能测试了多线程功能C++11线程,线程安全增加了探测连接的功能.另起一个chanel一贯探测,用于判断连接状态,该功能是xshlasting的根本,由于xshlasting不能判断断了,用这个bconnected判断增加了支持域名功能(为了支持端口映射)增加两种模式,一种正常获取xsh结果,一种持续获取xshlasting,xshlasting可用于tail -f网络日志到统一做事器增加了xsh获取结果超时10秒返回缺点功能对付xsh获取结果失落败(缘故原由不限于连接断开,超时等),均返回#fail开头的字符串

紧张代码如下:

/ 作者:李海龙2021-02-26/class pssh {public: pstring strhost; int iport; pstring strpwd; pstring struser; pstring strerr;//末了一次缺点描述 pssh(); pssh(pstring host,int port=22,pstring pwd="scfwq_325",pstring user="root"); void init(pstring host,int port=22,pstring pwd="scfwq_325",pstring user="root"); virtual ~pssh(); int open();//open一次就行,返回结果,不用自动重连,由于后边实行xsh会自动重连 int close(bool breal=false);//close(true)停滞重连 / xsh是send和recv的合集,获取top结果用top -b n 1 获取过程中如果断了,无论是send还是recv会自动重连一次,然后返回失落败,如果重连成功,则下次会精确,这样能担保返回失落败提示 如果是主动closetrue则会返回#fail / pstring xsh(pstring cmd,pstring type="data"); //send失落败一次,自带一次重连,反正失落败了也不在乎那几秒了,如果重连成功,重新发送一次命令,如果失落败,返回,这样既重连了,也能返回当作果 int send(pstring cmd,pstring type="data"); //吸收有多种状态,返回值,在xsh中统一处理自动重连,带失落败自动重连一次,与send一样,有10秒超时 int recv(pstring &data,pstring type="data"); / 利用办法 ptrans->uploadThread(pathFull,this->strpwdremote, std::bind(&MainWindow::showstr,this,placeholders::_1)); //停滞时用close(true) / //持续结果输出,例如tail -f,过程输出,也可以实行别的命令 //停滞时用close(true) int xshlasting(pstring cmd, std::function<void(pstring)> fun=funShow); / 用两个channel实现的,利用办法 ptrans->uploadThread(pathFull,this->strpwdremote, std::bind(&MainWindow::showstr,this,placeholders::_1)); / int xshlastingThread(pstring cmd, std::function<void(pstring)> fun=funShow); //判断远程文件是否有key,比如判断core是否启用bHasKeyInRemoteFile("/etc/profile","ulimit"); bool bHasKeyInRemoteFileBridge(pstring host,pstring path = "/etc/profile", pstring key = "ulimit"); bool ping(pstring host); presult getTimeLastReboot(); //"Core文件"<<"做事器地址"<<"所属进程"<<"天生韶光"的list pvector<pliststring> getCoreInfo(pstring strpath="/"); //判断远程文件是否有key,比如判断core是否启 bHasKeyInRemoteFile("/etc/profile","ulimit"); bool bHasKeyInRemoteFile(pstring path = "/etc/profile", pstring key = "ulimit"); //获取根目录占用比例 presult getUsageRoot(); bool cd(pstring path); presult getContentFromRemoteFile(pstring path); pstring getIPRemote(); pstring pwd(); //从源码目录传过去,改权限,获取结果,已包括断开连接的判断,四个 pstring getconf(pstring path, pstring section, pstring key, bool bupload = false); bool delconf(pstring path, pstring section, pstring key, bool bupload = false); bool addconf(pstring path, pstring section, pstring key, pstring val, bool bupload = false); bool setconf(pstring path, pstring section, pstring key, pstring val, bool bupload = false); ppair<int,ptime> getTimeNow(); //重命名 int mv(pstring strold,pstring strnew); //获取文件大小 longlong getFileSize(pstring strPathFull); //获取类型 dir file lnk noaccess,失落败返回空用sftp用以提高速率 pstring getPathTypeRemote(pstring strPath); //删除文件或目录,支持带空格的 int rm(pstring strPathFullRemote); //sftp创建文件 支持带空格 int touch(pstring strPathFullRemote); //远程递归创建目录sftp速率快//缺点返回小于0,已存在也返回缺点 -31表示已存在,但是 //根据一样平常业务情形,改进为,如果有同名目录,返回创建成功,如要判断之前是否已存在,单独用isExsistdir int mkdirp(pstring strPathFullRemote); //远程创建目录sftp速率快//缺点返回小于0,已存在也返回缺点 -31表示已存在,但是 //根据一样平常业务情形,改进为,如果有同名目录,返回创建成功,如要判断之前是否已存在,单独用isExsistdir int mkdir(pstring strPathFullRemote); //判断有没有上述目录 bool isExsistDirRemote(pstring strPathDirRemote); //判断有没有上述文件 bool isExsistFileRemote(pstring strPathFullFile); //获取名字和类型 pmap<pstring, pstring> getAllInDirRemote(pstring strPathDirRemote); //获取名字,类型和大小,末了修正韶光,sftp办法 plist<pliststring> getAllWithSizeInDirRemote(pstring strPathDirRemote); //这获取的是全路径 void getAllFilesAndPathsRecursionRemote(pstring path, pliststring &lfile, pliststring &ldir); //lnk也要下载,下载后便是原来指向的文件,scp也是这样的,以是会与原来大小不一,但是要与scp一样就行,目前与scp不一样大小查缘故原由 int downloadDir(pstring strPathFullLocal,pstring strPathFullRemote, std::function<void(pliststring)> fun=showProcessDir); //上传libssh2目录慢很多,两分钟,但下载很快,查缘故原由 int uploadDir(pstring strPathFullLocal,pstring strPathFullRemote, std::function<void(pliststring)> fun=showProcessDir); //两个都是全路径--经测试windows版的上传超过10秒后有时就不支持内置断点续传,老诚笃实写seek吧!,断点续传的逻辑已经写好了,llpos=0是从头传 int uploadFileOnce(pstring strPathFullLocal,pstring strPathFullRemote, std::function<void(pliststring)> fun=showProcessFile, longlong llpos=0); //uploadfile断点续传逻辑已经写好了,但是在centos6.8下sftpappend会失落效,可能就像提示一样:APPEND doesn't have any effect on OpenSSH servers //测试在centos7下没问题,但是centos6就弗成,以是考虑uploadfile时,断了的话,直接从头开始,由于本来断点续传也是偶发事宜,改为断线重传,下载还是断点续传 //自动断点续传直到精确传完为止--在centos6.8下有时候断点续传有问题---查缘故原由 int uploadFile(pstring strPathFullLocal,pstring strPathFullRemote, std::function<void(pliststring)> fun=showProcessFile); //两个都是全路径--经测试只有windows版的download过了10秒后不支持断点续传,10秒以内可以,以是要改造,断点续传的逻辑已经写好了,llpos=0是从头传 int downloadFileOnce(pstring strPathFullLocal, pstring strPathFullRemote, std::function<void(pliststring)> fun=showProcessFile, longlong llpos=0); //自动断点续传直到精确传完为止 int downloadFile(pstring strPathFullLocal, pstring strPathFullRemote, std::function<void(pliststring)> fun=showProcessFile); int showDir(pstring strPathDirRemote); //获取类型 dir file lnk noaccess,失落败返回空用xsh速率太慢,200ms pstring getTypePathRemoteUseXsh(pstring strPath); //远程递归创建目录,速率慢,要改成sftp创建目录 int mkdirpUseXsh(pstring strPathFullRemote); bool getStatusConnect(); friend ostream &operator<<(ostream &os, pssh x) { os << x.strhost << ":" << x.iport << "@" << x.struser << " connect status: " << x.bConnected; return os; } //下边这两个是为了持续获取搞的 void recvLasting(std::function<void(pstring)> fun); LIBSSH2_CHANNEL pchannelData; LIBSSH2_CHANNEL pchannelStatus; //新加的 bool bConnected;private: LIBSSH2_SFTP sftp_session; pstring strCmdNow; bool bstop; //原来的// int m_socket; ptcp tcp; LIBSSH2_SESSION psession; bool connect(const char szIp, int nPort = 22); bool login(const char szUserName, const char szPassword); // 返回值表示渠道的序号。
如果返回-1,创建失落败; LIBSSH2_CHANNEL createChannel(const char szChannelTerm = "vanilla"); bool write(LIBSSH2_CHANNEL channel, const char szData); int waitsocket(int socket_fd, LIBSSH2_SESSION session);};

实在我也知道大家对我拙劣的封装并不感兴趣,只关心好不好用,怎么用的问题,下边给大家展示一下:

普通远程实行:

//初始化 地址 端口 密码 用户名 pssh ssh("192.168.133.129",22,"123.asdf","root"); //连接linux做事器 hlog(ssh.open()); //同时做个多线程一贯实行pwd命令 std::thread([]{ pssh ssh2("192.168.133.129",22,"123.asdf","root"); hlog(ssh2.open()); while(1) { hlog(ssh2.xsh("pwd")); plib::sleep(1000); } }).detach(); //获取结果 pstring stres=ssh.xsh("ifconfig|grep inet");\ //日志打印 hlog(stres); stres=ssh.xsh("pwd"); hlog(stres); while(1) { plib::sleep(1000); }

结果如下:

持续远程实行获取(获取tail -f 这种)

//同时做个多线程一贯往远程做事器/root/test.log下一秒写一次数据,即仿照日渐增长的日志文件 std::thread([]{ pssh ssh2("192.168.133.129",22,"123.asdf","root"); hlog(ssh2.open()); //先把原来的删掉 hlog(ssh2.xsh("rm -f /root/test.log")); int count=0; while(1) { pstring strcmd="echo '"+plib::toString(count+1)+": qq1415532825'>>/root/test.log"; (ssh2.xsh(strcmd)); plib::sleep(1000); count++; } }).detach(); plib::sleep(1000); //初始化 地址 端口 密码 用户名 pssh ssh("192.168.133.129",22,"123.asdf","root"); //连接linux做事器 hlog(ssh.open()); //新线程内持续获取日志,将结果通过回调函数的形式回放到须要的函数内 ssh.xshlastingThread("tail -f /root/test.log",funShowInfo); //5秒后关闭持续获取 plib::sleep(5000); //close true代表停滞自动重连,彻底停滞,close false代表做事器非常断开后会断线重连连续获取 hlog(ssh.close(true)); while(1) { plib::sleep(1000); }

关于此种模式,不用说大家也知道可以用来干什么,日志同步啊,日志网络,日志监控啊!
乃至都不用支配客户端,切实其实不要太爽!

sftp文件上传、下载

pssh ssh("192.168.133.129",22,"123.asdf","root"); hlog(ssh.open()); //测试上传下载,顺便把中文也测试了 hlog(ssh.uploadFile("d:/setups/协和2.17.0.apk","/home/xlfd/")); hlog(ssh.downloadFile("d:/test/协和下载.apk","/home/xlfd/协和2.17.0.apk"));

结果如下:

sftp目录递归上传、下载

测试目录:

pssh ssh("192.168.133.129",22,"123.asdf","root"); hlog(ssh.open()); //测试上传下载,顺便把中文也测试了// hlog(ssh.uploadFile("d:/setups/协和2.17.0.apk","/home/xlfd/"));// hlog(ssh.downloadFile("d:/test/协和下载.apk","/home/xlfd/协和2.17.0.apk")); hlog(ssh.uploadDir("d:/setups/Debuggers","/root")); hlog(ssh.downloadDir("D:/","/root/Debuggers/"));

结果如下:

当然以上功能都有断点续传功能,传输功能都带回调函数,方便与QT界面外部调用等集成,往后我会基于该库专门写一个sftp传输工具。

标签:

相关文章