验证通过SSH文件是否存在

6 投票
6 回答
18008 浏览
提问于 2025-04-15 18:50

我正在尝试通过SSH来检查一个文件是否存在,使用的是pexpect这个库。我已经写好了大部分代码,但我需要获取一个值,以便判断这个文件是否存在。下面是我写的代码:

def VersionID():

        ssh_newkey = 'Are you sure you want to continue connecting'
        # my ssh command line
        p=pexpect.spawn('ssh service@10.10.0.0')

        i=p.expect([ssh_newkey,'password:',pexpect.EOF])
        if i==0:
            p.sendline('yes')
            i=p.expect([ssh_newkey,'password:',pexpect.EOF])
        if i==1:
            p.sendline("word")
            i=p.expect('service@main-:')
            p.sendline("cd /opt/ad/bin")
            i=p.expect('service@main-:')
            p.sendline('[ -f email_tidyup.sh ] && echo "File exists" || echo "File does not exists"')
            i=p.expect('File Exists')
            i=p.expect('service@main-:')
            assert True
        elif i==2:
            print "I either got key or connection timeout"
            assert False

        results = p.before # print out the result

VersionID()

谢谢大家的帮助。

6 个回答

2

我在运行程序的时候遇到了一些问题,每次运行程序输出的结果都不一样。比如说,我在找 /bin/bash,有时候会显示找到了,有时候又说找不到。

我找到了一段代码,通过在我期待的内容前面加上 \r\n,让它在处理文件和文件夹时能稳定工作。

# returns 0 if the file is missing and 1 if the file exists
# if ( hostFileExists( host, '/bin/sh/' ) == 1 ): echo "File exists!"
def hostFileExists( host, theFile ):
    host.sendline( '[ ! -e %r ] && echo NO || echo YES' % theFile )
    return host.expect( ["\r\nNO", "\r\nYES"] )

或者

# provide the host, the command, and the expectation
# command = '[ ! -e "/bin/sh" ] && echo NO || echo YES'
# expecting = ['NO', 'YES']
# i = hostExpect( host, command, expecting )
# if ( i == 1 ): echo "File exists!"
def hostExpect( host, command, expect ):
    newExpect = []
    for e in expect:
        newExpect.append( "\r\n%s" % e )
    host.sendline( command )
    return host.expect( newExpect )

希望这对你有帮助。

补充一下:我还发现,当通过ssh连接到Windows(cygwin)并尝试查看一个文件是否存在时,文件名必须加上引号。而在Linux上,这个是可选的。所以在 host.sendline 中的 %s 被改成了 %r

9

为什么不利用命令的返回代码通过SSH传回来的这个特点呢?

$ ssh victory 'test -f .bash_history'
$ echo $?
0
$ ssh victory 'test -f .csh_history'
$ echo $?
1
$ ssh hostdoesntexist 'test -f .csh_history'
ssh: Could not resolve hostname hostdoesntexist: Name or service not known
$ echo $?
255

这样的话,你只需要检查返回代码,就不用去捕捉输出内容了。

4

如果服务器支持sftp连接,我建议你不用费心去用pexpect,而是直接使用paramiko这个Python的SSH2模块:

import paramiko
transport=paramiko.Transport("10.10.0.0")
transport.connect(username="service",password="word")
sftp=paramiko.SFTPClient.from_transport(transport)
filestat=sftp.stat("/opt/ad/bin/email_tidyup.sh")

这段代码会打开一个SFTPClient连接到服务器,你可以用stat()这个方法来检查文件和文件夹是否存在。

如果文件不存在,sftp.stat会抛出一个IOError,提示'没有这个文件'。

如果服务器不支持sftp,你可以用下面的方法:

import paramiko
client=paramiko.SSHClient()
client.load_system_host_keys()
client.connect("10.10.0.0",username="service",password="word")
_,stdout,_=client.exec_command("[ -f /opt/ad/bin/email_tidyup.sh ] && echo OK")
assert stdout.read()

SSHClient.exec_command会返回三个东西(stdin, stdout, stderr)。在这里,我们只需要检查是否有输出。你也可以改变命令,或者查看stderr来找是否有错误信息。

撰写回答