【问题标题】:Using Popen in Python in ssh to Run "ls -lh INPUTS" Bash Commands在 ssh 中使用 Python 中的 Popen 运行“ls -lh INPUTS”Bash 命令
【发布时间】:2018-04-23 06:44:11
【问题描述】:

INPUTS 是我为可能的输入文件目录的绝对路径提供的变量。我想在通过我的管道之前检查他们的状态。所以我尝试了:

import subprocess
import argparse

INPUTS = '/home/username/WinterResearch/Inputs'
status = subprocess.Popen(['ls', '-lh', INPUTS], shell=True, stdout=subprocess.PIPE)
stdout = status.communicate()
status.stdout.close()

常用的我也试过了

from shlx import split
import subprocess
import argparse

cmd = 'ls -lh INPUTS'
status = subprocess.Popen(cmd.split(), shell=True, stdout=subprocess.PIPE)

cmd = "ls -lh 'INPUTS'"

我没有收到错误代码。该过程根本不会向终端窗口输出任何内容。我不确定为什么 python 脚本只是跳过这个而不是说明有错误。当我包含 close_fds=True 指出 int 不能使用通信()时,我确实收到了一个错误。那么如何使用 subprocess.Popen() 接收来自 ls -lh INPUTS 等效项的输出?

【问题讨论】:

  • 考虑到斜杠,您在 macOS X 或某些 Linux 上。然后将您的 INPUT 变量更改为 ~/WinterResearch/Inputs 或放置以 /Users 开头的绝对路径...或检查您的预期命令是否在终端中正确执行。
  • 我尝试了~/WinterResearch/Inputs,错误是有"No such file or directory found"ls -lh /home/username/WinterResearch/Inputs 在终端上很好。
  • shell=True 是你的问题。
  • os.path.expanduser() 将修复~/WinterResearch/Inputs 字符串,将~ 替换为用户的实际主目录(就像shell 所做的那样)。
  • 顺便说一句,您为什么期望这段代码可以向终端写入任何内容?您的内容被捕获到管道中——因为您要求它被捕获——其输出被转储到名为 stdout 的变量中。

标签: python bash subprocess popen


【解决方案1】:

您看不到任何输出,因为您没有打印到控制台标准输出——它被保存到一个变量中(名为“stdout”)。无论如何,Popen 对这项任务来说太过分了,因为您没有将命令传递给另一个。为此,check_output 应该可以与子进程一起正常工作:

import subprocess
subprocess.check_output("ls -lh {0}".format(INPUTS), shell=True)

subprocess.check_output(args, *, stdin=None, stderr=None, shell=False, Universal_newlines=False)
运行带参数的命令并返回它的 输出为字节串。

安全风险较小的方法: (see warnings plastered throughout this page)

EDIT:使用communicate() 可以避免潜在的 shell=True安全风险:

output = subprocess.Popen(["ls", "-lh", INPUTS]).communicate()[0]
print(output)

【讨论】:

  • 如果您的目录名称中包含空格,这将表现得非常糟糕。如果它包含$(rm -rf ~); rm -rf ~,那就更糟了。删除 shell=True 并保留 OP 的原始代码要安全得多。
  • 谢谢!当我把它放在 print() 语句中时,这很有效。
  • @CharlesDuffy:我提供了一种完全不使用shell 参数的替代方法,因此请看一下。 OP 也使用了shell=True;我不确定为什么ls -lh 会突然变成rm -rf ~。无论这种情况如何发生,文档都会多次强调潜在风险;如果我添加的新方法得到您的认可,请告诉我,谢谢!
  • @l'L'l,解释一下“为什么ls -lh会突然变成rm -rf ~,记住在POSIX-y平台上shell=True通过将 ['sh', '-c'] 添加到参数列表来工作。如果INPUTS='~/WinterResearch/inbox/$(rm -rf ~)',那么你得到['sh', '-c', 'ls -lh ~/WinterResearch/inbox/$(rm -rf ~)']。同样,如果INPUTS='; rm -rf ~',你会得到['sh', '-c', 'ls -lh; rm -rf ~']。清除?也就是说,这确实在编辑后得到了很大改进。
【解决方案2】:

从你的第一个 sn-p:

stdout = status.communicate()
status.stdout.close()

这里没有打印任何内容。您可能需要将其更改为以下(或您喜欢的形式/格式)

stdout = status.communicate()
print stdout
status.stdout.close()

【讨论】:

  • 这打印出了父目录 WinterResearch 的所有相对文件路径。
猜你喜欢
  • 2018-01-03
  • 1970-01-01
  • 2017-07-19
  • 1970-01-01
  • 2011-05-14
  • 2016-11-15
  • 2014-04-07
  • 1970-01-01
相关资源
最近更新 更多