【问题标题】:Is it possible to use functions defined in the shell from python?是否可以从 python 使用在 shell 中定义的函数?
【发布时间】:2016-04-06 00:38:34
【问题描述】:

例子:

#!/bin/bash

function my_test(){
    echo this is a test $1
}

my_test 1

python -c "from subprocess import check_output; print(check_output('my_test 2', shell=True))"

输出:

this is a test 1
/bin/sh: my_test: command not found
Traceback (most recent call last):
  File "<string>", line 1, in <module>
  File "/usr/lib/python3.5/subprocess.py", line 629, in check_output
    **kwargs).stdout
  File "/usr/lib/python3.5/subprocess.py", line 711, in run
    output=stdout, stderr=stderr)
subprocess.CalledProcessError: Command 'my_test 2' returned non-zero exit status 127

【问题讨论】:

  • 为什么不将my_test 函数保存在一个单独的shell 文件中并使用另一个shell 脚本调用运行python -c
  • /bin/sh 不支持 function 关键字。使用#!/bin/bash(或其他shell)作为你的shebang。
  • 请问您为什么要调用仅在该 shell 中定义的函数?

标签: python shell subprocess


【解决方案1】:

你需要导出shell函数,所以它会被子shell继承。

#!/bin/bash

function my_test(){
    echo this is a test $1
}

my_test 1

export -f my_test
python -c "from subprocess import check_output; print(check_output('my_test 2', shell=True))"

【讨论】:

  • 谢谢,这行得通,但我想知道是否有办法从 python 继承它而不接触 shell 脚本。我想这是不可能的吧?
  • 你能把这个函数放在另一个脚本里吗?然后你可以在尝试调用函数之前使用source scriptname
  • 不,不可能。
  • 这就是导出的意义,它是允许函数被继承的方式。
  • 如果您使用例如bash -a my_script 运行脚本,shell 会将所有名称和函数标记为导出,而无需修改脚本本身。
【解决方案2】:

导出一个并非所有 shell 都支持的函数,将代码放入 环境块。这是一个与语言无关的 text 块,在创建新进程时会从父进程复制到子进程。

这是ShellShock 的基础。

问题在于 Bash 和 Python 这两种语言完全不同,所以用一种语言编写的函数在没有翻译的情况下不能直接由另一种语言执行。子进程可以扫描环境块以查找函数,然后将其翻译并编译成自己的语言。工作量很大,很容易成为安全问题。

如果你只想使用 Bash->Python->Bash,那么从第一个 Bash 脚本中导出函数就可以了,因为它将被复制到每个环境块中。但是,您还在评论中声明您不希望第一个脚本导出它。

可以使用 python 将函数代码读入文本字符串,然后自己将其放入环境块中(这就是 export 在 shell 中所做的)。使用os.environ 字典。

实际使用的名称取决于您的 Bash 版本。 ShellShock 漏洞导致了很多变化。最好创建一个测试函数,导出它,然后使用env 找到它的全名。例如,在我的版本中,一个名为 gash 的简单函数在环境块中显示为 BASH_FUNC_gash%%

BASH_FUNC_gash%%=() {  echo 'Hollow world'
}

例如:

import os
import subprocess

fun_body="""() {  echo 'Hollow world'
}
"""
os.environ['BASH_FUNC_gash%%'] = fun_body

p1 = subprocess.Popen('./myscript.sh')

p1.wait()

脚本 (myscript.sh) 包含:

#!/bin/bash
gash

或者,您可以再次查看您的设计。混合语言总是有问题的,为什么不用 Python 写一大堆呢?

【讨论】:

    【解决方案3】:

    你可以使用 os 模块。

    import os
    os.system("anything what you would like to do in the shell")
    

    【讨论】:

    • 我看不出这有什么帮助 python -c "import os; print(os.system('my_test 2'))" 仍然输出 sh: my_test: command not found
    【解决方案4】:

    os 模块绝对是最简单的方法,而且不会在 shell 中造成太大的麻烦。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2014-09-18
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2016-09-15
      • 1970-01-01
      相关资源
      最近更新 更多