0

In gradle 7 I have created this method:

def shellCmd(String cmd) {
  exec {
    executable "sh"
    args "-c", cmd
  }
}

And this "pure" groovy version:

def shellCmd2(String cmd) {
  def process = cmd.execute()
  def output = new StringWriter(), error = new StringWriter()
  process.waitForProcessOutput(output, error)
}

Which I call from another method e.g.:

def myMethod() {
  shellCmd('ls -la')
}

I am now experimenting with getting it to work with multi-line (jenkins like) shell commands:

def myMethod() {
  
  def cmd = """
   for i in \$(ls -la); do
     if [[ \$i == 'settings.gradle' ]]; then
       echo "Found $i"
     fi
   done
  """

  shellCmd(cmd)

}

but it fails with:

  script '/home/user/samples/build.gradle': 47: Unexpected input: 'i' @ line 47, column 5.
     for i in $(ls -la); do
         ^
  
  1 error

Probably I am breaking all the rules here but any input?

Also tried most of the suggestions here:

What's wrong with Groovy multi-line String?

but no luck so far.

Also based on the suggestion below I have tried to use shellCmd2 method (I am leaning towards using a plain groovy method for this to make it easier to debug outside of gradle) with:

def myMethod() {

  def cmd = """
  for i in \$(ls -la); do
    if [ \$i = 'settings.gradle' ]; then
      echo "Found \$i"
    fi
  done
  """
  
  shellCmd2(cmd)
}

But that gives:

Caught: java.io.IOException: Cannot run program "for": error=2, No such file or directory
java.io.IOException: Cannot run program "for": error=2, No such file or directory

So seems the for keyword is now causing an issue.

u123
  • 15,603
  • 58
  • 186
  • 303
  • not sure it's possible to put multiline string as a command line. i believe jenkins is creating a temp.sh file and executes it. – daggett Jul 21 '21 at 14:54

1 Answers1

2

There is nothing wrong with your multiline string. I had to change three things to make your code work:

  1. Use single brackets [ and ]
  2. Use single equal sign (=)
  3. Escape the missing $i variable which was being interpreted as a Groovy variable.

You are using sh so you should only use POSIX compatible features.

Code:

def shellCmd(String cmd) {
  exec {
    executable "sh" // or use another shell like bash or zsh (less portable)
    args "-c", cmd
  }
}

def myMethod() {
    def cmd = """
        for i in \$(ls -la); do
            if [ \$i = 'settings.gradle' ]; then
            echo "Found \$i"
            fi
        done
    """
    shellCmd(cmd)
}

You can compare with double brackets with shells like zsh and bash.

Maicon Mauricio
  • 2,052
  • 1
  • 13
  • 29
  • That gives: `Cannot run program "for": error=2, No such file or directory` see my updated example. I assume this is because I now switched from sh to e.g. bash that I am using? – u123 Jul 22 '21 at 06:51