2012-06-21 232 views
2

我創建了一個expect腳本,當執行ssh時,它將執行一系列命令。僞代碼如下所示:在python中執行一個bash腳本

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

當從一個bash shell中(./myscript.txt $)執行的代碼執行罰款。我現在想要做的是在python文件中有一行,它與bash shell一樣運行腳本中的命令。僞代碼如下所示:

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

我都放在同一個目錄下的myscript.txt腳本文件作爲我的runmyscript.py文件,但是當我運行python的文件我收到錯誤:

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

我已閱讀documentation on the python.org site,但無濟於事。有沒有人有一個狡猾的解決方案從.py代碼執行bash腳本?

解決方案:此代碼適用於我。

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

使用此代碼來調用一個期望文件,SSH和從.py文件發送命令到服務器 - 如果你有內置到您的機器麻煩pycrypto /的paramiko有用的解決方案。

+1

嗯,你可以運行/ usr/bin中/期待myscript.txt,但你也可以寫全指望在python腳本(我建議) – MiJyn

+1

參見http://stackoverflow.com/問題/ 1233655 /什麼是最簡單的方法來使用ssh使用python – krlmlr

+0

lkjoel - 我將如何重寫我的python命令行myscript.txt?在python中編寫期望腳本肯定會更可取 - 這會使添加命令變得更加容易。 user946850的鏈接對於ssh部分很有用。 – gortron

回答

3

這裏是一個Python實現你期望的腳本:

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

Paramiko已經證明在我的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)