jts*_*287 19 python bash subprocess
在工作中有一个列出已完成任务的脚本.这是由其他人编写的,并通过网络托管.我的.bashrc中有一个别名,它调用了这个脚本,有很多标志等等,我想编写一个python脚本,每隔几分钟调用一次这样的别名,这样我就可以打开一个带有更新统计数据的shell.但是,subprocess.call("myAlias")失败了.我对python仍然相当新,我正在努力解决这个问题.
from subprocess import call
def callAlias():
call("myAlias")
callAlias()
Run Code Online (Sandbox Code Playgroud)
我计划增加更多,但我在第一步遇到障碍.:P
我会发布更多,但有很多敏感的机密内容我必须要小心.对不起,代码模糊,缺少错误输出.
Jon*_*ley 65
如果您需要的别名在〜/ .bashrc中定义,那么它将因以下几个原因而无法运行:
1)你必须给'shell'关键字arg:
subprocess.call('command', shell=True)
Run Code Online (Sandbox Code Playgroud)
否则,您的给定命令用于查找可执行文件,而不是传递给shell,而shell是扩展别名和函数之类的东西.
2)默认情况下,subprocess.call和朋友使用'/ bin/sh'shell.如果这是您要调用的Bash别名,则需要使用'executable'关键字arg告诉子进程使用bash而不是sh:
subprocess.call('command', shell=True, executable='/bin/bash')
Run Code Online (Sandbox Code Playgroud)
3)然而,/ bin/bash不会派生〜/ .bashrc,除非作为'交互'shell启动(带'-i').不幸的是,你无法传递executable ='/ bin/bash -i',它认为整个值是可执行文件的名称.因此,如果您的别名是在用户的正常交互式启动中定义的,例如在.bashrc中,那么您将必须使用以下替代形式来调用命令:
subprocess.call(['/bin/bash', '-i', '-c', command])
# i.e. shell=False (the default)
Run Code Online (Sandbox Code Playgroud)
Mar*_*ers 20
您需要将shell关键字设置为True:
call("myAlias", shell=True)
Run Code Online (Sandbox Code Playgroud)
从相关文件:
如果
shell是True,则将通过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'))
Run Code Online (Sandbox Code Playgroud)
我稍微修改了 Jonathan 的理由#2 以使这项工作可行。制作一个/usr/local/bin/interactive_bash包含以下内容的文件
#!/bin/bash
/bin/bash -i "$@"
Run Code Online (Sandbox Code Playgroud)
和chmod +x它。然后从Python你可以调用
subprocess.call('my_alias', shell=True, executable='/usr/local/bin/interactive_bash')
Run Code Online (Sandbox Code Playgroud)
The recommended solution is to not use an alias to define functionality which isn't exclusively for interactive use (and even then, shell functions are superior in a number of ways).
Refactor the alias into a standalone script and call it like any other external command.
In more detail, if you have
alias myalias='for x in foo bar baz; do
frobnicate "$x"; done'
Run Code Online (Sandbox Code Playgroud)
you can improve it so it doesn't pollute your global namespace by turning it into a function
myalias () {
local x
for x in foo bar baz; do
frobnicate "$x"
done
}
Run Code Online (Sandbox Code Playgroud)
or just save it as /usr/local/bin/myalias and chmod a+x /usr/local/bin/myalias to make it executable for everyone;
#!/bin/sh
for x in foo bar baz; do
frobnicate "$x"
done
Run Code Online (Sandbox Code Playgroud)
(This runs in a subprocess so x will be gone when the script finishes; so we don't need to make it local.)
(Of course, if frobnicate is at all competently written, maybe you can simplify to just frobnicate foo bar baz as well.)
This is a common FAQ.