2012-06-21 5 views
2

Я создал сценарий ожидания, который при запуске ssh на сервере и выполняет серию команд. Псевдокод выглядит следующим образом:Выполнение скрипта bash в python

#!/usr/bin/expect 
spawn ssh [email protected] 
expect "password:" 
send "mypassword\n"; 
send "./mycommand1\r" 
send "./mycommand2\r" 
interact 

При выполнении из Баш оболочки ($ ./myscript.txt) код выполняется нормально. Теперь я хотел бы сделать строку в файле python, которая запускает команды в скрипте так же, как это делает оболочка bash. Псевдокод выглядит следующим образом:

import subprocess 
def runmyscript(): 
    subprocess.call("myscript.txt", executable="expect", shell=True) 
def main(): 
    run = runmyscript(): 
if __name__ == '__main__': main() 

Я поместил файл myscript.txt сценария в том же каталоге, что мой файл runmyscript.py, но когда я запускаю файл питона я получаю сообщение об ошибке:

WindowsError: [Error 2] The system cannot find the file specified 

Я прочитал documentation on the python.org site, но безрезультатно. У кого-нибудь есть хитрое решение для выполнения сценариев bash изнутри .py кода?

РЕШЕНИЕ: этот код работает для меня.

child = subprocess.Popen(['bash', '-c', './myscript.txt'], stdout = subprocess.PIPE) 

Используется этот код, чтобы вызвать Expect файл SSH и посылать команды на сервер из .py файла - полезное решение, если у вас возникли проблемы при получении PyCrypto/paramiko построен на вашей машине.

+1

Ну, вы можете запустить/USR/BIN/ожидать myscript.txt, но вы можете написать весь ожидать скрипт в Python (который я рекомендую) – MiJyn

+1

Смотрите также http://stackoverflow.com/ Вопросы/1233655/what-is-the-simple-way-to-ssh-using-python – krlmlr

+0

lkjoel - как бы я переписал свои командные строки в myscript.txt из python? Написание сценария ожидания в python, безусловно, было бы предпочтительнее - упростило бы добавление команд. Ссылка пользователя946850 полезна для секции ssh. – gortron

ответ

3

Вот реализация питон вашего ожидать сценария:

import paramiko 

user = "user" 
pass = "pass" 
host = "host" 

client = paramiko.SSHClient() 
client.load_system_host_keys() 
client.set_missing_host_key_policy(paramiko.AutoAddPolicy()) 
client.connect(host, port=22, username=user, password=pass) 
client.exec_command("./mycommand1") 
client.exec_command("./mycommand2") 
client.close() 
+0

Парамико оказалось очень сложным для установки на моей сборке Python. Я буду продолжать бороться за решение подпроцесса и публиковать его здесь, когда найду его. – gortron

1

Вы можете использовать pexpect (http://www.noah.org/wiki/pexpect)

Вот пример функции, которая обрабатывает довольно много случаев, вы можете столкнуться при выполнении команд удаленно через ssh.

import pexpect 

## Cleanly handle a variety of scenarios that can occur when ssh or scp-ing to an ip:port 
# amongst them are: 
# 
# (1) key has not been setup 
# (2) key has changed since last time 
# (3) command was executed (check exit status and output) 
# 
# @param cmdLine The "scp" or "ssh" command-line 
# @param mtimeout The millisecond timeout to wait for the child process to return 
# @param log  The log to record events to if necessary 
def cleanlyHandleSecureCmd(cmdLine, mtimeout = None, log = None): 
    status = -1 
    output = None 

    if mtimeout == None: 
    mtimeout = 60 * 1000 

    if cmdLine != None and ('scp' in cmdLine or 'ssh' in cmdLine): 
    # Scenarios for ssh include: (1) key not setup (2) key changed (3) remote cmd was executed (check exit status) 
    scenarios = ['Are you sure you want to continue connecting', '@@@@@@@@@@@@', EOF] 
    child  = spawn(cmdLine, timeout = mtimeout) 
    scenario = child.expect(scenarios) 

    if scenario == 0: 
     # (1) key not setup ==> say 'yes' and allow child process to continue 
     child.sendline('yes') 

     scenario = child.expect(scenarios) 

    if scenario == 1: 
     if log != None: 
     # (2) key changed ==> warn the user in the log that this was encountered 
     log.write('WARNING (' + cmdLine + '): ssh command encountered man-in-the-middle scenario! Please investigate.') 

     lines = child.readlines() 
     scenario = child.expect([EOF]) 

     child.close() 
    else: 
     # (3) remote cmd was executed ==> check the exit status and log any errors 
     child.close() 

     status = child.exitstatus 
     output = child.before 
     output = sub('\r\n', '\n', output) # Do not be pedantic about end-of-line chars 
     output = sub('\n$', '', output) # Ignore any trailing newline that is present 

     if status == None: 
     status = child.status 

     if status != 0 and log != None: 
     log.error('Error executing command \'' + str(cmdLine) + '\' gave status of ' + str(status) + ' and output: ' + str(output)) 
    else: 
    if log != None: 
     log.error('Command-line must contain either ssh or scp: ' + str(cmdLine)) 

    return (status, output) 
Смежные вопросы