Building a script in Ubuntu (Linux) from existing DOS .cmd

Greetings,
I would be very grateful to anyone who is willing to help and knows there scripting and how to convert a DOS CMD script. :slight_smile:
In this posting I am also hoping to pass on information to anyone wanting to see a bit of VMware command line stuff.
I have made a script (batch file) that runs great in windows but I want to run it on Ubuntu (9.04 64-bit).
The problem is that dividual commands run independently on the command line, but in a script it doesn't. It seems like only the first command runs and the rest don't really work.
I want to know how best to create the script file and run it. I also want to learn on the way.
I don't have the time to learn more shell scripting right now and want to get the job done. I tried to get it to work but it all just behaves strangely.

I created this script to quickly deploy 3 VMware virtual machines (2 are clones from a base image and one gets unzipped). The script does fancy stuff like change the vmnets and adjust the memory and display names of the new VMs. The idea is to use them and then later redeploy them afresh.
I will use something like "/home/administrator/vmware/Virtual Machines" instead of "c:\Virtual Machines" and /usr/bin/vmware instead of vmware.exe

Here is the working DOS script and below some conversion that I have created

@echo off
cd\
cd "Virtual Machines\VMs\"
rmdir England /S /Q
mkdir England
c:
cd\
cd "Virtual Machines\VMs\"
cls
echo.
echo Creating VMs ....
echo.
echo Start time:
echo.
time /T
time /T > timenow.txt
rem ##### PC 1
"C:\Program Files\VMware\VMware Workstation\vmrun.exe" clone "C:\Virtual Machines\VMs\XPVM\Windows XP Pro.vmx" "C:\Virtual Machines\VMs\England\pc1\pc1.vmx" linked
rem the next line looks in the vmx file for clone.... value and replaces with pc1
cscript replace.vbs "C:\Virtual Machines\VMs\England\pc1\pc1.vmx" "Clone of Windows XP Pro" "pc1" 
echo.
echo PC done.
echo.
time /T
echo.
rem ##### pc2
"C:\Program Files\VMware\VMware Workstation\vmrun.exe" clone "C:\Virtual Machines\VMs\XPVM\Windows XP Pro.vmx" "C:\Virtual Machines\VMs\England\pc2\pc2.vmx" linked
cscript replace.vbs "C:\Virtual Machines\VMs\England\pc2\pc2.vmx" "Clone of Windows XP Pro" "pc2" 
cscript replace.vbs "C:\Virtual Machines\VMs\England\pc2\pc2.vmx" "VMnet2" "VMnet3" 
cscript replace.vbs "C:\Virtual Machines\VMs\England\pc2\pc2.vmx" "512" "256" 
echo.
echo pc2 done.
echo.
time /T
echo.
7z e "C:\Virtual Machines\VMs\pc3.7z" -o"C:\Virtual Machines\VMs\England\pc3\" 
"C:\Program Files\VMware\VMware Workstation\vmware-vdiskmanager.exe" -c -s 10240MB -a lsilogic -t 2 "C:\Virtual Machines\VMs\England\pc3\pc3-000001.vmdk" 
echo.
echo pc3 done.
echo.
time /T
echo.
sleep 5
cls
echo.
echo.
rem sleep 10
cls
echo.
echo  The time now is:
time /T
echo     Launching VMware Workstation Console now ....
echo.
echo.
echo Start time was:
type timenow.txt
echo.
time /T
echo.
echo.
echo.
rem cls
echo.
echo All done !
echo.
echo Job complete
echo.
echo.
sleep 30

===================================================
END

Conversions

This is the base image being used to make a linked clone, to later be called pc1
/usr/bin/vmrun -T ws clone "/home/administrator/vmware/Virtual Machines/CheckPoint/XPVM/Windows XP Pro.vmx" "/home/administrator/vmware/Virtual Machines/CheckPoint/England/pc1/pc1.vmx" linked

This replaced the vb script (cscript replace (above)) for replacing text values in the file:
rpl "Clone of Windows XP Pro" "pclondon" "/home/administrator/vmware/Virtual Machines/England/pc1/pc1.vmx"

Can you show us what you've tried? You may be halfway there already.

Sure (see below). Thanks for your response.
I just recreated most of it (I hadn't saved it all and deletes the last version of file)
The main problem is that the first line or two of the script works and then each one after that doesn't. But each line pasted into a terminal works fine. I just donw want to have to run it all manually each time or run a seperate script for each line!
So I just don't know how to get the script to run each line properly as an independent command.

I get errors like this:
"errors:
Creating VMs ....
Error: Invalid clone type: must be "full" or "linked"
" not found.home/administrator/vmware/Virtual Machines/VMs/England/pc1/pc1.vmx
PC 1."

 
#!/bin/bash
rmdir -p "/home/administrator/vmware/Virtual Machines/VMs/England"
mkdir "/home/administrator/vmware/Virtual Machines/VMs/England"
REM THESE FIRST 3 LINES SEEM TO WORK
echo Creating VMs ....
echo ##### PC 1
/usr/bin/vmrun -T ws clone "/home/administrator/vmware/Virtual Machines/VMs/XPVM/Windows XP Pro.vmx" "/home/administrator/vmware/Virtual Machines/VMs/England/pc1/pc1.vmx" linked
rpl "Clone of Windows XP Pro" "pc1" "/home/administrator/vmware/Virtual Machines/VMs/England/pc1/pc1.vmx"
echo 
echo PC 1 done.
REM THESE LINES DONT WORK IN THE SCRIPT BUT DO IN THE COMMAND LINE
read -p "Press any key to continue"
rem ##### PC 2
/usr/bin/vmrun -T ws clone "/home/administrator/vmware/Virtual Machines/VMs/XPVM/Windows XP Pro.vmx" "/home/administrator/vmware/Virtual Machines/VMs/England/pc2/pc2.vmx" linked
rpl "Clone of Windows XP Pro" "pc2" "/home/administrator/vmware/Virtual Machines/VMs/England/pc2/pc2.vmx"
rpl "VMnet2" "VMnet3" "/home/administrator/vmware/Virtual Machines/VMs/England/pc2/pc2.vmx"
rpl "512" "256" "/home/administrator/vmware/Virtual Machines/VMs/England/pc2/pc2.vmx"
echo 
REM THIS ONE IS UNZIPPING A VM AND THEN CREATING THE BLANK HARD DRIVE (PRE_ALLOCATED 10GB SPACE).
echo PC 2 done.
rem ##### PC 3
7z e "/home/administrator/vmware/Virtual Machines/VMs/pc3.7z" -o"/home/administrator/vmware/Virtual Machines/VMs/England/pc3/"
/usr/bin/vmware-vdiskmanager -c -s 10240MB -a lsilogic -t 2 "/home/administrator/vmware/Virtual Machines/VMs/England/pc3/pc3-000001.vmdk"
echo 

2 things:

  1. Shell comments don't start with REM, but with a hash '#', and can start anywhere on the line
  2. If you want to output literal hash characters, enclose them or the complete string with single or double quotes. Otherwise you'll start a comment.

The 7z command has '-o"text"', does it require a space?

You might try single quotes around the vmx files. From the first error it appears to be dropping a parameter. Further debugging could be done with...

vmEngland="/home/administrator/vmware/Virtual Machines/VMs/England"
rmdir -p "$vmEngland"
mkdir "$vmEngland"
vmxorig="/home/administrator/vmware/Virtual Machines/VMs/XPVM/Windows XP Pro.vmx"
vmxclone="$vmEngland/pc1/pc1.vmx"
if [ ! -e "$vmxorig" ]; then
  echo "Error: can't find \"$vmxorig\" "
  exit 1
fi
# Should we test that the clone exists before overwriting? 
# Probably not because the directory was removed and recreated.
if [ -e "$vmxclone" ]; then
  echo "Warning: clone exists \"$vmxclone\" "
  read -p "Continue to overwrite? [n] or y> " ans
  if [ "${ans:0:1}" != "y" ]; then
    exit 2
  fi
  rm "$vmxclone"
fi
# This should FAIL unless the clone command can create 'pc1' path for 'pc1/pc1.vmx'.
# Lets make the pc1 directory..
mkdir -p "$vmEngland/pc1/"
/usr/bin/vmrun -T ws clone "$vmxorig" "$vmxclone" linked
if [ ! -e "$vmxclone" ]; then
  echo "Error: can't find \"$vmxclone\" "
  exit 3
fi
rpl "Clone of Windows XP Pro" "pc1" "$vmxclone"
if [ ! -e "$vmxclone" ]; then
  echo "Error: can't find \"$vmxclone\" "
  exit 4
fi
# You'll probably need to create pc2/ and pc3/ directories also.
vmxclone="$vmEngland/pc2/pc2.vmx"
mkdir -p "$vmEngland/pc2/"
# Repeat above script. This could be a lot better as a loop.
# Check a single section to see if I found the problem and 
# then let me know if you want a loop.

You would also need to check what happened to the leading '/' on the path for pc1.vmx. Did the 'rpl' script remove it?

Thanks for that. I need some time to obsorb and test it but to answer your question in the meantime:
The 7z command and switches are formatted correctly. It is just like that with 7z.
I am trying to read this stuff: UNIX / Linux Bourne / Bash Shell Scripting Tutorial [ steve-parker.org ] and I see there is plenty to read here too.
Will respond later.
Thanks for the REM comment/reply. I know this much now from steve-parker and you. I appreciate the feedback and lessons.

Is gedit safe to put these scripts together? No nasty hidden characters or formatting...?

Yes.

OK. Thanks m1xram, from what you gave me I have done some work to come up with the script below.
PC3 isn't a clone job but an unzip job followed by a 'create it's vmdisk' job (using vmware-vdiskmanager)

  1. This script isn't 100% yet and I appreciate your experienced eyes and advice here.
    It works until the second last instruction and that is 7z, which doesn't quite work. It unzips the files to a new subdierctory in the target directory (names %0D). It works when run manually line by line... Please see my hashed out notes at the bottom.
    I left out the error checking and messages, mostly because I don't understand them yet (I can interperte though) and also because the files will always be there. I will make sure of that.
  2. Once the 7z is fixed (I hope it can be) I want to make another two countries, Ecuador and Chile (with PCs 4, 5 and 6 and PCs 7, 8 and 9 in them) and I planned on having similar scripts for them but can it be done in one, with the "read" command for example or some other fancy way?
    Thanks,
    D
#!/bin/bash
country=England
echo $country
vmEngland="/home/administrator/vmware/Virtual Machines/VMs/England"
echo $vmEngland
rm -rf "$vmEngland"
echo "==========================================================="
echo "Clean up done"
echo "==========================================================="
read -p "Press Enter to continue . . ."
mkdir "$vmEngland"
echo "==========================================================="
echo "Country directory created."
echo "==========================================================="
read -p "Press Enter to continue . . ."
vmxorig="/home/administrator/vmware/Virtual Machines/VMs/XPVM/Windows XP Pro.vmx"
# original line -- vmxclone="$vmEngland/pc1/pc1.vmx"
vmxpc1="$vmEngland/pc1/pc1.vmx"
vmxpc2="$vmEngland/pc2/pc2.vmx"
vmxpc3="$vmEngland/pc3/pc3.vmx"
pc37z="/var/VMs/7z/pc3.7z"
pc3dir="/home/administrator/vmware/Virtual Machines/VMs/England/pc3/"
pc3disk="/home/administrator/vmware/Virtual Machines/VMs/England/pc3/pc3-000001.vmdk"
# not working --> for i in $vmxpc1 $vmxpc2
# not working ---> /usr/bin/vmrun -T ws clone "$vmxorig" "$i" linked
echo "==========================================================="
echo "Creating PC1 and PC2 (as clones)...."
echo "==========================================================="
/usr/bin/vmrun -T ws clone "$vmxorig" "$vmxpc1" linked
/usr/bin/vmrun -T ws clone "$vmxorig" "$vmxpc2" linked
echo 
echo "==========================================================="
echo "Renaming clones ...."
echo "==========================================================="
rpl "Clone of Windows XP Pro" "$pc1" "$vmxpc1"
rpl "Clone of Windows XP Pro" "$pc2" "$vmxpc2"
echo 
echo "==========================================================="
echo "PCs Done. Going ahead with PC 3 now ..."
echo "==========================================================="
echo
read -p "Press Enter to continue . . ." 
clear
echo "==========================================================="
echo "Unzipping PC 3 and creating Hard drive ...."
echo "==========================================================="
# THIS NEXT LINE WORKS IN THE COMMAND LINE WHEN PASTED IN BUT NOT PROPERLY WHEN
# IN THIS SCRIPT. IT CREATES A DIRECTORY NAMED "%0D" IN $pc3dr AND UNZIPS TO THERE.
7z e "$pc37z" -o"$pc3dir"

/usr/bin/vmware-vdiskmanager -c -s 10240MB -a lsilogic -t 0 "$pc3disk" # Use -t 2 for preallocated 10GB drive (takes 10GB free disk space).

echo "==========================================================="
echo "PC3 Done (including creating 10GB CSI Virtual Hard drive)."
echo "==========================================================="

# exit

---------- Post updated 16-12-09 at 09:01 AM ---------- Previous update was 15-12-09 at 08:26 PM ----------

I have got a temporary working fix for the problem I had. It is not graceful but makes the script 100% functional for what I want.
I would like to understand what is causing the problem with 7z though, if anyone knows?
I am also keen to learn how to improve this and also how I could make the other 2 countries scripts, if I should be making two more country scripts (Ecuador and Chile as mentioned above) like this of if it can all be done in this one.
The fix:

# First line kind of works
# Line two and three clean up after the first line
7z e "$pc37z" -o"$pc3dir"
mv "$pc3dir/%0D/*" "$pc3dir"
rm -rf "$pcdir%0D/"

Your "for" loop needs quotes.

for i in "$vmxpc1" "$vmxpc2"; do
  echo "Processing \"$i\"..."
done

As 7zip is a port to Linux maybe it does its own command line thing, taking the raw line and parsing it. Although this is unlikely you could try an "eval" command on it to force the issue. Some escaped quotes will also be required for the test. Let me know the result.

# TEST1: Do variable substitution before execution.
7z_cmd="7z e \"$pc37z\" -o\"$pc3dir\""
eval $7z_cmd

Another thing to try is quoting the parameter with the switch. This is a very unusual thing to do but might work with their parser.

# TEST2: Do variable substitution before execution.
7z_cmd="7z e \"$pc37z\" \"-o$pc3dir\""
eval $7z_cmd

I'm surprised that the "vmrun" command worked without creating directories for "$vmEngland/pcX". Does "vmrun" create the "pcX" part of the path?

One other note. /var hangs around forever. /tmp gets cleaned up periodically.

Thanks m1xram,

The vmrun command does indeed create the target directories, successfully. This is very handy.
I gave up on 7z and just used the unzip command (see second code window below). Of course I first had to unzip the .7z files and re-archive them as .zip for unzip to work.
I also had to create the directories to unzip to. 7zip does that automatically (but not succefully in this case!)

I used /var so that the files would be 'safe' and tucked away for whenever they are needed by the script.

I have searched but cannot find the answer to another question. Maybe you can help me. Can you launch a program (vmware console in this case) at the end of the script and allow the program to carry on running in the background, while the script exits gracefully? In the first code window below is the command to run last thing in the script.
I am also copying it to the desktop in the form of a seperate script file (to double click and click Run), which works.
I thought nohup would help with an & but vmware console doesn't stay open after the script exits...?

vmware "$vmxpc1"  "$vmxpc2"  "$vmxpc3"
pc3zip="/var/VMs/zip/pc3.zip"
pc3dir="/home/administrator/vmware/Virtual Machines/VMs/England/pc3/"
pc3disk="/home/administrator/vmware/Virtual Machines/VMs/England/pc3

mkdir "$pc3dir"
unzip "$pc3zipzip" -d "$pc3dir"

From what I understand you can do something like...

( ( cmd & ) & )

A Linux Guru could explain better why this works but I believe the run-in-background fork that '&' creates detaches from the parent. So I think the first '&' detaches from the process that created it and then next one detaches from the login process. I've tried it without the second set of ()s and it doesn't work so all ()s are required. Some commands know how to do this on their own like dameons.

Usually for scripts where you intend to stay logged in, one '&' is sufficient.

Another way to do this, and I think your goal is to eventually run this from cron periodically, is to spawn off the parallel jobs and wait for them to complete. The simpliest way is...

backup node1 &
backup node2 &
wait
echo "TIMESTAMP: Backup jobs complete."

'wait' waits for all the subprocesses to complete. This might create some confusion in your log files. I tried an experiment with detached processes...

#!/bin/bash

for x in $(seq 1 $1); do

    sleep $2
    echo "Proc $$, loop $x"
done

And ran them with...

./backuptest.sh 5 2 &
./backuptest.sh 10 1 &

...to see what the output looks like and it is a bit yucky. Add a easy to read prefix to your output to differentiate the jobs like "London" or "Manchester" and a timestamp instead of "Proc $$", the process id.

I remember doing a backup job some time ago. The one thing that bugged me was finding files. You create this gargantuan zip or tar gzip file and then want to restore a single file. Searching for that file in the archive is very time consuming unless you also create a directory listing with the archive. The directory listing is much smaller and faster to search. The last part of the zip job could be...

unzip -l $ARCHIVE > ${ARCHIVE/\.zip/.lst}