【问题标题】:Bash commands in python [duplicate]python中的Bash命令[重复]
【发布时间】:2019-03-13 07:57:00
【问题描述】:

我正在 python 中运行一个代码,它计算目录中存在的文件数`

hadoop fs -count /user/a909983/sample_data/ | awk '{print $2}'

这在 linux 命令行中成功返回 0,因为目录是 empty。但是当我在 python 脚本中运行它时,它返回 1 .python中的代码行是:

directoryEmptyStatusCommand = subprocess.call(
["hadoop", "fs", "-count", "/user/a909983/sample_data/", "|", "awk '{print $2}'"])

我该如何纠正这个问题?或者我错过了什么?我也尝试过使用Popen,但结果是一样的。

【问题讨论】:

  • 如果你想使用shell的管道函数|,你需要使用shell=True作为选项运行。在这种情况下,您应该使用字符串,而不是命令列表。但是,最好将此命令拆分为两个子进程,分别为 hadoopawk,然后通过 Python 管道传输数据。
  • @pygo 如果你只是删除你的答案会更好,因为它无论如何都是重复的。

标签: python subprocess


【解决方案1】:

使用subprocess.Popen,不要使用管道|,因为它需要shell=True,存在安全风险。所以,使用subprocess.PIPE 并使用subprocess.check_output 而不使用管道这是正确的方法。

所以,你可以试试这样的:

command = subprocess.Popen(("hadoop", "fs", "-count", "/user/a909983/sample_data/") , stdout=subprocess.PIPE)
output = subprocess.check_output(("awk '{print $2}'"), stdin=command.stdout)

如果您想通过启用 shell=True 来尝试 Shell 命令:

cmd = "hadoop fs -count /user/a909983/sample_data/ | awk '{print $2}'"
command = subprocess.Popen(cmd,shell=True,stdout=subprocess.PIPE,stderr=subprocess.STDOUT)
output = command.communicate()[0]
print(output)

【讨论】:

  • 如果文件名来自一个变量(它可能是这样!),如果不将该变量从解析为代码的内容中带外移动,那么仅设置 shell=True 并不是一个好习惯。跨度>
  • 考虑subprocess.Popen(['''hadoop fs -count "$1" | awk '{print $2}' ''', '_', '/user/a909983/sample_data/'], shell=True),将您的数据——文件名——从代码中带出。
  • @CharlesDuffy,同意shell=True 确实不推荐,因为它打开了一个安全漏洞并使程序容易受到外壳注入,作为安全专家,你更了解它;-)
  • 嗯——我想说的是,如果作为cmd 的第一个元素传递的字符串是一个常量,那么一个可以安全地使用shell=True由人工仔细审核,并且所有可能变化的元素都被保留在带外(并且没有任何干预环境变量)。但是,是的,完全避免它确实是最好的方法。 :)
猜你喜欢
  • 2021-04-17
  • 1970-01-01
  • 1970-01-01
  • 2016-02-20
  • 2013-12-25
  • 2018-06-12
  • 1970-01-01
  • 2012-08-15
  • 2021-11-10
相关资源
最近更新 更多