【问题标题】:Can a python script execute a function inside a bash script?python 脚本可以在 bash 脚本中执行函数吗?
【发布时间】:2011-04-29 00:00:23
【问题描述】:

我有一个由第 3 方提供的 bash 脚本,它定义了一组函数。这是一个看起来像的模板

$ cat test.sh

#!/bin/bash

define go() {
    echo "hello"
}

我可以从 bash shell 执行以下操作来调用 go():

$ source test.sh
$ go
hello

有没有办法从 python 脚本访问相同的函数?我尝试了以下方法,但没有成功:

Python 2.6.6 (r266:84292, Sep 15 2010, 15:52:39) 
[GCC 4.4.5] on linux2
Type "help", "copyright", "credits" or "license" for more information.
>>> import subprocess
>>> subprocess.call("source test.sh")
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
  File "/usr/lib/python2.6/subprocess.py", line 470, in call
    return Popen(*popenargs, **kwargs).wait()
  File "/usr/lib/python2.6/subprocess.py", line 623, in __init__
    errread, errwrite)
  File "/usr/lib/python2.6/subprocess.py", line 1141, in _execute_child
    raise child_exception
OSError: [Errno 2] No such file or directory
>>> 

【问题讨论】:

  • bash 中有什么功能不能在Python 中复制?

标签: python bash


【解决方案1】:

是的,间接的。鉴于此 foo.sh

function go() { 
    echo "hi" 
}

试试这个:

>>> subprocess.Popen(['bash', '-c', '. foo.sh; go'])

输出:

hi

【讨论】:

    【解决方案2】:

    基于@samplebias 解决方案,但进行了一些对我有用的修改,

    所以我把它包装成函数,加载 bash 脚本文件,执行 bash 函数并返回输出

    def run_bash_function(library_path, function_name, params):
        params = shlex.split('"source %s; %s %s"' % (library_path, function_name, params))
        cmdline = ['bash', '-c'] + params
        p = subprocess.Popen(cmdline,
                             stdout=subprocess.PIPE, stderr=subprocess.PIPE)
        stdout, stderr = p.communicate()
        if p.returncode != 0:
            raise RuntimeError("'%s' failed, error code: '%s', stdout: '%s', stderr: '%s'" % (
                ' '.join(cmdline), p.returncode, stdout.rstrip(), stderr.rstrip()))
        return stdout.strip()  # This is the stdout from the shell command
    

    【讨论】:

    • 如果你正在编写一个函数来接受任意参数,那么你应该使用shlex.quote
    • @donkopotamus 正确,但我认为shlex.split 会在这种情况下完成工作,不是吗?即:shlex.split('"source %s; %s %s"' % (library_path, function_name, params))
    • 您的回答中没有提到shlex.split。在任何情况下,shlex.split 都不处理引用输入。重点如下……如果用函数名blah; rm -rf / 调用你的函数会做什么? (我不建议你测试它......)
    • @donkopotamus,但仍然没有明白你的意思。如果用户决定调用rm -fr / 而不是调用实际函数,那是他自己的错。顺便说一句,“blah”不是函数名,而是加载函数的库路径
    • 是的,这是一个错字...我知道blah 是一个文件名。文件名可以是任何东西......它们应该在传递给 shell 之前被引用,以防它们包含对 shell 有意义的字符。这些字符可以像空格一样简单,也可以像分号一样愚蠢。
    【解决方案3】:

    不,该函数仅在该 bash 脚本中可用。

    您可以做的是通过检查参数来调整 bash 脚本,并在给出特定参数时执行函数。

    例如

    # $1 is the first argument
    
    case $1 in
     "go" )
           go
           ;;
     "otherfunc" )
           otherfunc
           ;;
     * )
           echo "Unknown function"
           ;;
    esac 
    

    然后你可以这样调用函数:

    subprocess.call("test.sh otherfunc")
    

    【讨论】:

      猜你喜欢
      • 2017-03-08
      • 2012-06-24
      • 2013-07-13
      • 2012-01-13
      • 1970-01-01
      • 2016-04-10
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多