2010-02-03 2 views
4

Я пытаюсь проверить, существует ли файл через SSH с использованием pexpect. У меня большая часть кода работает, но мне нужно поймать значение, чтобы я мог утверждать, существует ли файл. Код, который я сделал, приведен ниже:Проверка файла существует по ssh

def VersionID(): 

     ssh_newkey = 'Are you sure you want to continue connecting' 
     # my ssh command line 
     p=pexpect.spawn('ssh [email protected]') 

     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('[email protected]:') 
      p.sendline("cd /opt/ad/bin") 
      i=p.expect('[email protected]:') 
      p.sendline('[ -f email_tidyup.sh ] && echo "File exists" || echo "File does not exists"') 
      i=p.expect('File Exists') 
      i=p.expect('[email protected]:') 
      assert True 
     elif i==2: 
      print "I either got key or connection timeout" 
      assert False 

     results = p.before # print out the result 

VersionID() 

Спасибо за любую помощь.

+1

@chrissygormley - Я полагаю, вы не собираетесь использовать ssh-agent для хранения вашей кодовой фразы? Если бы вы это сделали, вы могли бы полностью избавиться от pexpect и просто сделать: ssh user @ host «command» –

+0

Я отправил свой ответ на этот вопрос ниже. Спасибо – chrissygormley

ответ

3

Если сервер принимает SFTP сессий, я бы не стал заморачиваться с pexpect, но вместо того, чтобы использовать SSH2 модуль paramiko для Python:

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, стандартный вывод, STDERR). Здесь мы просто проверяем наличие любого выхода. Вместо этого вы можете изменить команду или проверить stderr для любых сообщений об ошибках.

+0

@flight - Я получаю сообщение об ошибке: ---- paramiko.SSHException: Канал закрыт .-- - Все данные введены правильно, знаете ли вы, почему? Спасибо – chrissygormley

+0

@chrissygormley: «sftp [email protected]» работает для вас (т. Е. В оболочке)? – flight

+0

@flight - sftp работает на других машинах, но для камеры, с которой я вхожу, он отклоняется. Я рассмотрю, как решить эту проблему, и попробуйте приведенный выше код снова. Спасибо – chrissygormley

0

У меня нет опыта работы с pexpect, но, глядя на их веб-страницу, похоже, вы можете вызвать метод ожидания с несколькими значениями, и он возвращает индекс того, который он соответствует (это основано исключительно на мне, просто глядя в этом примере).

child.expect('password:') 
child.sendline (my_secret_password) 
# We expect any of these three patterns... 
i = child.expect (['Permission denied', 'Terminal type', '[#\$] ']) 
if i==0: 
    print 'Permission denied on host. Can't login' 
    child.kill(0) 
elif i==2: 
    print 'Login OK... need to send terminal type.' 
    child.sendline('vt100') 
    child.expect ('[#\$] ') 
elif i==3: 
    print 'Login OK.' 
    print 'Shell command prompt', child.after 

Фактически, вы уже используете эту функциональность в верхней части.

Итак, вы хотите, чтобы поймать, существует ли файл или нет? ...

Попробуйте это ...

 p.sendline('[ -f email_tidyup.sh ] && echo "File exists" || echo "File does not exists"') 
     file_exists = {0: True, 1: False}[p.expect(('File Exists', 'File does not exists'))] 
0

Когда вы, как пользователь типа что-то в SSH, оболочка будет вторят символы назад. Это происходит и сейчас.

Так делать:

p.sendline('test -f email_tidyup.sh && echo "File exists" || echo "File does not exist"') 

приведет к входу:

[email protected]: test -f email_tidy.sh && echo "File exists" || echo "File does not exists" 
File does not exist 

Выполнение:

i = p.expect(['File exists', 'File does not exist']) 

будет всегда приводить к I == 0, потому что " Файл существует "присутствует в первой строке, которая получена обратно.

Альтернативой где первоначально посыла линии, не имеет ожидаемый срок:

p.sendline('test -f email_tidyup.sh; echo result: $?') 
i = p.expect('result: 0', 'result: 1') 

Или еще как оригинал:

p.sendline('[ -f email_tidyup.sh ] && echo "File exists" || echo "File does not exist"') 
i = p.expect(['\nFile exists', '\nFile does not exist']) 
+0

@Johan Я попробовал решение, которое вы предоставили. Когда File Exists i == 0, но когда файл не выходит из i == 0. – chrissygormley

+0

Версия с квадратной скобкой ** точно совпадает с версией 'test'. –

+0

@Dennis Вы правы. Я удаляю эту часть из ответа. – Johan

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 

Таким образом, вы можете просто проверить код возврата, не требуя захвата вывода.

+1

(да, да, я написал в сценарии оболочки ... писать в Python оставлено как упражнение для читателя :)) – MikeyB

0

Я работал над решением, которое сделает меня. Код находится ниже:

def VersionID(): 

    ssh_newkey = 'Are you sure you want to continue connecting' 
    # my ssh command line 
    p=pexpect.spawn('ssh [email protected]') 

    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('[email protected]:') 
     p.sendline("cd /opt/ad/bin") 
     i=p.expect('[email protected]:') 
     p.sendline('[ -f email_tidyup.sh ] && echo "File exists" || echo "File does not exists"') 
     i=p.expect('[email protected]:') 
     assert True 
    elif i==2: 
     print "I either got key or connection timeout" 
     assert False 


     results = p.before # print out the result 
     print results 
     value = results.split('"')[8] 
     split_value = value.split('\r\n')[1:-1] 
     self.assertEquals(split_value, ['File exists']) 

Это извлекает значение из 'p' в строковом формате. Затем я разделил строку, чтобы получить строку «File Exists» в списке и сравнить ее с ответом, который я ищу. Если файл не существует, тест завершится с ошибкой.

Спасибо за помощь.

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'ing в Windows (cygwin) и пытается увидеть, существует ли файл, файл должен быть указан. В Linux это необязательно. Таким образом, %s в host.sendline был изменен на %r.

Смежные вопросы