通过PuTTY实现SSH的Python脚本

kgqe7b3p  于 2023-02-18  发布在  Python
关注(0)|答案(3)|浏览(203)

我可以在命令行中给予以下命令

C:\>cd "C:\Program Files\ExtraPuTTY\Bin"

C:\Program Files\ExtraPuTTY\Bin>putty.exe -ssh root@172.20.0.102 22

这有助于我通过PuTTY打开SSH会话。
但是我无法在Python脚本中重现它们。

cwd="C://Program Files//ExtraPuTTY//Bin"
COMMAND="ls"
ssh = Popen(['putty.exe -ssh','%s'%HOST, COMMAND,cwd],shell=True,stdout=f,stderr=f)

我看到的错误是
“putty.exe -ssh”'未被识别为内部或外部命令、可操作程序或批处理文件

zte4gxcn

zte4gxcn1#

putty download page中,下载并安装plink,并确保其位于windows path$PATH变量)中
然后,这个python代码片段应该可以工作:

import subprocess
cmd='plink -ssh {}@{} -pw {}'.format(user,server,password)
sp = subprocess.Popen(cmd, stdin=subprocess.PIPE, stdout=subprocess.PIPE,stderr=subprocess.PIPE, shell=True)
sp.stdin.write(stdin)
sp.stdin.close()
stdout= sp.stdout.read()
stderr=sp.stderr.read()
sp.wait()

stdin是用户在终端中键入的命令,stdoutstderr是服务器输出。
在ssh连接的user="root"server="172.20.0.102 22"password中填写凭据

falq053o

falq053o2#

您必须将cwd作为Popencwd参数传递:

Popen(['putty.exe -ssh'...], shell=True, stdout=f, stderr=f, cwd=cwd)

你应该使用Plink而不是PuTTY来自动执行远程命令,Plink接受命令行上的命令(PuTTY不接受):

Popen(['plink.exe -ssh root@172.20.0.102 ls'], shell=True, stdout=f, stderr=f, cwd=cwd)

更好的是,使用原生Python SSH库,比如Paramiko:
Python Paramiko - Run command

sr4lhrrt

sr4lhrrt3#

我知道这有点离题,但最封闭的主题,我发现(我想找到的代码一个星期前在该职位)
我正在寻找一个代码,以大量检查密码是否有效,并更改它,如果可能的话
Putty有几个cli工具,如plink和pscp,它们对很多东西都很有用。
这是python 3的函数,用来连接到ssh服务器并接受ssh密钥。使用pscp允许自动接受密钥......对于第一次使用可能很有用

def TestSSHConnection(IP_Addr,User,Password,verbosity=0, force_plink=False):
#Some infos about returned code
# 0 = Error Or crash
# 1 = Connection ok
# 2 = No connect Password Error
# 3 = SSH key trouble (shit append)
# 4 = Timeout
# 5 = Host Unreachable
# 6 = Connection Crash

out=""
err=""
try:
    if force_plink:
        print("echo y | plink -l "+str(User)+" -pw "+str(Password)+" -batch "+str(IP_Addr)+" exit",)
        ssh=subprocess.Popen("echo y | plink -l "+str(User)+" -pw "+str(Password)+" -batch "+str(IP_Addr)+" exit",shell=True, stdout=subprocess.PIPE, stderr=subprocess.PIPE,encoding='utf8')#,stdin=subprocess.PIPE)
    else:
        print("echo y | pscp -l "+str(User)+" -pw "+str(Password)+" -ls "+str(IP_Addr)+":/",)
        ssh=subprocess.Popen("echo y | pscp -l "+str(User)+" -pw "+str(Password)+" -ls "+str(IP_Addr)+":/",shell=True,stdout=subprocess.PIPE, stderr=subprocess.PIPE)

    out,err = ssh.communicate()
    try:
        out = out.decode('utf-8')
    except AttributeError as inst:
        pass
    except Exception as inst:
        if verbosity>1:
            print("While decoding stdout: "+str(type(inst)))
    try:
        err = err.decode('utf-8')
    except AttributeError as inst:
        pass
    except Exception as inst:
       print("While decoding stderr: "+str(type(inst)))
    ssh.kill()
    del ssh
except Exception as inst:
    print("Crash"+str(inst))
    return 0

if len(err)>0:
    if 'Unable to open connection' in err or 'Host does not exist' in err:
        if verbosity>0: print("Unreachable")
        result = 5
        if verbosity>1:
            print()
            print("-"*30)
            print(err)
            print("-"*30)

    elif 'Connection timed out' in err:
        result = 4

    elif 'The server\'s host key is not cached in the registry' in err:
        result = 3
        if verbosity>1:
            print()
            print("SSH key Err".center(30,"-"))
            print(err)
            print("-"*30)

    elif 'Access denied' in err:
        result = 2
        if verbosity>2:
            print()
            print("Denied".center(30,"-"))
            print(err)
            print("-"*30)
    else:
        result = 6
        if verbosity>0: print("ConnCrash")
        print("Oups".center(30,"-"))
        print(err)
        print("-"*30)
else:
    if verbosity>0: print("Conn ok")
    result = 1

del out,err
return result

当然,这只是检查连接(并接受ssh键)
这里有一个在主机上运行脚本的代码(确切地说是密码修改).要做到这一点,你不能使用一行语法(即使它必须工作,它不会,我试过了)你必须通过一个脚本文件,并用plink推送它.

def ChangeMyPassword(IP_Addr,User,Old_Password,New_Password,verbosity=0):
#Some infos about returned code
# 0 = Error Or crash
# 1 = Change Ok
# 2 = Old Password Error
# 3 = SSH key trouble (shit append)
# 4 = Timeout
# 5 = Host Unreachable
# 6 = Connection Crash

out=""
err=""

try:
    path_script = "."+os.sep+"Script_chmdp_"+str(IP_Addr)+".sh"
    if os.path.exists(path_script):os.remove(path_script)
    fic_script = codecs.open(path_script,'w', encoding='utf8')
    fic_script.write('echo -e \"'+str(Old_Password)+'\\n'+str(New_Password)+'\\n'+str(New_Password)+'\" | passwd')
    fic_script.flush()
    fic_script.close()

    cmd = "plink -l "+str(User)+" -pw "+str(Old_Password)+" -batch "+str(IP_Addr)+ " "
    cmd += "-m "+path_script

    print(str(cmd))

    ssh=subprocess.Popen(cmd,shell=True, stdout=subprocess.PIPE, stderr=subprocess.PIPE,encoding='utf8')#,stdin=subprocess.PIPE)

    out,err = ssh.communicate()
    try:
        out = out.decode('utf-8')
    except AttributeError as inst:
        pass
    except Exception as inst:
        if verbosity>1:
            print("While decoding stdout: "+str(type(inst)))
    try:
        err = err.decode('utf-8')
    except AttributeError as inst:
        pass
    except Exception as inst:
       print("While decoding stderr: "+str(type(inst)))
    ssh.kill()
    del ssh
except Exception as inst:
    print("Crash"+str(inst))
    return 0

if 'all authentication tokens updated successfully' in out:
    if verbosity>0: print("Conn ok")
    result = 1
else:
    if verbosity>0: print("Something goes wrong, hope we do not crash your server :)")
    result = 0
del out,err
return result

所以现在你有两个功能来大规模地改变你的系统密码。

**额外好处:**一个获取/etc/passwd和/etc/shadow的函数。为什么?用于IT管理员的教育用途,比如“嘿,你他妈的在哪里都使用相同的密码,现在所有这些帐户都可以被暴力强迫。所以清理你的烂摊子吧

def GetPass(IP_Addr,User,Password,verbosity=0, force_plink=False):
#Some infos about returned code
# 0 = Error Or crash
# 1 = Connection ok
# 2 = No connect Password Error
# 3 = SSH key trouble (shit append)
# 4 = Timeout
# 5 = Host Unreachable
# 6 = Connection Crash

out=""
err=""
try:

    ssh=subprocess.Popen("echo "+str(Password)+" | plink -l "+str(User)+" -pw "+str(Password)+" -batch "+str(IP_Addr)+" sudo cat /etc/passwd;sudo cat /etc/shadow",shell=True, stdout=subprocess.PIPE, stderr=subprocess.PIPE,encoding='utf8')#,stdin=subprocess.PIPE)

    out,err = ssh.communicate()
    try:
        out = out.decode('utf-8')
    except AttributeError as inst:
        pass
    except Exception as inst:
        if verbosity>1:
            print("While decoding stdout: "+str(type(inst)))
    try:
        err = err.decode('utf-8')
    except AttributeError as inst:
        pass
    except Exception as inst:
       print("While decoding stderr: "+str(type(inst)))
    ssh.kill()
    del ssh
except Exception as inst:
    print("Crash"+str(inst))
    return 0

if len(err)>0:
    if 'Unable to open connection' in err or 'Host does not exist' in err:
        if verbosity>0: print("Unreachable")
        result = 5
        if verbosity>1:
            print()
            print("-"*30)
            print(err)
            print("-"*30)

    elif 'Connection timed out' in err:
        result = 4

    elif 'The server\'s host key is not cached in the registry' in err:
        result = 3
        if verbosity>1:
            print()
            print("SSH key Err".center(30,"-"))
            print(err)
            print("-"*30)

    elif 'Access denied' in err:
        result = 2
        if verbosity>2:
            print()
            print("Denied".center(30,"-"))
            print(err)
            print("-"*30)
    else:
        result = 6
        if verbosity>0: print("ConnCrash")
        print("Oups".center(30,"-"))
        print(err)
        print("-"*30)
else:
    if verbosity>0: print("Conn ok")
    result = out

del out,err
return result

更多备注:

如果你不使用shell=True,你就不会得到输出,它也不会工作,我不知道为什么。
我还尝试了异步通信来逐行发送命令,它不起作用。
我也尝试了ssh命令(是的,它现在存在于windows \o/上),但它不适合我的目的。
希望这有一天能帮助到别人,一周前它会帮我很大的忙:)

相关问题