我们知道,通过SSH服务可以远程连接到Linux服务器,查看上面的日志状态,批量配置远程服务器,文件上传,文件下载等,Python的paramiko模块同样实现了这一功能。

首先我们需要安装这一模块,pycharm环境中如下操作

一,安装paramiko模块

PyCharm→Preferences→Project:项目名→Project Interpreter

点击箭头所指加号,在搜索框输入选中,并安装

完成后会在Project Interpreter中显示,如上上图

二, 基于用户名和密码的 sshclient 方式登录

import paramiko
# 创建SSH对象
ssh = paramiko.SSHClient()
# 允许连接不在know_hosts文件中的主机ssh.set_missing_host_key_policy(paramiko.AutoAddPolicy())
# 连接服务器
ssh.connect(hostname='192.168.199.146', port=22, username='fishman', password='9')
# 执行命令
stdin, stdout, stderr = ssh.exec_command('df')
# 获取命令结果
res,err = stdout.read(),stderr.read()
result = res if res else errprint(result.decode())# 关闭连接
ssh.close()

解析:首先导入模块,然后创建一个SSH对象,然后通过命令连接远程机器,默认端口是22,这里我连接的是192.168.199.146的机器,密码为9,然后执行df命令,获取返回的结果如下

我们可以比较一下通过SSH得到的结果

三,基于用户名和密码的 transport 方式登录

基于SSHClient是传统的连接服务器、执行命令、关闭的一个操作,有时候需要登录上服务器执行多个操作,比如执行命令、上传/下载文件,上面方法则无法实现,可以通过如下方式来操作

#SSHClient 封装 Transport
import paramiko
# 实例化一个transport对象
transport = paramiko.Transport(('192.168.199.146', 22))
# 建立连接
transport.connect(username='fishman', password='9')
# 将sshclient的对象的transport指定为以上的transport
ssh = paramiko.SSHClient()
ssh._transport = transport
# 执行命令,和传统方法一样
stdin, stdout, stderr = ssh.exec_command('df')
print (stdout.read().decode())
# 关闭连接
transport.close()

四,基于公钥密钥连接

4.1 SSH配置免密登陆

我们知道通过配置公钥密钥,可以实现SSH的免密登陆,比如现在连接fishman机器会提示我们输入密码,然后才能登陆

通过SSH原理与运用中介绍,我们知道,要实现免密公钥登陆,需要将我们自己机器的公钥存储在要登陆的远程主机上。登录的时候,远程主机会向用户发送一段随机字符串,用户用自己的私钥加密后,再发回来。远程主机用事先储存的公钥进行解密,如果成功,就证明用户是可信的,直接允许登录shell,不再要求密码。

首先我们生成自己的公钥通过命令 ssh-keygen,这里会提示这个公钥保存的文件路径,默认即可然后回车,这里由于我本地已经有生成的公钥,所以提示是否要覆盖,我这里就不重写了,如果本地没有生成过继续回车,提示要不要对私钥设置口令(passphrase),如果担心私钥的安全,这里可以设置一个。默认也可以直接回车

得到公钥后一种方法是通过命令将公钥直接传到远程机器ssh-copy-id user@host,如我们登陆的机器:

ssh-copy-id fishman@192.168.199.146

另一种方法是进入公钥文件去复制,进入.ssh/id_rsa.pub通过more或者cat复制公钥

➜  ~ more .ssh/id_rsa.pub
ssh-rsa AAAAB3NzaC1yc2EAAAADAQABAAABAQCyQ2GtkbKcFAP/kX/+65e91Q8EJ+twpyqjEBzlVmZ2mxy8Zw7b/AfeV60ehloCq7p521IGJaXWbr3bky7Jljc6x7cAZsRW7mZRPFelPYa5iJ4lIshU3RwhbTYW6RyrG+InF3ognJ7bggpPmJbWFxqqpZwdkEilpnv0+8b17frSbF1xaQQh57vDjG78xr0pys2MBzylqrs1RNiTcRz86zJT7SbujYY/bpiUB78w46CmRlwzHOk8Zg0hcegqSMHjboQyhkSX0xcFv2ZLHm5Gpfba3863M+62Q1r2U+QW5Ki1f3nsGwHWQIRuHNWldUzWKYRPsKJHVvwFwkYDG3sZZMWR ljf@meijiabaodeiMac.lan
➜  ~ cat .ssh/id_rsa.pub
ssh-rsa AAAAB3NzaC1yc2EAAAADAQABAAABAQCyQ2GtkbKcFAP/kX/+65e91Q8EJ+twpyqjEBzlVmZ2mxy8Zw7b/AfeV60ehloCq7p521IGJaXWbr3bky7Jljc6x7cAZsRW7mZRPFelPYa5iJ4lIshU3RwhbTYW6RyrG+InF3ognJ7bggpPmJbWFxqqpZwdkEilpnv0+8b17frSbF1xaQQh57vDjG78xr0pys2MBzylqrs1RNiTcRz86zJT7SbujYY/bpiUB78w46CmRlwzHOk8Zg0hcegqSMHjboQyhkSX0xcFv2ZLHm5Gpfba3863M+62Q1r2U+QW5Ki1f3nsGwHWQIRuHNWldUzWKYRPsKJHVvwFwkYDG3sZZMWR ljf@meijiabaodeiMac.lan
➜  ~

复制后,我们登陆远程机器,在目录下.ssh文件夹中发现有以下文件,其中id_ras id_ras.pub保存该机器的公钥私钥,

know_hosts:ssh会把你每个你访问过计算机的公钥(public key)都记录在~/.ssh/known_hosts。当下次访问相同计算机时,OpenSSH会核对公钥。如果公钥不同,OpenSSH会发出警告, 避免你受到DNS Hijack之类的攻击。

我们需要将刚才复制的我的公钥保存到authorized_keys文件中

通过vi打开编辑然后粘贴退出保存

此时,我们退出登陆,然后重新登陆,发现就不需要输入登陆密码了,可以实现免密登陆,美滋滋。

另外我们要注意,.ssh目录的权限为700,其下文件authorized_keys和私钥的权限为600。否则会因为权限问题导致无法免密码登录

另外,将公钥拷贝到服务器的~/.ssh/authorized_keys文件中方法有如下几种:
1、将公钥通过scp拷贝到服务器上,然后追加到~/.ssh/authorized_keys文件中,这种方式比较麻烦。scp -P 22 ~/.ssh/id_rsa.pub user@host:~/。
2、通过ssh-copy-id命令最简单,也是第一种方法,ssh-copy-id "-p22 user@host"即可,有时候user@host需要加引号,前面写-p端口号
3、可以通过cat ~/.ssh/id_rsa.pub | ssh -p 22 user@host ‘cat >> ~/.ssh/authorized_keys’,这个也是比较常用的方法,因为可以更改端口号。

4.2 基于公钥密钥的 SSHClient 方式登录

进入路径查看我本地id_rsa文件路径

import paramiko
private_key = paramiko.RSAKey.from_private_key_file('/Users/ljf/.ssh/id_rsa')
# 创建SSH对象
ssh = paramiko.SSHClient()
# 允许连接不在know_hosts文件中的主机
ssh.set_missing_host_key_policy(paramiko.AutoAddPolicy())
# 连接服务器
ssh.connect(hostname='192.168.199.146', port=22, username='fishman', pkey=private_key)
# 执行命令
stdin, stdout, stderr = ssh.exec_command('df')
# 获取命令结果
res,err = stdout.read(),stderr.read()
result = res if res else err
print(result.decode())
# 关闭连接
ssh.close()

同理。可以用transport封装

import paramiko
private_key = paramiko.RSAKey.from_private_key_file('/Users/ljf/.ssh/id_rsa')
# 实例化一个transport对象
transport = paramiko.Transport(('192.168.199.146', 22))
# 建立连接
transport.connect(username='fishman', pkey=private_key)
ssh = paramiko.SSHClient()
ssh._transport = transportstdin, stdout, stderr = ssh.exec_command('df')
# 获取命令结果
res,err = stdout.read(),stderr.read()
result = res if res else err
print(result.decode())
# 关闭连接
ssh.close()

同理,可以直接根据私钥字符串连接,首先在本地获取私钥字符串

➜  .ssh cat id_rsa
-----BEGIN RSA PRIVATE KEY-----
MIIEowIBAAKCAQEAskNhrZGynBQD/5F//uuXvdUPBCfrcKcqoxAc5VZmdpscvGcO
2/wH3letHoZaAqu6edtSBiWl1m6925MuyZY3Ose3AGbEVu5mUTxXpT2GuYieJSLI
VN0cIW02FukcqxviJxd6IJye24IKT5iW1hcaqqWcHZBIpaZ79PvG9e360mxdcWkE
Iee7w4xu/Ma9KcrNjAc8paq7NUTYk3Ec/OsyU+0m7o2GP26YlAe/MOOgpkZcMxzp
PGYNIXHoKkjB426EMoZEl9MXBb9mSx5uRqX22t/OtzPutkNa9lPkFuSotX957BsB
1kCEbhzVpXVM1imET7CiR1b8BcJGAxt7GWTFkQIDAQABAoIBAH54j7Q0yiMxkCSh
dc3GF8H2htDMAZ3K+9T0eYu74LYFFj4UX9Zy2KJGUex2JSX/8CzEDU2PKDkaGFjP
80HR8R0i1BLU1jdWrAC2bvgszoiTBKAULU0IEg0lDlryyAQdpDVX0q2QcKQLfoU6
HMmHWsP2+ut+kgv0Mb19Y4rXbDwctmx53BJ0Ykk3RaQe8FiLOAAdFzxbGIUdIwLh
N8PEh9HW/wMFvJVEAgNu3oD0bONH+PZKasxqnOQlHrILSPQrNiXBOxCYr9u8cFx7
hl1V0yhQHnCF+JK2se6VXQnJ1pUVtWc3kRTtwas3x7IRPdNJDbj8WT6/n6ocUm+Q
OgEY9gECgYEA3CtYVABizz8GsHpged/xDkOKf9gET5m1kX/awdd3m6lkoWboB5OL
ym6YwxWpl6Fs0XHRAih3w2434MyTxqdgZf5ixMgq00PBr7itGycokLm1KO1GFjbZ
4tog3qwX6vejHsDl+TMWojxmkEjwQ1uPcQOeY96CvOafHH+kP5zmfAUCgYEAz0Ym
1y07sSfiKSDEO+99r7deex8fssk/xcFI3PgD/4zwu0zGF3QIB124cbZX6Sy6ut0d
jzX+RQm5OGUNR1m4Qg1syeNIEF/2mV0rL7+qPGIpYIsuoeuBwedNj7qTIDx4wKtm
aJcwdErEQwRJ7UOX9KEdPkKivyf4A+uT5fCsJR0CgYBE7tFF46UMLDiE8pvYLLRF
egIYCuM2pPKDLpuoSzToqL2YBycokBqZc80ib1rc3a67WL5OxarRpmWaXZL7BJaa
+G2mHOHDqZgv00tnj/gUcAB3Yuqps9y+OPtHnGwUphoNW+nk/wjcHLsj+6I2BKnB
gZeKvzUBvdcdTh13yUEknQKBgHBkmNEbPP/+IXutwdrCLYQnyXq30Mdwqzz/ZxQz
BHABK9RUeCHlkCj2X/qBJsBQudxz5ABxBbTH5gC3gvDKrMhcYT5EGSKP9rcIt09H
/faKP+eS8TFp882CMCOcxwS25b+L8ZcLTIHyvOOeIrweZ/qFlsbY+UjwUmNFzcfk
rmPdAoGBAJ9NWhf16aLQxUrPkUvHK9k7ONUadamBxA6NNvHMZxow81/p9VQK71o7
iUdJmC/+VOvGqbA3AbtqkbjBMUWGjEeVKLxMnCZngfu9J6bnWDUaYbQz3gVY63ca
KFWjRXO6GtynW0Dec0Nj/q22V5J+2ZCkIvSAQ+cI04d0Ij7RdKPl
-----END RSA PRIVATE KEY-----
➜  .ssh
#!/usr/bin/env python
# -*- coding: utf-8 -*-
# 基于私钥字符串进行连接
import paramiko
from io import StringIO
key_str = """-----BEGIN RSA PRIVATE KEY-----
MIIEowIBAAKCAQEAskNhrZGynBQD/5F//uuXvdUPBCfrcKcqoxAc5VZmdpscvGcO
2/wH3letHoZaAqu6edtSBiWl1m6925MuyZY3Ose3AGbEVu5mUTxXpT2GuYieJSLI
VN0cIW02FukcqxviJxd6IJye24IKT5iW1hcaqqWcHZBIpaZ79PvG9e360mxdcWkE
Iee7w4xu/Ma9KcrNjAc8paq7NUTYk3Ec/OsyU+0m7o2GP26YlAe/MOOgpkZcMxzp
PGYNIXHoKkjB426EMoZEl9MXBb9mSx5uRqX22t/OtzPutkNa9lPkFuSotX957BsB
1kCEbhzVpXVM1imET7CiR1b8BcJGAxt7GWTFkQIDAQABAoIBAH54j7Q0yiMxkCSh
dc3GF8H2htDMAZ3K+9T0eYu74LYFFj4UX9Zy2KJGUex2JSX/8CzEDU2PKDkaGFjP
80HR8R0i1BLU1jdWrAC2bvgszoiTBKAULU0IEg0lDlryyAQdpDVX0q2QcKQLfoU6
HMmHWsP2+ut+kgv0Mb19Y4rXbDwctmx53BJ0Ykk3RaQe8FiLOAAdFzxbGIUdIwLh
N8PEh9HW/wMFvJVEAgNu3oD0bONH+PZKasxqnOQlHrILSPQrNiXBOxCYr9u8cFx7
hl1V0yhQHnCF+JK2se6VXQnJ1pUVtWc3kRTtwas3x7IRPdNJDbj8WT6/n6ocUm+Q
OgEY9gECgYEA3CtYVABizz8GsHpged/xDkOKf9gET5m1kX/awdd3m6lkoWboB5OL
ym6YwxWpl6Fs0XHRAih3w2434MyTxqdgZf5ixMgq00PBr7itGycokLm1KO1GFjbZ
4tog3qwX6vejHsDl+TMWojxmkEjwQ1uPcQOeY96CvOafHH+kP5zmfAUCgYEAz0Ym
1y07sSfiKSDEO+99r7deex8fssk/xcFI3PgD/4zwu0zGF3QIB124cbZX6Sy6ut0d
jzX+RQm5OGUNR1m4Qg1syeNIEF/2mV0rL7+qPGIpYIsuoeuBwedNj7qTIDx4wKtm
aJcwdErEQwRJ7UOX9KEdPkKivyf4A+uT5fCsJR0CgYBE7tFF46UMLDiE8pvYLLRF
egIYCuM2pPKDLpuoSzToqL2YBycokBqZc80ib1rc3a67WL5OxarRpmWaXZL7BJaa
+G2mHOHDqZgv00tnj/gUcAB3Yuqps9y+OPtHnGwUphoNW+nk/wjcHLsj+6I2BKnB
gZeKvzUBvdcdTh13yUEknQKBgHBkmNEbPP/+IXutwdrCLYQnyXq30Mdwqzz/ZxQz
BHABK9RUeCHlkCj2X/qBJsBQudxz5ABxBbTH5gC3gvDKrMhcYT5EGSKP9rcIt09H
/faKP+eS8TFp882CMCOcxwS25b+L8ZcLTIHyvOOeIrweZ/qFlsbY+UjwUmNFzcfk
rmPdAoGBAJ9NWhf16aLQxUrPkUvHK9k7ONUadamBxA6NNvHMZxow81/p9VQK71o7
iUdJmC/+VOvGqbA3AbtqkbjBMUWGjEeVKLxMnCZngfu9J6bnWDUaYbQz3gVY63ca
KFWjRXO6GtynW0Dec0Nj/q22V5J+2ZCkIvSAQ+cI04d0Ij7RdKPl
-----END RSA PRIVATE KEY-----"""
private_key = paramiko.RSAKey(file_obj=StringIO(key_str))
transport = paramiko.Transport(('192.168.199.146', 22))
transport.connect(username='fishman', pkey=private_key)ssh = paramiko.SSHClient()
ssh._transport = transportstdin, stdout, stderr = ssh.exec_command('df')
res,err = stdout.read(),stderr.read()
result = res if res else err
print(result.decode())
# 关闭连接
ssh.close()

以上得到的结果都相同

这里需要注意,如果你是Linux及OSX系统,那么自带SSH,以上操作都没问题,如果你是Windows,那么通过Xsheel也可以生成一个,通过Xsheel--》工具--》新建用户秘钥生成向导,

如果没有装Xsheel,可以将Linux的公钥copy过来,这样在这里可以读取本地存的公钥信息

通过命令sz ~/.ssh/id_rsa,将公钥保存为一个txt文件,paramiko.RSAKey.from_private_key_file(公钥文件)

五,SFTPClient用于连接远程服务器并执行上传下载

我们计划将本地LocalFile.txt上传到fishman机器的test路径下remote.txt,这是该路径下原来的文件,其中remote.txt为空,没有内容,通过sftp.put('LocalFile.txt', '/home/fishman/test/remote.txt')即可上传

基于用户名密码上传下载

import paramiko
# 实例化一个trans对象# 实例化一个transport对象
transport = paramiko.Transport(('192.168.199.146', 22))
# 建立连接
transport.connect(username='fishman', password='9')
# 实例化一个 sftp对象,指定连接的通道
sftp = paramiko.SFTPClient.from_transport(transport)# LocalFile.txt 上传至服务器 /home/fishman/test/remote.txt
# sftp.put('LocalFile.txt', '/home/fishman/test/remote.txt')
# 将LinuxFile.txt 下载到本地 fromlinux.txt文件中
sftp.get('/home/fishman/test/LinuxFile.txt', 'fromlinux.txt')
transport.close()

同理,我们可以下载远程机器上test路径下的LinuxFile.txt文件到本地fromLinux.txt

基于公钥密钥上传下载

import paramiko
private_key = paramiko.RSAKey.from_private_key_file('/Users/ljf/.ssh/id_rsa')
transport = paramiko.Transport(('192.168.199.146', 22))
transport.connect(username='fishman', password='9')
sftp = paramiko.SFTPClient.from_transport(transport)# LocalFile.txt 上传至服务器 /home/fishman/test/remote.txt
# sftp.put('LocalFile.txt', '/home/fishman/test/remote.txt')
# 将LinuxFile.txt 下载到本地 fromlinux.txt文件中
sftp.get('/home/fishman/test/LinuxFile.txt', 'fromlinux.txt')transport.close()

5 实现输入命令立马返回结果的功能 
以上操作都是基本的连接,如果我们想实现一个类似xshell工具的功能,登录以后可以输入命令回车后就返回结果:

import paramiko
import os
import select
import sys# 建立一个socket
trans = paramiko.Transport(('192.168.2.129', 22))
# 启动一个客户端
trans.start_client()# 如果使用rsa密钥登录的话
'''
default_key_file = os.path.join(os.environ['HOME'], '.ssh', 'id_rsa')
prikey = paramiko.RSAKey.from_private_key_file(default_key_file)
trans.auth_publickey(username='super', key=prikey)
'''
# 如果使用用户名和密码登录
trans.auth_password(username='super', password='super')
# 打开一个通道
channel = trans.open_session()
# 获取终端
channel.get_pty()
# 激活终端,这样就可以登录到终端了,就和我们用类似于xshell登录系统一样
channel.invoke_shell()
# 下面就可以执行你所有的操作,用select实现
# 对输入终端sys.stdin和 通道进行监控,
# 当用户在终端输入命令后,将命令交给channel通道,这个时候sys.stdin就发生变化,select就可以感知
# channel的发送命令、获取结果过程其实就是一个socket的发送和接受信息的过程
while True:readlist, writelist, errlist = select.select([channel, sys.stdin,], [], [])# 如果是用户输入命令了,sys.stdin发生变化if sys.stdin in readlist:# 获取输入的内容input_cmd = sys.stdin.read(1)# 将命令发送给服务器channel.sendall(input_cmd)# 服务器返回了结果,channel通道接受到结果,发生变化 select感知到if channel in readlist:# 获取结果result = channel.recv(1024)# 断开连接后退出if len(result) == 0:print("\r\n**** EOF **** \r\n")break# 输出到屏幕sys.stdout.write(result.decode())sys.stdout.flush()# 关闭通道
channel.close()
# 关闭链接
trans.close()

6 支持tab自动补全

import paramiko
import os
import select
import sys
import tty
import termios'''
实现一个xshell登录系统的效果,登录到系统就不断输入命令同时返回结果
支持自动补全,直接调用服务器终端'''
# 建立一个socket
trans = paramiko.Transport(('192.168.2.129', 22))
# 启动一个客户端
trans.start_client()# 如果使用rsa密钥登录的话
'''
default_key_file = os.path.join(os.environ['HOME'], '.ssh', 'id_rsa')
prikey = paramiko.RSAKey.from_private_key_file(default_key_file)
trans.auth_publickey(username='super', key=prikey)
'''
# 如果使用用户名和密码登录
trans.auth_password(username='super', password='super')
# 打开一个通道
channel = trans.open_session()
# 获取终端
channel.get_pty()
# 激活终端,这样就可以登录到终端了,就和我们用类似于xshell登录系统一样
channel.invoke_shell()# 获取原操作终端属性
oldtty = termios.tcgetattr(sys.stdin)
try:# 将现在的操作终端属性设置为服务器上的原生终端属性,可以支持tab了tty.setraw(sys.stdin)channel.settimeout(0)while True:readlist, writelist, errlist = select.select([channel, sys.stdin,], [], [])# 如果是用户输入命令了,sys.stdin发生变化if sys.stdin in readlist:# 获取输入的内容,输入一个字符发送1个字符input_cmd = sys.stdin.read(1)# 将命令发送给服务器channel.sendall(input_cmd)# 服务器返回了结果,channel通道接受到结果,发生变化 select感知到if channel in readlist:# 获取结果result = channel.recv(1024)# 断开连接后退出if len(result) == 0:print("\r\n**** EOF **** \r\n")break# 输出到屏幕sys.stdout.write(result.decode())sys.stdout.flush()
finally:# 执行完后将现在的终端属性恢复为原操作终端属性termios.tcsetattr(sys.stdin, termios.TCSADRAIN, oldtty)# 关闭通道
channel.close()
# 关闭链接
trans.close()

Python paramiko 模块详解与SSH主要功能模拟相关推荐

  1. python time模块详解

    python time模块详解 转自:http://blog.csdn.net/kiki113/article/details/4033017 python 的内嵌time模板翻译及说明    一.简 ...

  2. python paramiko并发_使用Python paramiko模块利用多线程实现ssh并发执行操作

    1.paramiko概述 ssh是一个协议,OpenSSH是其中一个开源实现,paramiko是Python的一个库,实现了SSHv2协议(底层使用cryptography). 有了Paramiko以 ...

  3. Python—requests模块详解

    Python-requests模块详解 来源(博客园@小L小 ):Python-requests模块详解

  4. python re正则_正则表达式+Python re模块详解

    正则表达式(Regluar Expressions)又称规则表达式,在代码中常简写为REs,regexes或regexp(regex patterns).它本质上是一个小巧的.高度专用的编程语言. 通 ...

  5. python cx_oracle模块详解_cx_Oracle模块详解

    1.安装cx_Oracle模块 1-1.环境准备: 1-1-1.oracle client最小安装 instantclient-sqlplus-linux.x64-11.2.0.4.0 instant ...

  6. Python shutil 模块详解

    Python shutil 模块详解 1.模块介绍 2.copytree 示例 3.move 示例 1.模块介绍 import shutil# copy data from file-like obj ...

  7. Python timeit 模块详解(准确测量小段代码的执行时间)

    timeit 模块详解 -- 准确测量小段代码的执行时间 timeit 模块提供了测量 Python 小段代码执行时间的方法.它既可以在命令行界面直接使用,也可以通过导入模块进行调用.该模块灵活地避开 ...

  8. python pexpect模块详解_python pexpect原理详解及使用说明

    pexpect是python中用于实现SSH,FTP,telnet等命令进行自动化交互,从而无需人工干预实现自动化运维的一个第三方扩展模块.理论的描述过于抽象,这里首先设想一下,如果让您设计一个实现自 ...

  9. Python Tkinter模块详解(后续持续补充)

    声明:该文章是个人学习中写的,目的是总结及当作工具参考,有一定的借鉴成分,后续若有新发现则补充 目录 Tkinter简介 创建组件基本语法 Tkinter组件汇总 Variable 类 常见参数详解 ...

最新文章

  1. cmd系统命令不识别
  2. javascript Array方法总结
  3. 什么是Vue?Vue的工作原理是什么?
  4. 百度网盘不限速被限速_基本API限速
  5. 选择排序和冒泡排序以及折半查找
  6. Mysql数据库的几大优势
  7. 新突破!CVPR2019接收论文:新的基于自编码变换的无监督表示学习方法—AET
  8. [原创] ASP.NET 应用程序中使用定时器
  9. sql server (mssqlserver)无法启动,事件查看器提示SQL Server 无法生成 FRunCM 线程
  10. Oracle Sharding
  11. 收购小蓝单车部分资产、与ofo蜜月期结束,滴滴重构共享单车布局
  12. 【千份热门课后习题答案大全】
  13. eclipse php 教程,Eclipse PHPEclipse配置方法文字教程
  14. 苏宁“北京攻略”:老阵地,新战场 | 一点财经
  15. clone别人远程仓库的代码,运行npm install报错npm ERR! Maximum call stack size exceeded
  16. MusicPlayerByService
  17. 少儿编程教学平台和scratch课程
  18. 怎么撰写一份优秀的数据分析报告(三)
  19. Android键盘操作的函数:onKeyDown, onKeyUp, on, onKeyMultiple
  20. 你为什么在现在的公司不离职?

热门文章

  1. 解决telnet不是内部或外部命令的方案!
  2. windows10计算机里输入法,win10电脑上输入法不见了怎么办
  3. win10切换输入法快捷键_常用win10快捷键有哪些
  4. 如何在IntelliJ IDEA 中新建一个项目Project
  5. 【人工智能数学基础(三)】数学优化
  6. 网络与信息安全工程师职位要求
  7. [Puppeteer]Puppeteer+Mocha+Chai实现端到端测试
  8. SeetaFace2-master在Windows10 VS2019编译的两种方法
  9. python + opencv微博图片去水印
  10. 四旋翼飞行器控制pid学习笔记