在工作中有一个列出已完成任务的脚本。这是由其他人编写的,并通过网络托管。我的.bashrc中有一个别名,它调用了这个脚本,有很多标志等等,我想编写一个python脚本,每隔几分钟调用一次这样的别名,这样我就可以打开一个带有更新统计数据的shell。但是,subprocess.call("myAlias")
失败。我对python仍然相当新,我正在努力解决这个问题。
from subprocess import call
def callAlias():
call("myAlias")
callAlias()
我计划增加更多,但我在第一步遇到障碍。 :P
我会发布更多内容,但我需要注意很多敏感的机密内容。很抱歉模糊的代码和错误输出。
答案 0 :(得分:57)
如果您需要的别名在〜/ .bashrc中定义,那么它不会因为以下几个原因而运行:
1)你必须给出' shell'关键字arg:
subprocess.call('command', shell=True)
否则,您的给定命令用于查找可执行文件,而不是传递给shell,而它是扩展别名和函数之类的shell。
2)默认情况下,subprocess.call和朋友使用' / bin / sh'贝壳。如果这是您想要调用的Bash别名,则您需要告诉子进程使用bash而不是sh,使用'可执行文件'关键字arg:
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)
答案 1 :(得分:20)
您需要将shell
关键字设置为True:
call("myAlias", shell=True)
如果
shell
为True
,则将通过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'))
答案 2 :(得分: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/myalias
和chmod 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
。)
这是一个常见的常见问题解答。
答案 3 :(得分: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')