how to use shell script in not_if condition

SASI picture SASI · Apr 29, 2015 · Viewed 9.2k times · Source

I want to use shell script output to validate the resource in guard condition.I am using below code still its not working.

bash "stampDisksuccess" do
                code <<-EOH
                whoami
        EOH
        user 'root'
        not_if {"`sudo sh /home/scripts/getStampedDisk.sh test`" == ''}
      end

Whether script(getStampedDisk.sh) returns blank message or some data, bash resource is getting executed. Where i am expecting it should not run when script returns blank data.

Correct me if anything missing.

Answer

Tensibai picture Tensibai · Apr 29, 2015

Let's dissect it:

not_if {"`sudo sh /home/scripts/getStampedDisk.sh test`" == ''}
  • Not_if ... quite obvious, it's the guard
  • { Block opening
  • "string opening
  • backticks opening
  • command
  • closing backticks and quote
  • == operator
  • '' constant empty string
  • } closing block

That's a lot of operations to test you have an empty string. The output from the backticks is not guaranteed to be really empty (it can have a newline for example) and then you compare it with an arbitrary empty string (not nil, it's a string with nothing). There's many way it can turn bad and it's quite hard to debug non printing characters.

However the shells have already an operator for this, it's -z for the usual bash.

Quoting bash documentation:

-z string
    True if the length of string is zero.

Another helper is $() to evaluate a command inside the script

Last one the [[ ]] construction to tell we're using an operator and not a command.

All together you end up with the command execution guard when expressed as string (Documentation on guards here)

not_if '[[ -z $(sudo sh /home/scripts/getStampedDisk.sh test) ]]' 

Quote from the guard documentation:

A guard attribute accepts either a string value or a Ruby block value:

  • A string is executed as a shell command. If the command returns 0, the guard is applied. If the command returns any other value, then the guard attribute is not applied.
  • A block is executed as Ruby code that must return either true or false. If the block returns true, the guard attribute is applied. If the block returns false, the guard attribute is not applied.

If you don't use ruby in the guard, don't use a block, you're just adding layers witch will get you in trouble, specifically when you try to compare non printable or empty strings and it's harder to debug, try to stick with standard shell commands if you need to call a command or a script, you can test it in console and be sure it is not the problem later.