2

我有一个 bash 脚本,我想从 groovy 中执行它

some_shell_script.sh param1 "report_date=`some_function 0 \"%Y%m%d\"`"

该脚本从命令行成功运行,但是当我尝试从 Groovy 执行它时

def command = "some_shell_script.sh param1 "report_date=`some_function 0 \"%Y%m%d_%H%M%S\"`""
def sout = new StringBuffer()
def serr = new StringBuffer()
//tried to use here different shells /bin/sh /bin/bash bash 
ProcessBuilder pb = new ProcessBuilder(['sh', '-c',command])
Process proc = pb.start()
proc.consumeProcessOutput(sout, serr)

def status = proc.waitFor()

println 'sout: ' + sout
println 'serr: ' + serr

我有以下错误

serr: sh: some_function: command not found

同时

which some_function

返回函数定义,如

some_function ()
{
;some definition here
}

看起来当我从 groovy 运行外部脚本时,它会在没有父进程上下文的情况下启动不同的进程。我的意思是不存在父进程的函数定义。

任何人都知道如何应对这种情况?

4

4 回答 4

2

您应该用单引号替换命令定义中的双引号。

def command = 'some_shell_script.sh param1 "report_date=`some_function 0 "%Y%m%d_%H%M%S"`'

添加:

println command 

以确保您正在执行正确的命令。

还要打开一个新的 bash shell 并确保some_function已定义。

于 2012-08-07T18:27:36.727 回答
1

这似乎是一个路径问题。您可以将完整路径放入脚本并重试吗?

于 2012-08-07T17:41:21.320 回答
1

一定要查看@Reimeus 指出的那些引号。我对这些有些怀疑。

此外,当您以交互方式运行 bash 时,some_function()可以在其中定义或在其中任何一个来源的文件中定义。如果您运行脚本,则不会发生这种情况。(这有利于使脚本以可预测的方式运行 - 你不能让你的脚本依赖于人们的登录环境。)~/.bashrc/etc/bash.bashrc

如果是这种情况,请将 some_function() 移动到另一个文件,并将其完整路径放在 BASH_ENV 变量中,以便 bash 在处理脚本时选择它。

男子重击:

   When  bash  is  started  non-interactively,  to run a shell script, for
   example, it looks for the variable BASH_ENV in the environment, expands
   its  value if it appears there, and uses the expanded value as the name
   of a file to read and execute.  Bash behaves as if the  following  com-
   mand were executed:
          if [ -n "$BASH_ENV" ]; then . "$BASH_ENV"; fi
   but  the  value of the PATH variable is not used to search for the file
   name.
   [Manual page bash(1) line 158]
于 2012-08-07T22:30:31.687 回答
0

免责声明:解决方案存在局限性,并且在部署之前应正确测试 shell 子脚本命令。但是,如果不需要多线程,例如函数立即提供一些简短的结果,那么我在此处实现了另一种选择。

例如,如果结果mycmd取决于设置的环境变量,~/.bashrc我可以显示它的结果:(作为 groovy-script/v1.8.1 尝试,是的,这是一个愚蠢的例子,它可能有风险!)

commands = '''source ~/.bashrc; cd ~/mytest; ./mycmd'''
"bash".execute().with{
  out << commands
  out << ';exit $?\n'
  waitFor()
  [ok:!exitValue(), out:in.text, err:err.text]
}.with{ println ok?out:err }
于 2012-08-08T20:51:58.557 回答