A while back I noticed a tip posted somewhere on how to use the
find
utility to register a bunch a virtual machines at once. It was a really helpful post and illustrated some of the potential of the the Swiss Army-like
find
utility. But it overlooked one of the coolest features of
find
, the
-exec
option.
Using
-exec
, you can launch a command with
find
and pass each found file as a parameter to it, eliminating the need to run
vmware-cmd
in a
for
loop. Just place the command to run after the
-exec
parameter, and
find
will replace the string
{}
with the current file being processed:
[root@esx02 root]# find /vmfs/volumes/ -name '*.vmx' -exec vmware-cmd -s register {} \;
register(/vmfs/volumes/495e44a0-d41258bc-fac4-000c299206d0/lab-dc1/lab-dc1.vmx) = 1
register(/vmfs/volumes/495e44a0-d41258bc-fac4-000c299206d0/lab-ex1/lab-ex1.vmx) = 1
register(/vmfs/volumes/495e44a0-d41258bc-fac4-000c299206d0/uda14-esx/uda14-esx.vmx) = 1
|
The
-exec
option is often considered less efficient than using
xargs
, which will feed multiple parameters to a command at once rather than launching the command with a single argument like
-exec
does. But for use with a command like
vmware-cmd
, which only expects to have one
.vmx
file passed to it,
-exec
is perfect.
And
find
has another option,
-ok
, which does the same thing but will present a prompt before running the command on each
.vmx
file that is found. This can be really handy if you are registering or powering on a bunch of VMs but know that there are some you are going to want to skip:
[root@esx02 root]# find /vmfs/volumes/ -name '*.vmx' -ok vmware-cmd -s register {} \;
< vmware-cmd ... /vmfs/volumes/495e44a0-d41258bc-fac4-000c299206d0/lab-dc1/lab-dc1.vmx > ? y
register(/vmfs/volumes/495e44a0-d41258bc-fac4-000c299206d0/lab-dc1/lab-dc1.vmx) = 1
< vmware-cmd ... /vmfs/volumes/495e44a0-d41258bc-fac4-000c299206d0/lab-ex1/lab-ex1.vmx > ? y
register(/vmfs/volumes/495e44a0-d41258bc-fac4-000c299206d0/lab-ex1/lab-ex1.vmx) = 1
< vmware-cmd ... /vmfs/volumes/495e44a0-d41258bc-fac4-000c299206d0/uda14-esx/uda14-esx.vmx > ? n
|
find
rules
I've been in a couple of jams where find
really saved the day. Consider a situation where a standalone ESX server needs to be rebuilt, but the virtual machines are all on networked storage. Using find
afterwards to register and start the VMs makes the process trivial:
[root@esx02 root]# find /vmfs/volumes/ -name 'lab*.vmx' -exec vmware-cmd -s register {} \;
register(/vmfs/volumes/495e44a0-d41258bc-fac4-000c299206d0/lab-dc1/lab-dc1.vmx) = 1
register(/vmfs/volumes/495e44a0-d41258bc-fac4-000c299206d0/lab-ex1/lab-ex1.vmx) = 1
[root@esx02 root]# find /vmfs/volumes/ -name 'lab*.vmx' -exec vmware-cmd {} start \;
VMControl error -16: Virtual machine requires user input to continue
VMControl error -16: Virtual machine requires user input to continue
[root@esx02 root]# find /vmfs/volumes/ -name 'lab*.vmx' -print -exec vmware-cmd {} getstate \;
/vmfs/volumes/495e44a0-d41258bc-fac4-000c299206d0/lab-dc1/lab-dc1.vmx
getstate() = stuck
/vmfs/volumes/495e44a0-d41258bc-fac4-000c299206d0/lab-ex1/lab-ex1.vmx
getstate() = stuck
[root@esx02 root]# find /vmfs/volumes/ -name 'lab*.vmx' -print -exec vmware-cmd {} answer \;
/vmfs/volumes/495e44a0-d41258bc-fac4-000c299206d0/lab-dc1/lab-dc1.vmx
Question (id = 1) :msg.uuid.moved:The location of this virtual machine's configuration file has changed since it was last powered on.
If the virtual machine has been copied, you should create a new unique identifier (UUID). If it has been moved, you should keep its old identifier.
If you are not sure, create a new identifier.
What do you want to do?
0) Create
1) Keep
2) Always Create
3) Always Keep
4) Cancel
Select choice. Press enter for default ɘ> : 1
selected 1 : Keep
/vmfs/volumes/495e44a0-d41258bc-fac4-000c299206d0/lab-ex1/lab-ex1.vmx
Question (id = 1) :msg.uuid.moved:The location of this virtual machine's configuration file has changed since it was last powered on.
If the virtual machine has been copied, you should create a new unique identifier (UUID). If it has been moved, you should keep its old identifier.
If you are not sure, create a new identifier.
What do you want to do?
0) Create
1) Keep
2) Always Create
3) Always Keep
4) Cancel
Select choice. Press enter for default ɘ> : 1
selected 1 : Keep
|
You could even use the -ok
option to introduce a pause between the VM start-ups.
Shrimp tacos
The syntax for -exec
and -ok
can be a little difficult to remember. The ;
at the end of the command designates the end of the command find
should execute, and it has to be escaped like \;
so the shell doesn't interpret it.
I could never get the syntax right from memory until I associated it with shrimp tacos. The curly braces {}
are a corn tortilla, and I'm using a spatula to get my shrimp off the skillet, \;
It may be corny, but I never forget the syntax now!
You've got some excellent article Robert! I don't know if you noticed it or not but I've added you to the top 5 blog articles blog on the VMTN blog a couple of times already.
ReplyDeleteAnyway, keep up the great work... really enjoy reading this stuff!
Duncan
Yellow-Bricks.com
VMTN Blog
Duncan, thanks for the feedback! I noticed the feed had gotten picked up, but I hadn't seen the top 5 yet, so thanks for letting me know.
ReplyDeletePutting this stuff together has turned out to be way more work than I imagined, how you have time to put Yellow Bricks together in addition to all the other things you do, I'll never understand.
It's pretty reaffirming to hear you are enjoying the posts, so thanks for all the support!