Python subprocess.call一个bash别名

问题描述 投票:17回答:4

在工作中有一个列出已完成任务的脚本。这是由其他人编写的,并通过网络托管。我的.bashrc中有一个别名,它调用了这个脚本,有很多标志等等,我想编写一个python脚本,每隔几分钟调用一次这样的别名,这样我就可以打开一个带有更新统计数据的shell。但是,subprocess.call("myAlias")失败了。我对python仍然相当新,我正在努力解决这个问题。

from subprocess import call

def callAlias():
    call("myAlias")

callAlias()

我计划增加更多,但我在第一步遇到障碍。 :P

我会发布更多,但有很多敏感的机密内容我必须要小心。对不起,代码模糊,缺少错误输出。

python bash subprocess
4个回答
57
投票

如果您需要的别名在〜/ .bashrc中定义,那么由于以下几个原因它将无法运行:

1)你必须给'shell'关键字arg:

subprocess.call('command', shell=True)

否则,您的给定命令用于查找可执行文件,而不是传递给shell,而shell是扩展别名和函数之类的东西。

2)默认情况下,subprocess.call和朋友使用'/ bin / sh'shell。如果这是您要调用的Bash别名,则需要使用'executable'关键字arg告诉子进程使用bash而不是sh:

subprocess.call('command', shell=True, executable='/bin/bash')

3)然而,/ bin / bash不会派生〜/ .bashrc,除非作为'交互'shell启动(带'-i')。不幸的是,你无法传递executable ='/ bin / bash -i',它认为整个值是可执行文件的名称。因此,如果您的别名是在用户的正常交互式启动中定义的,例如在.bashrc中,那么你将不得不使用这个替代形式调用命令:

subprocess.call(['/bin/bash', '-i', '-c', command])
# i.e. shell=False (the default)

20
投票

您需要将shell关键字设置为True:

call("myAlias", shell=True)

来自relevant documentation

如果shellTrue,则指定的命令将通过shell执行。如果您主要使用Python来提供大多数系统shell提供的增强控制流,并且仍然希望访问其他shell功能(如文件名通配符,shell管道和环境变量扩展),则此功能非常有用。

别名是shell特征(例如,它们由shell定义和解释)。

但是,shell(/ bin / sh)是非交互式执行的,因此不会读取.profile.bashrc文件,并且您的别名可能无法使用。

如果您不愿意将完整的扩展命令用于python脚本,则必须使用$ENV environment variable使shell读取其中定义了别名的文件:

call("myAlias", shell=True, env=dict(ENV='/path/to/aliasfile'))

3
投票

建议的解决方案是不使用别名来定义非专门用于交互式使用的功能(即使这样,shell功能在许多方面都是优越的)。

将别名重构为独立脚本,并像调用任何其他外部命令一样调用它。

更详细的,如果你有

alias myalias='for x in foo bar baz; do
    frobnicate "$x"; done'

你可以改进它,这样它就不会通过将它变成一个函数来污染你的全局命名空间

myalias () {
    local x
    for x in foo bar baz; do
        frobnicate "$x"
    done
}

或者只是将其保存为/usr/local/bin/myaliaschmod a+x /usr/local/bin/myalias,以使其可供所有人使用;

#!/bin/sh
for x in foo bar baz; do
    frobnicate "$x"
done

(这在子进程中运行,因此当脚本完成时,x将会消失;因此我们不需要将它设为local。)

(当然,如果frobnicate完全写成,也许你可以简化为frobnicate foo bar baz。)

这是一个常见的FAQ。


2
投票

我稍微修改了Jonathan的理由#2。制作一个包含的/usr/local/bin/interactive_bash文件

#!/bin/bash
/bin/bash -i "$@"

chmod +x它。然后从Python你可以打电话

subprocess.call('my_alias', shell=True, executable='/usr/local/bin/interactive_bash')
© www.soinside.com 2019 - 2024. All rights reserved.