Py学习  »  Python

如何在python子进程中运行bash函数?[复制品]

saikishor • 6 年前 • 2421 次点击  

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

from subprocess import call

def callAlias():
    call("myAlias")

callAlias()

我也打算再加一点,但第一步就遇到了困难。P

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

Python社区是高质量的Python/Django开发社区
本文地址:http://www.python88.com/topic/44312
文章 [ 4 ]  |  最新文章 6 年前
James
Reply   •   1 楼
James    7 年前

我稍微修改了乔纳森的理由,使之生效。做一个 /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')
tripleee
Reply   •   2 楼
tripleee    8 年前

建议的解决方案是 使用 定义功能的别名 唯一地 对于交互使用(甚至在那时,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 同样如此。

这是常见的常见问题。

Community Fernando Kosh
Reply   •   3 楼
Community Fernando Kosh    9 年前

你需要设置 shell 关键字为true:

call("myAlias", shell=True)

relevant documentation :

如果 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'))
Jonathan Hartley
Reply   •   4 楼
Jonathan Hartley    11 年前

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

1)必须给“shell”关键字arg:

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

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

2)默认情况下,subprocess.call和friends使用'/bin/sh'外壳。如果这是要调用的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)