35

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

from subprocess import call

def callAlias():
    call("myAlias")

callAlias()

我也计划添加更多,但我在第一步中遇到了障碍。:P

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

4

4 回答 4

84

更新:感谢这个黑客解决问题的支持,我很高兴它很有用。但一个更好的答案是 Tripleee 的,在页面的下方很远......

如果您需要的别名是在 ~/.bashrc 中定义的,那么由于以下几个原因它不会运行:

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

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

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

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

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

3) 但是,/bin/bash 除非作为“交互式”shell(使用“-i”)启动,否则不会获取 ~/.bashrc。不幸的是,您不能传递 executable='/bin/bash -i',因为它认为整个值是可执行文件的名称。因此,如果您的别名是在用户的正常交互式启动中定义的,例如在 .bashrc 中,那么您必须使用这种替代形式调用命令:

subprocess.call(['/bin/bash', '-i', '-c', command])
# i.e. shell=False (the default)
于 2014-08-02T22:03:01.123 回答
22

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

call("myAlias", shell=True)

相关文档

如果shellTrue,指定的命令将通过 shell 执行。如果您将 Python 主要用于它在大多数系统 shell 上提供的增强控制流,并且仍然希望访问其他 shell 功能,例如文件名通配符、shell 管道和环境变量扩展,这将很有用。

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

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

如果您不愿意在 python 脚本中使用完整的扩展命令,则必须使用$ENV环境变量让 shell 读取文件中定义的别名:

call("myAlias", shell=True, env=dict(ENV='/path/to/aliasfile'))
于 2012-08-21T18:28:36.633 回答
14

推荐的解决方案是不使用别名来定义并非专门用于交互式使用的功能(即使这样,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一样。)

这是一个常见的常见问题解答。

于 2018-03-10T12:46:01.283 回答
3

我稍微修改了乔纳森的理由 #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')
于 2015-10-15T23:13:10.603 回答