在工作中有一个列出已完成任务的脚本。这是由其他人编写的,并通过网络托管。我的.bashrc中有一个别名,它调用了这个脚本,有很多标志等等,我想编写一个python脚本,每隔几分钟调用一次这样的别名,这样我就可以打开一个带有更新统计数据的shell。但是,subprocess.call("myAlias")
失败了。我对python仍然相当新,我正在努力解决这个问题。
from subprocess import call
def callAlias():
call("myAlias")
callAlias()
我计划增加更多,但我在第一步遇到障碍。 :P
我会发布更多,但有很多敏感的机密内容我必须要小心。对不起,代码模糊,缺少错误输出。
如果您需要的别名在〜/ .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)
您需要将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'))
建议的解决方案是不使用别名来定义非专门用于交互式使用的功能(即使这样,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
。)
这是一个常见的FAQ。
我稍微修改了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')