【问题标题】:Automate ssh connection and execution of program with Python's Paramiko使用 Python 的 Paramiko 自动化 ssh 连接和程序执行
【发布时间】:2023-03-10 18:24:01
【问题描述】:

我想使用 python 自动执行特定任务。
除其他外,此任务包括通过 ssh 连接到远程服务器,以及运行可能会或可能不会要求用户输入的特定程序(称为 prog.out)。
经过一些研究和权衡我的选择后,我决定使用 Python 的 Paramiko(考虑到以下内容,这可能是错误的......)。

让我们从prog.out 不询问任何输入,而只是将一些信息打印到控制台的简单可能性开始:

int main(int argc, char* argv[]) {

        printf("Hey there, fella\n");
        printf("How are you this morning?\n");
        printf("See ya...\n");

        return 0;
}

编译为:prog.out,并位于 server_name 上,等待执行。
所以在那种情况下:

client = paramiko.SSHClient()
client.set_missing_host_key_policy(paramiko.AutoAddPolicy())
client.connect("server_name")
sin, sout, serr = client.exec_command('./prog.out')

for line in sout.readlines():
    print(line, end = '')

可以正常工作,并且会打印出prog.out 生成的任何内容。
但如果不是 prog.out 是:

int main(int argc, char* argv[]) {

        printf("Hey there, fella\n");
        printf("How are you this morning?\n");
        printf("please enter an integer...\n");
        int a;
        scanf("%d", &a);
        printf("you entered %d\n", a);
        printf("see ya...\n");

        return 0;
}

那么上面的python代码会在sout.readlines()阻塞(等待eof?)...
避免在sout.readlines() 中阻塞的方法是通过写入prog.out 的标准输入管道来为prog.out 提供输入:

client = paramiko.SSHClient()
client.set_missing_host_key_policy(paramiko.AutoAddPolicy())
client.connect("server_name")
sin, sout, serr = client.exec_command('./prog.out')

sin.write('55\n')

for line in sout.readlines():
    print(line, end = '')

但我无法提前知道prog.out 是否需要用户输入...
我正在寻找一种稳健的方式来运行prog.out,并让用户在必要时与它进行交互。 prog.out 需要输入时是否有一些迹象?

编辑

好的,我做了一点实验,发现只要prog.out没有退出,任何从通道读取()的尝试都会阻塞,但是prog.out只要没有退出就不能退出'未提供输入...
prog.out 已经发送的字节怎么还没读完呢?
我真的很想模拟给用户,就好像他或她直接与prog.out交互...

【问题讨论】:

    标签: python ssh paramiko


    【解决方案1】:

    有一个基于 Paramiko 构建的库,它可能更适合您的需求。

    我说的是python fabric(我没有任何关联)

    Fabric 是一个 Python (2.5-2.7) 库和命令行工具,用于 简化 SSH 在应用程序部署或系统中的使用 管理任务。

    它提供了一套基本的操作来执行本地或远程 shell 命令(通常或通过 sudo)和上传/下载文件, 以及提示运行用户等辅助功能 用于输入或中止执行。

    如果我正确理解了您的要求,您的代码可能看起来像这样。

    from fabric.api import run
    
    @task
    def run_a_out()
        run('echo "some input for a.out" | ./a.out')
    

    你会使用

    执行远程程序
        fab --hosts=someserver run_a_out
    

    如果您想动态控制将什么 get 传递到 a.out,您可以向 run_a_out() 添加一个参数并从命令行传递它。

    简而言之,Fabric 为 paramiko 提供了更高级别的 API,并且隐藏了大部分复杂性。

    【讨论】:

    • 当然是你的选择,但面料作者已经做了你想做的事
    • 你能详细说明一下这个库如何帮助我的特定需求吗?我阅读了它的文档,但不明白为什么这对我上面的问题有帮助......
    • 这是一个非常整洁的库。
    • 好的,我又调查了一些,你是对的。使用这个库非常容易......
    • 很高兴能帮上忙。
    最近更新 更多