如何使用SSH在Python中远程执行脚本?

9
def execute(self,command):
            to_exec = self.transport.open_session()
            to_exec.exec_command(command)
            print 'Command executed'
connection.execute("install.sh")

当我检查远程系统时,发现脚本没有运行。有线索吗?


请提供更多的代码。上下文不够清晰。 - Lior Cohen
问题太模糊了,你使用的是哪个SSH包装器?出现了什么错误?你怎么知道“脚本没有运行”而不是“脚本运行但有错误”? - Lie Ryan
1
我不知道你为什么想这样做,但如果是为了系统管理,你可能会发现Fabric很有用。 - charlax
@charlax Fabric 是一个不错的建议。Fabric 的作者 Jeff Forcier 也是将 Paramiko 分支为 ssh 模块 的人。我的回答针对如何使用 Python 中的 ssh,但 Fabric 是更好的处理 @kevin 可能要解决的更一般问题的方法。 - aculich
3个回答

23
下面的代码可以实现你想要的功能,你可以根据自己的需要将其适应到execute函数中:
from paramiko import SSHClient
host="hostname"
user="username"
client = SSHClient()
client.load_system_host_keys()
client.connect(host, username=user)
stdin, stdout, stderr = client.exec_command('./install.sh')
print "stderr: ", stderr.readlines()
print "pwd: ", stdout.readlines()

注意,命令将默认运行在你的$HOME目录下,因此你需要将install.sh文件放在$PATH环境变量中,或者(更可能)你需要先使用cd命令切换到包含install.sh脚本的目录。

你可以通过以下命令检查默认路径:

stdin, stdout, stderr = client.exec_command('getconf PATH')
print "PATH: ", stdout.readlines()

然而,如果它不在您的路径中,您可以使用 cd 命令进入目录并像这样执行脚本:

stdin, stdout, stderr = client.exec_command('(cd /path/to/files; ./install.sh)')
print "stderr: ", stderr.readlines()
print "pwd: ", stdout.readlines()
如果脚本不在您的$PATH中,您需要使用./install.sh而不是install.sh,就像在命令行上一样。
如果您在执行以上操作后仍然遇到问题,可能还需要检查install.sh文件的权限。
stdin, stdout, stderr = client.exec_command('ls -la install.sh')
print "permissions: ", stdout.readlines()

3
需要澄清的是,这个 install.sh 脚本位于 SSH 服务器的 ssh 工作目录下。运行 Python 脚本的 SSH 客户端可能没有这个文件。是否有一种方法可以在不先复制文件的情况下,在服务器上运行客户端找到的 shell 脚本? - jxramos
@jxramos,关于在客户端而不是远程主机上运行的脚本,有任何更新吗? - pyofey

0
ssh = paramiko.client.SSHClient()
ssh.set_missing_host_key_policy(paramiko.client.AutoAddPolicy())
ssh.connect(hostname=host, username=username, password = password)
chan = ssh.invoke_shell()

def run_cmd(cmd):    
    print('='*30)
    print('[CMD]', cmd)
    chan.send(cmd + '\n')
    time.sleep(2)
    buff = ''
    while chan.recv_ready():
        print('Reading buffer')
        resp = chan.recv(9999)
        buff = resp.decode()
        print(resp.decode())

        if 'password' in buff:
            time.sleep(1)
            chan.send(password + '\n')        
        time.sleep(2)

    print('Command was successful: ' + cmd)

3
虽然这段代码可能回答了问题,但提供关于为什么和/或如何回答问题的额外背景信息可以提高其长期价值。 - rollstuhlfahrer
OP问的是如何在Python中远程执行脚本,而不是运行命令并打印出cmd和响应以进行调试。 - ProgrammingFreak

-3
subprocess.Popen('ssh thehost install.sh')

请查看 subprocess 模块。

请确保您已生成SSH密钥,否则当程序从cron执行时无法请求密码。 - Michał Šrajer
2
最好使用ssh模块,该模块旨在使SSH协议更加健壮且易于使用;没有充分的理由使用subprocess模块,因为它不仅更麻烦,而且您也无法依赖于从ssh返回的返回代码,因为如果它返回错误代码255,则无法确定这是否是您的远程脚本返回的内容,还是只是由于与远程脚本完全无关的错误而导致ssh返回代码。 - aculich

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接