在Python中运行BASH内置命令?

20

有没有一种方法可以从Python运行BASH内置命令?

我尝试过:

subprocess.Popen(['bash','history'],shell=True, stdout=PIPE)

subprocess.Popen('history', shell=True, executable = "/bin/bash", stdout=subprocess.PIPE)

os.system('history')

还有其他很多变体形式。我想要运行history或者fc -ln


1
第二个看起来对我来说是正确的。它出了什么问题? - Devin Jeanpierre
运行一个bash进程并与之交互怎么样?这可能更简单,对于长时间运行的命令或与shell交互(例如在sudo后输入密码)非常有用。我认为pexpect可以满足这个需求。 - Ehtesh Choudhury
2个回答

19

我终于找到了一个可行的解决方案。

from subprocess import Popen, PIPE, STDOUT
shell_command = 'bash -i -c "history -r; history"'
event = Popen(shell_command, shell=True, stdin=PIPE, stdout=PIPE, 
    stderr=STDOUT)

output = event.communicate()

感谢大家的贡献。


这里的 shell=True 是多余的(它启动了不必要的 /bin/sh)。你可以将其删除,并像 @lesmana 的答案 中那样使用列表参数。 - jfs
3
不幸的是,'-r'选项不会获取自打开shell以来执行的任何当前命令。 '-r'选项会将/.bash_history文件中的所有内容加载到新打开的shell中。然而,/.bash_history文件通常只会在关闭shell时更新(除非您在.bashrc中使用PROMPT_COMMAND hack)。由于您无法关闭当前正在运行的shell(以使历史记录文件更新),因此您就没有办法了。我还没有找到解决方法。 - ishmael

17
subprocess.Popen(["bash", "-c", "type type"])

这会调用Bash,并告诉Bash运行字符串type type,该字符串在参数type上运行内置命令type

输出:type是一个shell内置命令

-c后面的部分必须是一个字符串。 这样做是不起作用的:["bash", "-c", "type", "type"]


这适用于 'type' 和 'alias',但不适用于 'history' 或 'fc -ln'。 - duanedesign
3
@duanedesign,它们确实能工作,但从子进程启动的bash会话已经禁用了其历史记录。这种行为是有意设计的。你需要想办法告诉bash启用它的历史记录。我记得有一次在某个Stack Exchange网站上看到了关于这个问题的提问。我再找到它后会回复你。 - Lesmana
1
@duanedesign http://unix.stackexchange.com/questions/5684/history-command-inside-bash-script/ - Lesmana
那里的描述建议只获取$HOME/.bash_history,但那似乎不是最新的。我认为它仅在shell退出时保存,或者也许所有的shell都是这样? - TextGeek
你的警告“**-c 后面必须是一个字符串**”非常重要。我第一次错过了它,在我的情况下,suprocess.run(['bash', '-c', 'command command-that-shouldnt-exist'], check=True) 正确地失败了,而 suprocess.run(['bash', '-c', 'command', 'command-that-shouldnt-exist'], check=True) 却可以正常工作。 - user3064538

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接