How to include quoted string into a command

486 views
Skip to first unread message

Vadym Chepkov

unread,
Dec 13, 2015, 11:20:00 AM12/13/15
to Puppet Users
Hi,

I can't figure out how to include a single quoted string into a command, not matter what escaping I do.
Here is a simplified code :

$string = '\'a quoted string\''

exec { 'show string':
  command   => "echo \'I want to see ${string}\'",
  logoutput => true,
  path      => '/bin:/usr/bin',
}

Quotes don't show up, no matter what.
What do I do wrong?

$ puppet --version
3.6.2 (Puppet Enterprise 3.3.2)

Thanks,
Vadym

Johan De Wit

unread,
Dec 14, 2015, 4:56:01 AM12/14/15
to puppet...@googlegroups.com

Hi Vadim,


I used following:

(the $string uses <double><single> .... <single><double> quotes


[johan@zbook ~]$ cat test.pp


$string = "'a quoted string'"

exec { 'show string':
  command     => "echo \"I want to see ${string}\"",
  logoutput => true,
  path    => '/bin:/usr/bin',
}

[johan@zbook ~]$ puppet apply test.pp
Notice: Compiled catalog for zbook.koewacht.net in environment production in 0.06 seconds
Notice: /Stage[main]/Main/Exec[show string]/returns: I want to see 'a quoted string'
Notice: /Stage[main]/Main/Exec[show string]/returns: executed successfully
Notice: Applied catalog in 0.06 seconds





--
You received this message because you are subscribed to the Google Groups "Puppet Users" group.
To unsubscribe from this group and stop receiving emails from it, send an email to puppet-users...@googlegroups.com.
To view this discussion on the web visit https://groups.google.com/d/msgid/puppet-users/923ff9af-4321-4dee-a7b9-8002a1204042%40googlegroups.com.
For more options, visit https://groups.google.com/d/optout.

Thomas Hallgren

unread,
Dec 14, 2015, 5:55:34 AM12/14/15
to Puppet Users
Try this:


command => "echo \"I want to see ${string}\"",

i.e. send a double quoted string containing single quotes to the echo command rather than a single quoted string containing single quotes.

HTH,
- thomas

jcbollinger

unread,
Dec 14, 2015, 9:58:13 AM12/14/15
to Puppet Users


On Sunday, December 13, 2015 at 10:20:00 AM UTC-6, Vadym Chepkov wrote:
Hi,

I can't figure out how to include a single quoted string into a command, not matter what escaping I do.
Here is a simplified code :

$string = '\'a quoted string\''

exec { 'show string':
  command   => "echo \'I want to see ${string}\'",
  logoutput => true,
  path      => '/bin:/usr/bin',
}

Quotes don't show up, no matter what.
What do I do wrong?


The value of variable $string starts and ends with a single quote.  These are retained when you insert it into the Exec's 'command' paramater, so that there are then four single quotes in that parameter value (and no backslashes) in that parameter's value.  You are using the default provider for your Exec (probably the 'posix' provider), so this command string ends up being handed off to Ruby's Kernel.exec(), which under some circumstances hands it off to the shell, and under other circumstances performs its own expansions as if by the shell, and executes it directly.  So consider what the shell would do with the resulting command string:

echo 'I want to see 'a quoted string''

It is equivalent to this:

echo "I want to see a" quoted string

And of course, the output is just

I want to see a quoted string

There are several ways to go about what you are after but the bottom line is that you need to recognize that the strings will be processed at least twice: once by Puppet, and once by Kernel.exec(), in that order.  You need to insert appropriate escapes or quotes into your command for the latter, and then escape or quote the result for the former.
 
For example, you might do this:

$string = "\\'a quoted string\\'"

exec { 'show string':
  command  
=> "echo I want to see ${string}",
  logoutput
=> true,
  path      
=> '/bin:/usr/bin',
}

That escapes the backslashes so they get passed on to Kernel.exec() or the shell, and uses double quotes around the value of $string so that the single quotes within do not need to be escaped for Puppet.  There are other ways to wrangle the details, of course.


John

Vadym Chepkov

unread,
Dec 14, 2015, 11:51:51 AM12/14/15
to Puppet Users
I passed the single quotes bump, thank you, now I stuck on back ticks, puppet actually calls the script it and doesn't allow me to escape ` symbol

I need this for Solaris logadm.conf, which is a very unusual config file, since logadm modifies it during each run.
I am using the same technique PuppetLabs uses in solaris agent:

    # Have to use exec, since logadm adds a timestamp to the line when it runs
    $sig_command = "'kill -HUP `cat /var/run/syslog.pid`'"
    exec { "${logfile} log rotation":
      command => "/usr/bin/echo \"# ${facility} rotation rule\n${logfile} -C 5 -a ${sig_command} -p 1d\" >> /etc/logadm.conf",
      unless  => "/usr/bin/grep '^${logfile}' /etc/logadm.conf > /dev/null",
    }

I end up with
/var/log/local0.log -C 5 -a 'kill -HUP 28787' -p 1d


Thanks,
Vadym

jcbollinger

unread,
Dec 15, 2015, 10:10:18 AM12/15/15
to Puppet Users
The analysis goes along pretty much the same as before.  Given ...


    $sig_command = "'kill -HUP `cat /var/run/syslog.pid`'"

... the value of variable $sig_command is all the literal characters within the double quotes, from single quote to single quote, inclusive: 'kill -HUP `cat /var/run/syslog.pid`'. That gets interpolated into the double-quoted command string, so the literal text of the command will be something like:

/usr/bin/echo "# local0 rotation rule
local0.log -C 5 -a 'kill -HUP `cat /var/run/syslog.pid`' -p 1d"
>> /etc/logadm.conf

Kernel.exec() will execute that via the shell, on account of the metacharacters within.

Note that there is exactly one argument to the echo command, and it is double-quoted.  As a result, the shell (not Puppet) will perform command substitution, among others, on the contents before before handing the result to echo.  Within the double quotes, the internal single quotes are just plain data; they do not inhibit the command substitution.

The direct solution to this problem is also along the lines I gave you before: get your quoting and escaping correct for execution directly by the shell (and test it), then quote the result appropriately for Puppet.  I leave this one as an exercise for you.

On the other hand, if you can do without the leading comment, then what I now see you are trying to do would be well served by the file_line resource type provided by puppetlabs-stdlib. That module also provides a wide variety of functions that you may find useful, and you may have it already because many other modules depend on it. It wouldn't completely relieve you of having to think about quoting, but it would simplify matters by taking the shell out of consideration.


John

Vadym Chepkov

unread,
Dec 15, 2015, 1:20:30 PM12/15/15
to Puppet Users
Shell allows me to escape back-tick:

$ echo "/var/log/syslog -C 8 -a 'kill -HUP \`cat /var/run/syslog.pid\`'"
/var/log/syslog -C 8 -a 'kill -HUP `cat /var/run/syslog.pid`'

puppet does like them:

$string="/var/log/syslog -C 8 -a 'kill -HUP \`cat /var/run/syslog.pid\`'"

exec{'echo string':
  command   => "echo \" ${string} \" ",
  logoutput => true,
  path      => '/bin:/usr/bin',
}

Warning: Unrecognised escape sequence '\`' in file /home/vc7733/quotes.pp at line 1
Warning: Unrecognised escape sequence '\`' in file /home/vc7733/quotes.pp at line 1
Notice: Compiled catalog for pubdevx-dev601.bnaint.com in environment production in 0.36 seconds
Notice: /Stage[main]/Main/Exec[echo string]/returns:  /var/log/syslog -C 8 -a 'kill -HUP `cat /var/run/syslog.pid`' 

And as I said earlier, no, I can't use file_line

Thanks,
Vadym


Josh Cooper

unread,
Dec 15, 2015, 5:48:36 PM12/15/15
to puppet...@googlegroups.com
On Tue, Dec 15, 2015 at 10:20 AM, Vadym Chepkov <vche...@gmail.com> wrote:
Shell allows me to escape back-tick:

$ echo "/var/log/syslog -C 8 -a 'kill -HUP \`cat /var/run/syslog.pid\`'"
/var/log/syslog -C 8 -a 'kill -HUP `cat /var/run/syslog.pid`'

puppet does like them:

$string="/var/log/syslog -C 8 -a 'kill -HUP \`cat /var/run/syslog.pid\`'"

Puppet is interpreting \` as an escape sequence since it's in a double-quoted string, and reporting that it's an invalid escape sequence. I think you'll need to escape the backslash:

$string="/var/log/syslog -C 8 -a 'kill -HUP \\`cat /var/run/syslog.pid\\`'"
 

exec{'echo string':
  command   => "echo \" ${string} \" ",
  logoutput => true,
  path      => '/bin:/usr/bin',
}

Warning: Unrecognised escape sequence '\`' in file /home/vc7733/quotes.pp at line 1
Warning: Unrecognised escape sequence '\`' in file /home/vc7733/quotes.pp at line 1
Notice: Compiled catalog for pubdevx-dev601.bnaint.com in environment production in 0.36 seconds
Notice: /Stage[main]/Main/Exec[echo string]/returns:  /var/log/syslog -C 8 -a 'kill -HUP `cat /var/run/syslog.pid`' 

And as I said earlier, no, I can't use file_line

Thanks,
Vadym


--
You received this message because you are subscribed to the Google Groups "Puppet Users" group.
To unsubscribe from this group and stop receiving emails from it, send an email to puppet-users...@googlegroups.com.

For more options, visit https://groups.google.com/d/optout.

--
Josh Cooper
Developer, Puppet Labs

Vadym Chepkov

unread,
Dec 15, 2015, 7:05:07 PM12/15/15
to Puppet Users


On Tuesday, December 15, 2015 at 5:48:36 PM UTC-5, Josh Cooper wrote:

Puppet is interpreting \` as an escape sequence since it's in a double-quoted string, and reporting that it's an invalid escape sequence. I think you'll need to escape the backslash:

$string="/var/log/syslog -C 8 -a 'kill -HUP \\`cat /var/run/syslog.pid\\`'"
 

Bingo! Thank you very much
 
Reply all
Reply to author
Forward
0 new messages