代码之家  ›  专栏  ›  技术社区  ›  saikishor

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

  •  0
  • saikishor  · 技术社区  · 7 年前

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

    from subprocess import call
    
    def callAlias():
        call("myAlias")
    
    callAlias()
    

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

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

    0 回复  |  直到 8 年前
        1
  •  57
  •   Jonathan Hartley Zombie    12 年前

    如果您需要的别名是在~/.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)
    
        2
  •  20
  •   Community Mohan Dere    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'))
    
        3
  •  3
  •   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 同样如此。

    这是常见的常见问题。

        4
  •  2
  •   James    8 年前

    我稍微修改了乔纳森的理由,使之生效。做一个 /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')
    
    推荐文章