python ssh 脚本错误

1 投票
1 回答
1026 浏览
提问于 2025-04-17 15:17

先简单介绍一下情况,我正在写一个脚本,用来通过ssh连接到几个远程服务器,并把我的公钥复制到这些服务器上。因为我不能安装任何外部的python模块,所以我决定自己写一个定制的ssh客户端。简单来说,我所在的公司规定,如果不是标准的python库里的东西,就不能使用。

经过几周的寻找,我找到了一段我认为能解决我所有问题的脚本。我对它进行了修改,以满足我的需求,但现在出现了一个“找不到变量”的错误,我需要一些帮助来解决这个问题。

这是我找到的脚本:

#!/usr/bin/python

import pty, re, os, sys, stat, socket
from getpass import getpass

class ssherror(Exception):
    def __init__(self, value):
        self.value = value
    def __str__(self):
        return repr(self.value)

class sshclient:
    def __init__(self, ip, passwd, user, port):
        self.ip = ip
        self.passwd = passwd
        self.user = user
        self.port = port

    def runcmd(self, c):
        (pid, f) = pyt.fork()
        if pid == 0:
            os.execlp("ssh", "ssh", '-p %d' % self.port, self.user + '@' + self.ip, c)
        else:
        return (pid, f)

    def pushfile(self, src, dst):
        (pid, f) = pty.fork()
        if pid == 0:
            os.execlp("scp", "scp", '-P %d' % self.port, src, self.user + '@' + self.ip + ':' + dst)
        else:
            return (pid, f)

    def pushdir(self, src, dst):
        (pid, f) = pty.fork()
        if pid == 0:
            os.execlp("scp", "scp", '-P %d' % self.port, "-r", src, self.user + '@' + self.ip + ':' + dst)
        else:
            return (pid, f)

    def _read(self, f):
        x = ''
        try:
            x = os.read(f, 1024)
        except Exception, e:
            pass
        return x

    def connect(self, pid, f):
        output = ''
        got = self._read(f)
        m = re.search('authenticity of host', got)
        if m:
            os.write(f, 'yes\n')
            while True:
                got = self._read(f)
                m = re.search('Permanently added', got)
                if m:
                    break

            got = self._read(f)
        m = re.search('assword:', got)
        if m:
            os.write(f, self.passwd + '\n')
            tmp = self._read(f)
            tmp += self._read(f)
            m = re.search('Permission denied', tmp)
            if m:
                raise Exception('Invalid passwd')
            got = tmp
        while got and len(got) > 0:
            output += got
            got = self._read(f)
        os.waitpid(pid, 0)
        os.close(f)
        return output

    def cmd(self, c):
        (pid, f) = self.runcmd(c)
        return self.connect(pid, f)

    def push(self, src, dst):
        s = os.stat(src)
        if stat.S_ISDIR(s[stat.ST_MODE]):
            (pid, f) = self.pushdir(src, dst)
        else:
            (pid, f) = self.pushfile(src, dst)
        return self.connect(pid, f)



def sshconnect(ip, passwd, user, port=22):
    s = sshclient(ip, passwd, user, port)
    return s.connect(pid, f)


def sshpush(ip, passwd, src, dst, user, port=22):
    s = sshclient(ip, passwd, user, port)
    return s.push(src, dst)



passwd = getpass()
src = '/path/to/dir/being/copied'
dst = '/path/to/destination/directory'
user = os.getlogin()
port = portnum
hosts = ['host1', 'host2', 'host3']
for host in hosts:
    try:
        s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
    except socket.error, msg:
        print 'Failed to create socket. Error code: ' + str(msg[0]) + ' , Error message : ' + msg[1]
        sys.exit()

    print 'Socket Created'
    try:
        ip = socket.gethostbyname(host)
    except socket.gaierror:
        print 'Hostname could not be resolved. Exiting...'
        sys.exit()

    print 'Ip address of ' + host + ' is ' + ip
    sshconnect(ip, passwd, user, port)
    sshpush(ip, passwd, src, dst, user, port=22)
    print 'ssh directory copied to ' + host

我对它做了很多修改,但仍然遇到以下错误:

Traceback (most recent call last):
  File "ssh.py", line 129, in <module>
    sshconnect(ip, passwd, user, port)
  File "ssh.py", line 99, in sshconnect
    return s.connect(pid, f)
NameError: global name 'pid' is not defined

我知道我需要定义pid这个变量,但我现在不知道最好的方法是什么。如果有人能提供帮助、建议,或者给我点药吃,我将非常感激!!!

1 个回答

1

代码中的错误:

第20行:(pid, f) = pyt.fork()(应该是pty)

第24行:else:后面什么都没有

第93行:pidf在这个函数里没有定义——这就是你的问题所在。

第106行:portnum在这个范围内是未知的

他们是否允许你使用一个合适的集成开发环境(IDE)来检查代码?如果可以的话,换成那个吧。否则,如果你喜欢简单的vi,可以使用一个静态源检查工具

看了Paul Mikesell的代码片段,我觉得你在第91行的sshconnect函数其实不需要。直接调用sshclient.push就可以了,就像你在下一个函数(sshpush)里做的那样,它会自己连接。

撰写回答