List vs string in cloud init runcmd

Viewed 1063

On the official example page, cloud config describes using runcmd

#cloud-config

# run commands
# default: none
# runcmd contains a list of either lists or a string
# each item will be executed in order at rc.local like level with
# output to the console
# - runcmd only runs during the first boot
# - if the item is a list, the items will be properly executed as if
#   passed to execve(3) (with the first arg as the command).
# - if the item is a string, it will be simply written to the file and
#   will be interpreted by 'sh'
#
# Note, that the list has to be proper yaml, so you have to quote
# any characters yaml would eat (':' can be problematic)
runcmd:
 - [ ls, -l, / ]
 - [ sh, -xc, "echo $(date) ': hello world!'" ]
 - [ sh, -c, echo "=========hello world'=========" ]
 - ls -l /root
 # Note: Don't write files to /tmp from cloud-init use /run/somedir instead.
 # Early boot environments can race systemd-tmpfiles-clean LP: #1707222.
 - mkdir /run/mydir
 - [ wget, "http://slashdot.org", -O, /run/mydir/index.html ]

Now my question is whether the list form is any different than the string form when passing a command

Is this

[sudo, ufw, --force, enable]

more correct than this?

sudo ufw --force enable
1 Answers

Neither is better, but the string form will be more straightforward. Everything under runcmd gets written out as a script to be executed later. If it's specified as a list, it will get quoted, but this shouldn't be a problem.

If you want to see how it gets written, you should be able to find the script generated at /var/lib/cloud/instance/scripts/runcmd. For your example I see:

root@me:~# cat /var/lib/cloud/instance/scripts/runcmd 
#!/bin/sh
'ls' '-l' '/'
'sh' '-xc' 'echo $(date) '\'': hello world!'\'''
'sh' '-c' 'echo "=========hello world'\''========="'
ls -l /root
mkdir /run/mydir
'wget' 'http://slashdot.org' '-O' '/run/mydir/index.html'
Related