从 python 中运行 bash 脚本

Posted

技术标签:

【中文标题】从 python 中运行 bash 脚本【英文标题】:Running bash script from within python 【发布时间】:2012-11-24 14:26:53 【问题描述】:

我对以下代码有疑问:

callBash.py:

import subprocess
print "start"
subprocess.call("sleep.sh")
print "end"

sleep.sh:

sleep 10

我希望在 10 秒后打印“结束”。 (我知道这是一个愚蠢的例子,我可以简单地在 python 中睡觉,但是这个简单的 sleep.sh 文件只是作为一个测试)

【问题讨论】:

我也试过了 "$!bin/bash; sleep 10; " 目前还不清楚这个问题试图问什么问题,但这个问题可能应该仍然存在,因为它已经积累了一个或多或少好的猜测作为答案的历史抓包。可能还会搜索您的具体错误,和/或阅读相关问题,例如***.com/questions/4256107/… 【参考方案1】:

使 sleep.sh 可执行并将shell=True 添加到参数列表中(如先前答案中所建议的那样)可以正常工作。根据搜索路径,您可能还需要添加./ 或其他一些适当的路径。 (即,将"sleep.sh" 更改为"./sleep.sh"。)

如果 bash 脚本的第一行是 shell 的路径,则不需要 shell=True 参数(在 Linux 等 Posix 系统下);例如,#!/bin/bash

【讨论】:

【参考方案2】:

如果sleep.sh 具有shebang #!/bin/sh 并且它具有适当的文件权限——运行chmod u+rx sleep.sh 以确保它在$PATH 中,那么您的代码应该可以正常工作:

import subprocess

rc = subprocess.call("sleep.sh")

如果脚本不在 PATH 中,则指定它的完整路径,例如,如果它在当前工作目录中:

from subprocess import call

rc = call("./sleep.sh")

如果脚本没有shebang,则需要指定shell=True

rc = call("./sleep.sh", shell=True)

如果脚本没有可执行权限并且您无法更改它,例如,通过运行os.chmod('sleep.sh', 0o755),那么您可以将脚本作为文本文件读取并将字符串传递给subprocess 模块:

with open('sleep.sh', 'rb') as file:
    script = file.read()
rc = call(script, shell=True)

【讨论】:

【参考方案3】:

其实你只需要加上shell=True参数:

subprocess.call("sleep.sh", shell=True)

但要小心 -

警告如果与不受信任的输入结合使用,使用 shell=True 调用系统 shell 可能会带来安全隐患。有关详细信息,请参阅常用参数下的警告。

source

【讨论】:

如果sleep.sh 不在PATH 中,它将不起作用。如果它在路径中并且它有正确的shebang,那么你就不需要shell=True。见my answer【参考方案4】:

如果有人在寻找使用参数调用脚本

import subprocess

val = subprocess.check_call("./script.sh '%s'" % arg, shell=True)

记得在传递之前将 args 转换为字符串,使用 str(arg)。

这可以用来传递任意数量的参数:

subprocess.check_call("./script.ksh %s %s %s" % (arg1, str(arg2), arg3), shell=True)

【讨论】:

我建议使用列表作为参数,例如subprocess.check_call(["./script.ksh", arg1, arg2, arg3], shell=True),这对我来说似乎更清晰,您不需要关心格式。【参考方案5】:

确保sleep.sh具有执行权限,并使用shell=True运行:

#!/usr/bin/python

import subprocess
print "start"
subprocess.call("./sleep.sh", shell=True)
print "end"

【讨论】:

所以我错过了 shell=True。您能否解释一下,为什么在 sh 脚本的第一行设置 #!bin/bash 是不够的? #!bin/bash 中的错误是缺少/#!/bin/bash 就像我在回答中提到的那样工作。【参考方案6】:

如果 chmod 不起作用,那么你也试试

import os
os.system('sh script.sh')
#you can also use bash instead of sh

由我测试,谢谢

【讨论】:

os.system 文档特别建议避免使用它以支持subprocess(这些天,subprocess.run())。如果您无法让subprocess 工作,那么您很可能也会遇到os.system() 的问题。【参考方案7】:

添加一个答案是因为我在询问如何从 python 运行 bash 脚本后被引导到这里。如果您的脚本接受参数,您会收到错误OSError: [Errno 2] file not found。例如,您的脚本接受了睡眠时间参数:subprocess.call("sleep.sh 10") 将不起作用,您必须将其作为数组传递:subprocess.call(["sleep.sh", 10])

【讨论】:

你必须了解the actual meaning of shell=True,但是是的,通常避免它是你最好的游戏。

以上是关于从 python 中运行 bash 脚本的主要内容,如果未能解决你的问题,请参考以下文章

Python:从命令行运行小型多行脚本

在 Python 中,我可以调用导入模块的 main() 吗?

Cron,以root身份执行bash脚本,但一部分(Python脚本)以用户身份执行

从 php 执行的 python 脚本给出错误

无法在 Windows/MSYS2 下从 bash 脚本运行 MATLAB

如何使用 crontab 运行运行 Python 脚本的 Bash 脚本