我想通过 ssh 执行一个简单的任务:从给定文件列表中返回所有不存在的文件。
我这样做的方法是将以下内容包装在 ssh 会话中:
for f in $(files); do stat $f > /dev/null ;done
stdout 重定向将忽略所有好文件,然后读取 stderr会给我一个所有未找到文件的列表。
我首先想到在subprocess.run(..., shell=True)
内将这个 bash 代码与 ssh 部分一起使用,但被劝阻这样做。相反,有人建议paramiko
。
我试图理解为什么以及何时原生 python 比子处理 bash 更好
- 不同操作系统的可计算性(对我来说不是问题,因为代码与 Ubuntu 紧密相连(
- 错误和异常处理 - 我确实得到了这个,并认为这很重要,尽管从子进程中捕获异常或退出代码也很容易
在我看来,原生 python 的缺点是需要涉及一些复杂的模块,例如 paramiko,而 bash 的 ssh 和 stat 在我看来更简单易用
是否有任何关于何时以及如何选择bash而不是python的指南?
这个问题主要是关于在ssh上使用命令,但与bash以简短简单的方式执行的任何其他命令和python包装有关。
这里实际上有三种选择:在进程中执行某些操作(如paramiko
(,直接运行ssh
(使用subprocess
(,以及使用shell运行ssh
(也使用subprocess
(。 作为一般规则,避免以编程方式运行 shell(而不是在交互式用户请求时运行(。
原因是它是一个面向人的界面(因此很容易将单词与空格和快捷方式分开,用于$HOME
和通配(,作为 API 的能力远远不足。 例如,考虑您的代码将如何检测缺少ssh
:paramiko
不会出现这种情况(只要安装了它(,subprocess
很明显,并且只是一个(模棱两可的(退出代码和来自 shell 的 stderr 消息。 还要考虑如何提供要运行的命令:它已经必须是适合 shell 的命令(由于 SSH 协议的限制(,但如果使用 shell调用ssh
,则必须对其进行编码(有时称为"双重转义"(,以便使本地 shell 的解释成为远程 shell 所需的多字命令。
到目前为止,paramiko
和subprocess
几乎是等价的。 作为更困难的情况,请考虑密钥验证失败的表现方式:paramiko
将失败描述为数据,而其他人将尝试与用户交互(可能存在,也可能不存在(。paramiko
还支持通过一个经过身份验证的连接打开多个通道;ssh
也可以这样做,但只能通过涉及Unix套接字文件的复杂ControlMaster
配置(在某些部署中可能没有任何好的位置(。 说到配置,您可能需要传递-F
以避免用户.ssh/config
的复杂性,如果它的设计没有考虑到这个自动化用例。
总之,库是为像您这样的用例而设计的,因此它们比从面向人类的命令组装您自己的界面更好也就不足为奇了,尤其是对于边缘情况(尽管这种手动组合非常有用! 如果安装像paramiko
这样的非标准依赖项是一种负担,至少直接使用subprocess
;切掉第二个外壳已经是一个很大的改进。