如何使用Python连接到远程Windows计算机并执行命令?

31

我是Python的新手,正在尝试编写一个脚本,连接到远程Windows机器并在那里执行命令以测试端口连通性。

这是我正在编写的代码,但它不起作用。基本上,我想要的是连接到远程机器并返回该机器的数据,而不是本地机器的数据。

import wmi
import os
import subprocess
import re
import socket, sys

def main():

     host="remotemachine"
     username="adminaam"
     password="passpass!"
     server =connects(host, username, password)
     s = socket.socket()
     s.settimeout(5)
     print server.run_remote('hostname')

class connects:

    def __init__(self, host, username, password, s = socket.socket()):
        self.host=host
        self.username=username
        self.password=password
        self.s=s

        try:
            self.connection= wmi.WMI(self.host, user=self.username, password=self.password)
            self.s.connect(('10.10.10.3', 25))
            print "Connection established"
        except:
            print "Could not connect to machine"


   def run_remote(self, cmd, async=False, minimized=True):
       call=subprocess.check_output(cmd, shell=True,stderr=subprocess.STDOUT )
       print call

main() 

有什么建议吗?请帮帮忙。 - zewOlF
重要的是在用户名前面加上域名前缀。例如 username = r"EUR\adminaam" - MathKid
11个回答

12

您可以使用以下两种方法之一将网络中的一台计算机连接到另一台计算机:

  • 使用 WMI 库。
  • Netuse 方法。

WMI

以下是使用 wmi 模块进行连接的示例:

ip = '192.168.1.13'
username = 'username'
password = 'password'
from socket import *
try:
    print("Establishing connection to %s" %ip)
    connection = wmi.WMI(ip, user=username, password=password)
    print("Connection established")
except wmi.x_wmi:
    print("Your Username and Password of "+getfqdn(ip)+" are wrong.")

netuse

第二种方法是使用 netuse 模块。

通过 Netuse,您可以连接到远程计算机。您可以以以下两种方式访问远程计算机的所有数据:

  1. 通过虚拟连接进行连接。

    import win32api
    import win32net
    ip = '192.168.1.18'
    username = 'ram'
    password = 'ram@123'
    
    use_dict={}
    use_dict['remote']=unicode('\\\\192.168.1.18\C$')
    use_dict['password']=unicode(password)
    use_dict['username']=unicode(username)
    win32net.NetUseAdd(None, 2, use_dict)
    

    断开连接:

    import win32api
    import win32net
    win32net.NetUseDel('\\\\192.168.1.18',username,win32net.USE_FORCE)
    
  2. 在本地系统中挂载远程计算机驱动器。

  3. import win32api
    import win32net
    import win32netcon,win32wnet
    
    username='user'
    password='psw'
    
    try:
        win32wnet.WNetAddConnection2(win32netcon.RESOURCETYPE_DISK, 'Z:','\\\\192.168.1.18\\D$', None, username, password, 0)
        print('connection established successfully')
    except:
        print('connection not established')
    

    在本地系统中卸载远程计算机驱动器:

    import win32api
    import win32net
    import win32netcon,win32wnet
    
    win32wnet.WNetCancelConnection2('\\\\192.168.1.4\\D$',1,1)
    

在使用 netuse 之前,您应该确保已经在您的系统中安装了 pywin32 并且与 Python 兼容。


来源:连接远程计算机


1
WMI和Netuse相比有什么相对的优缺点,反之亦然? - alpha_989

10
你可以使用跨平台兼容的 pywinrm 代替。

这里是一个简单的代码示例:

#!/usr/bin/env python
import winrm

# Create winrm connection.
sess = winrm.Session('https://10.0.0.1', auth=('username', 'password'), transport='kerberos')
result = sess.run_cmd('ipconfig', ['/all'])

通过以下方式安装库:pip install pywinrm requests_kerberos


这里是从此页面的另一个示例,以在远程主机上运行 Powershell 脚本:

import winrm

ps_script = """$strComputer = $Host
Clear
$RAM = WmiObject Win32_ComputerSystem
$MB = 1048576

"Installed Memory: " + [int]($RAM.TotalPhysicalMemory /$MB) + " MB" """

s = winrm.Session('windows-host.example.com', auth=('john.smith', 'secret'))
r = s.run_ps(ps_script)
>>> r.status_code
0
>>> r.std_out
Installed Memory: 3840 MB

>>> r.std_err

我正在尝试这个,但是当我运行像'ipconfig'这样的命令时,遇到了问题。它显示“HTTPSConnectionPool(host ='192.168.1.13',port = 5986):超过了url:/ wsman的最大重试次数(由ConnectTimeoutError(<requests.packages.urllib3.connection.VerifiedHTTPSConnection object at 0x7fcb12024a90>引起),'连接到192.168.1.13超时。(连接超时= 30)')”。 - Adnan Sheikh

7
也许您可以使用SSH连接到远程服务器。
在Windows服务器上安装freeSSHd。
SSH客户端连接代码:
import paramiko

hostname = "your-hostname"
username = "your-username"
password = "your-password"
cmd = 'your-command'

try:
    ssh = paramiko.SSHClient()
    ssh.set_missing_host_key_policy(paramiko.AutoAddPolicy())
    ssh.connect(hostname,username=username,password=password)
    print("Connected to %s" % hostname)
except paramiko.AuthenticationException:
    print("Failed to connect to %s due to wrong username/password" %hostname)
    exit(1)
except Exception as e:
    print(e.message)    
    exit(2)

执行命令并获得反馈:

try:
    stdin, stdout, stderr = ssh.exec_command(cmd)
except Exception as e:
    print(e.message)

err = ''.join(stderr.readlines())
out = ''.join(stdout.readlines())
final_output = str(out)+str(err)
print(final_output)

这个解决方案帮了我大忙。我正在尝试从Windows机器上运行一个shell脚本到远程机器,最终需要运行Python脚本路径。 如果我需要运行多个命令,那么我可以重复执行命令框吗?请建议。 - Rohit
当您多次运行exec_command时,每个命令都在自己的“shell”中执行。因此,先前的命令对后续命令的环境没有影响。 - Beatrice Lin
如果您需要前面的命令影响后续的命令,只需使用服务器shell的适当语法。大多数*nix shell使用分号或双“&”(具有不同的语义)来指定命令列表。在您的情况下,符号“&”更合适,因为它只有在前面的命令成功执行后才会执行后续命令:像这样: stdin,stdout,stderr = ssh.exec_command(“ORACLE_SID = PROD && cd / 01 / application / dataload && pwd”) - Beatrice Lin

6

建立连接

c=wmi.WMI('machine name',user='username',password='password')

#this connects to remote system. c is wmi object

针对命令

process_id, return_value = c.Win32_Process.Create(CommandLine="cmd.exe /c  <your command>")

#this will execute commands

哇,非常酷,工作得非常好,可以使用pip安装。 [#]pip install wmi - Michael Biniashvili

2

客户端机器是否已经安装了Python?如果是的话,我将使用psexec来完成此操作。

在我的本地机器上,我使用subprocess在我的.py文件中调用命令行。

import subprocess
subprocess.call("psexec {server} -c {}") 

-c选项会将文件复制到服务器上,这样我就可以运行任何可执行文件(在您的情况下可能是一个充满连接测试或上面提到的.py文件的.bat文件)。


2
我个人发现{{link1:pywinrm库}}非常有效。但是,在它能够正常工作之前,需要在计算机上运行一些命令并进行其他设置。

你能推荐一些可用于跨平台远程登录的软件包吗? - Rjain
很有趣,你问得正好。我个人正在开源一个库,专门用于这个目的。 - Rusty Weber

1

我不了解WMI,但是如果你想要一个简单的服务端/客户端, 你可以使用tutorialspoint上的这个简单代码。

服务器端:

import socket               # Import socket module

s = socket.socket()         # Create a socket object
host = socket.gethostname() # Get local machine name
port = 12345                # Reserve a port for your service.
s.bind((host, port))        # Bind to the port

s.listen(5)                 # Now wait for client connection.
while True:
   c, addr = s.accept()     # Establish connection with client.
   print 'Got connection from', addr
   c.send('Thank you for connecting')
   c.close()                # Close the connection 

客户端

#!/usr/bin/python           # This is client.py file

import socket               # Import socket module

s = socket.socket()         # Create a socket object
host = socket.gethostname() # Get local machine name
port = 12345                # Reserve a port for your service.

s.connect((host, port))
print s.recv(1024)
s.close                     # Close the socket when done

它还包含了简单客户端/服务器应用所需的所有信息。

只需转换服务器并使用一些简单的协议从Python调用函数即可。

P.S:我相信有很多更好的选择,但如果您想要一个简单的选择,这只是其中之一...


谢谢Kobi的回复,但是要去每个客户端运行脚本会非常困难...... 我想做的是从一个机器访问多台机器并在那里执行命令。 - zewOlF

1

连接远程服务器并执行命令的最佳方法是使用“wmiexec.py

只需运行pip install impacket

这将在Python的scripts文件夹下创建“wmiexec.py”文件

在python > Scripts > wmiexec.py内部,我们需要按以下方式运行wmiexec.py

python <wmiexec.py location> TargetUser:TargetPassword@TargetHostname "<OS command>"

请根据您自己的情况更改wmiexec.py文件的位置。例如,我使用的是Python 3.8.5,我的wmiexec.py文件位于C:\python3.8.5\Scripts\wmiexec.py
python C:\python3.8.5\Scripts\wmiexec.py TargetUser:TargetPassword@TargetHostname "<OS command>"

根据您的远程机器修改TargetUser,TargetPassword,TargetHostname和OS命令

注意: 上述方法用于在远程服务器上运行命令。

但是,如果您需要捕获来自远程服务器的输出,我们需要创建一个Python代码。

import subprocess
command = 'C:\\Python36\\python.exe C:\\Python36\\Scripts\\wmiexec.py TargetUser:TargetPassword@TargetHostname "ipconfig"'
command = subprocess.Popen(command, shell=True, stdout=subprocess.PIPE)
stdout= command.communicate()[0]
print (stdout)

相应地修改代码并运行它。


0

现在太晚了吗?

我个人同意Beatrice Len的观点,我使用paramiko可能对于Windows来说是一个额外的步骤,但我有一个示例项目在git hub上,随时可以克隆或向我询问。

https://github.com/davcastroruiz/django-ssh-monitor


0

已经有很多答案了,但还有一个选项

PyPSExec https://pypi.org/project/pypsexec/

这是著名的psexec的Python克隆版本。 在远程Windows机器上无需任何安装即可运行。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接