VC++ 使用ssh协议连接Linux服务器执行指令并返回
提供一个libssh2.dll的工程和调用libssh2.dll实现登录Linux服务器并执行指令返回数据的工程
链接:https://pan.baidu.com/s/1ShXnldDHVv3YjDUJp4aMrg
提取码:rz6m
libssh2官网,这个里面好像并没有什么用,下载的东西只有代码,然后编译一堆错误
libssh2 函数说明
密钥文件登录Linux服务器
Windows 配置 ssh 免密登录_windows ssh_清潇和梨花的博客-CSDN博客
这里的难点是libssh2.dll编译,这个需要openssl zlib 2个环境,
配置的过程很麻烦总缺少东西,原以为是需要安装zlib 和 openssl,现在看来大神已经配置好到工程里了
我也没走通配置过程,这个工程是从GitHub里下载的,当时下载太多资源导致链接找不到了
现提供一个资源下载,方便自己方便他人
现在又有一个客户要求使用密钥文件执行ssh指令,使用上面那个libssh2编译出来的libssh2.dll老在验证密钥那里报错
密钥文件是没有后缀名的文件,再提供客户发过来的libssh2程序,编译环境与上面找的那个libssh2一致,openssl 和 zlib
遇到同样文件可以用这个工程试一下
链接:https://pan.baidu.com/s/1ANAST8UWjo9mEUhGBz7AKQ
提取码:s3k5
########################################################################################################################
这个dll是偶然得到的,可以用
https://files.cnblogs.com/files/ckrgd/libssh2.rar?t=1733474531&download=true
把代码写出来以后供参考
1 //SSH会话对象 2 LIBSSH2_SESSION *m_SSHsession; 3 //socket对象 4 SOCKET m_socket; 5 //会话通道 6 LIBSSH2_CHANNEL *m_SSHchannel; 7 8 9 //连接ssh 10 BOOL ConnectSSH(CString strIP, CString strUserName, CString strKeyFile) 11 { 12 //指定socket版本 13 WSADATA wsadata; 14 int err = WSAStartup(MAKEWORD(2, 0), &wsadata); 15 if (err != 0) 16 { 17 CString strMsg; 18 strMsg.Format("WSAStartup failed with error:%d", err); 19 AfxMessageBox(strMsg); 20 return FALSE; 21 } 22 //初始化libssh2函数 23 int rc = libssh2_init(0); 24 if (rc != 0) 25 { 26 CString strMsg; 27 strMsg.Format("libssh2_init failed:%d", rc); 28 AfxMessageBox(strMsg); 29 return FALSE; 30 } 31 //socket连接 32 m_socket = socket(AF_INET, SOCK_STREAM, 0); 33 struct sockaddr_in sin; 34 sin.sin_family = AF_INET; 35 sin.sin_port = htons(22); 36 sin.sin_addr.s_addr = inet_addr(strIP); 37 if (connect(m_socket, (struct sockaddr*)(&sin), sizeof(struct sockaddr_in)) != 0) 38 { 39 CString strMsg; 40 strMsg.Format("socket failed to connect"); 41 AfxMessageBox(strMsg); 42 return FALSE; 43 } 44 //初始化SSH会话对象 45 m_SSHsession = libssh2_session_init(); 46 if (!m_SSHsession) 47 { 48 CString strMsg; 49 strMsg.Format("libssh2_session_init error"); 50 AfxMessageBox(strMsg); 51 return FALSE; 52 } 53 //设置或者清除会话的阻塞模式 54 libssh2_session_set_blocking(m_SSHsession, 0); 55 //执行SSH握手 56 while ((rc = libssh2_session_handshake(m_SSHsession, m_socket)) == LIBSSH2_ERROR_EAGAIN); 57 if (rc) 58 { 59 CString strMsg; 60 strMsg.Format("libssh2_session_handshake error:%d", rc); 61 AfxMessageBox(strMsg); 62 return FALSE; 63 } 64 //为此会话初始化已知主机的集合 返回的句柄用作libssh2提供的所有其他已知主机相关函数的输入 65 LIBSSH2_KNOWNHOSTS *nh; 66 nh = libssh2_knownhost_init(m_SSHsession); 67 if (!nh) 68 { 69 CString strMsg; 70 strMsg.Format("libssh2_knownhost_init error"); 71 AfxMessageBox(strMsg); 72 return FALSE; 73 } 74 //从指定文件中读取已知主机的集合 75 libssh2_knownhost_readfile(nh, "known_hosts", LIBSSH2_KNOWNHOST_FILE_OPENSSH); 76 //将已知主机的集合写入文件 77 libssh2_knownhost_writefile(nh, "dumpfile", LIBSSH2_KNOWNHOST_FILE_OPENSSH); 78 79 size_t len; 80 int type; 81 //获取远程密钥 82 const char *fingerprint; 83 fingerprint = libssh2_session_hostkey(m_SSHsession, &len, &type); 84 if (fingerprint) 85 { 86 //对照已知主机列表检查主机+密钥 87 struct libssh2_knownhost *host; 88 int check = libssh2_knownhost_checkp(nh, strIP, 22, fingerprint, len, LIBSSH2_KNOWNHOST_TYPE_PLAIN | LIBSSH2_KNOWNHOST_KEYENC_RAW, &host); 89 } 90 else 91 { 92 CString strMsg; 93 strMsg.Format("libssh2_session_hostkey error"); 94 AfxMessageBox(strMsg); 95 return FALSE; 96 } 97 //释放已知主机的集合 98 libssh2_knownhost_free(nh); 99 //使用密钥文件的方式登录 100 CString strPassWord; 101 strPassWord.Empty(); 102 if (strlen(strPassWord) != 0) 103 { 104 //用户身份验证密码 105 while ((rc = libssh2_userauth_password(m_SSHsession, strUserName, strPassWord)) == LIBSSH2_ERROR_EAGAIN); 106 if (rc) 107 { 108 CString strMsg; 109 strMsg.Format("libssh2_userauth_password error"); 110 AfxMessageBox(strMsg); 111 return FALSE; 112 } 113 } 114 else 115 { 116 //私钥文件登录 117 while ((rc = libssh2_userauth_publickey_fromfile(m_SSHsession, strUserName, NULL, strKeyFile, NULL)) == LIBSSH2_ERROR_EAGAIN); 118 if (rc) 119 { 120 char *error = NULL; 121 libssh2_session_last_error(m_SSHsession, &error, NULL, 0); 122 CString strMsg; 123 strMsg.Format("libssh2_userauth_publickey_fromfile failed:%d,%s", rc, error); 124 AfxMessageBox(strMsg); 125 return FALSE; 126 } 127 } 128 129 return TRUE; 130 } 131 132 //关闭ssh 133 BOOL CloseSSH() 134 { 135 //int exitcode = 127; 136 //int rc; 137 ////关闭通道 138 //while ((rc = libssh2_channel_close(m_SSHchannel)) == LIBSSH2_ERROR_EAGAIN) 139 //{ 140 // waitsocket(m_socket, m_SSHsession); 141 //} 142 //char *exitsignal = (char *)"none"; 143 //if (rc == 0) 144 //{ 145 // //获取远程退出代码 146 // exitcode = libssh2_channel_get_exit_status(m_SSHchannel); 147 // //获取远程退出信号 148 // libssh2_channel_get_exit_signal(m_SSHchannel, &exitsignal, NULL, NULL, NULL, NULL, NULL); 149 //} 150 //if (exitsignal) 151 //{ 152 // CString strMsg; 153 // strMsg.Format("Got signal:%s", exitsignal); 154 // AfxMessageBox(strMsg); 155 // return FALSE; 156 //} 157 158 //释放与通道关联的所有资源 159 libssh2_channel_free(m_SSHchannel); 160 m_SSHchannel = NULL; 161 //终止传输层 162 libssh2_session_disconnect(m_SSHsession, "Normal Shutdown, Thank you for playing"); 163 //释放与会话实例关联的资源 164 libssh2_session_free(m_SSHsession); 165 //关闭套接字 166 closesocket(m_socket); 167 //全局库取消初始化 168 libssh2_exit(); 169 170 return TRUE; 171 } 172 173 static int waitsocket(int socket_fd, LIBSSH2_SESSION *session) 174 { 175 struct timeval timeout; 176 int rc; 177 fd_set fd; 178 fd_set *writefd = NULL; 179 fd_set *readfd = NULL; 180 int dir; 181 182 timeout.tv_sec = 10; 183 timeout.tv_usec = 0; 184 185 FD_ZERO(&fd); 186 FD_SET(socket_fd, &fd); 187 188 //应用程序应等待套接字具有可用于读取或写入的数据 189 dir = libssh2_session_block_directions(session); 190 if (dir & LIBSSH2_SESSION_BLOCK_INBOUND) 191 { 192 readfd = &fd; 193 } 194 if (dir & LIBSSH2_SESSION_BLOCK_OUTBOUND) 195 { 196 writefd = &fd; 197 } 198 //确定一个或多个套接字的状态 199 rc = select(socket_fd + 1, readfd, writefd, NULL, &timeout); 200 201 return rc; 202 } 203 204 //执行指令并返回 205 BOOL ExecSSHCmd(CString strCmdFlag, CString &strRead) 206 { 207 CLog mLog; 208 CString strCmd; 209 210 //得到指令 211 mLog.WriteSSHLog("执行指令:%s,%s", strCmdFlag, strCmd); 212 213 //建立通用会话通道 214 while ((m_SSHchannel = libssh2_channel_open_session(m_SSHsession)) == NULL && libssh2_session_last_error(m_SSHsession, NULL, NULL, 0) == LIBSSH2_ERROR_EAGAIN) 215 { 216 waitsocket(m_socket, m_SSHsession); 217 } 218 if (m_SSHchannel == NULL) 219 { 220 CString strMsg; 221 strMsg.Format("libssh2_channel_open_session Error"); 222 AfxMessageBox(strMsg); 223 return FALSE; 224 } 225 //执行shell指令 226 int rc; 227 while ((rc = libssh2_channel_exec(m_SSHchannel, strCmd)) == LIBSSH2_ERROR_EAGAIN) 228 { 229 waitsocket(m_socket, m_SSHsession); 230 } 231 if (rc != 0) 232 { 233 CString strMsg; 234 strMsg.Format("libssh2_channel_exec Error"); 235 AfxMessageBox(strMsg); 236 return FALSE; 237 } 238 239 //这是重启指令 240 if (strCmdFlag == "A15-3" || strCmdFlag == "F2") 241 { 242 CloseSSH(); 243 return TRUE; 244 } 245 char buffer[0x4000]; 246 int bytecount = 0; 247 for (;;) 248 { 249 int rc; 250 do 251 { 252 //从通道流读取数据 253 rc = libssh2_channel_read(m_SSHchannel, buffer, sizeof(buffer)); 254 if (rc > 0) 255 { 256 int i; 257 bytecount += rc; 258 for (i = 0; i < rc; ++i) 259 { 260 fputc(buffer[i], stderr); 261 } 262 } 263 } while (rc > 0); 264 if (rc == LIBSSH2_ERROR_EAGAIN) 265 { 266 waitsocket(m_socket, m_SSHsession); 267 } 268 else 269 { 270 break; 271 } 272 } 273 //不加结束符会有些烫烫烫 274 buffer[bytecount] = '\0'; 275 //关闭会话通道 276 libssh2_channel_close(m_SSHchannel); 277 strRead.Format("%s", buffer); 278 strRead.Remove('\n');//这个'\n'就是'\0' 影响解析所以干掉他 279 mLog.WriteSSHLog("返回结果:%s", strRead); 280 //解析返回数据 281 InterpretingData(strCmdFlag, strRead); 282 283 return TRUE; 284 }
#############################################################################################################
这c++整一星期还没搞定,c#10分钟就完事了
C#使用SSH.NET编写一个Linux操作客户端_ssh net-CSDN博客
1.前言
因为公司的网关与流媒体是基于Linux,如何查询网关与流媒体程序的运行日志如果直接操作服务器,存在着很大的风险。所以准备做一个基于winform的日志查询工具或者Linux运维工具,显得相对比较重要。
2.实现
2.1.开发工具
我这边使用的是VS2015,框架使用的是.NET Framework 4.6.1
2.2.引入dll
右键引用,选择“管理NuGet程序包”。
在浏览界面搜索框输入SSH.NET
选择SSH.NET后点击安装
到此开发包引入完成
2.3.操作封装
using Renci.SshNet; using System; namespace NetSSHOperation.Utils { public class SSHClass { public delegate void GetSSHLog(string log); public static event GetSSHLog getSSHLog; /// <summary> /// SSH登录远程Linux服务器,并运行指令 /// </summary> /// <param name="host">远程Linux服务器IP或域名</param> /// <param name="username">账号名</param> /// <param name="password">账号密码</param> /// <param name="command">命令</param> /// <returns></returns> public static void RunSSHCommands(string host, string username, string password, string command) { if (command == null || command.Length == 0) { getSSHLog("指令为空!"); } try { using (var client = new SshClient(host, username, password)) { try { client.Connect(); string result = client.RunCommand(command).Execute(); getSSHLog(result); client.Disconnect(); } catch (Exception e) { getSSHLog(e.Message); } } } catch (Exception e) { getSSHLog(e.Message); } } } }

浙公网安备 33010602011771号