Skip Navigation

Using Batch Files to Run QEMU

QEMU is a fundamentally command-line application: its configuration is set by specifying arguments to a qemu-system- command for a given architecture. These arguments must be given each time the virtual machine is started, and the arguments will vary between virtual machines. Trying to remember exactly which arguments to use each time a VM needs to be started is not practical. On the Windows platform, we can use either a batch file or a PowerShell script to automate this process.

Page Contents

Batch Files

Batch files are an ancient (from the DOS days) way to automate a sequence of commands in a Windows environment. The syntax is a bit of a legacy, but the advantage of using a batch file is sheer simplicity. If one simply creates a text file with a .bat extension, Windows will recognize it immediately as a script, and the file can be run simply by double-clicking it in Explorer.

To create a batch file, create a plain text file but rename it with a .bat extension. You will need to enable the display of file extensions in Explorer to be able to change the extension.

A simple batch script to run an x86_64 virtual machine might look like this:

:: Comments begin with double-colons and are a good idea for documentation

qemu-system-x86_64 ^
    -name "Alpine Linux" ^
    -machine type=pc-q35-6.0 ^
    -accel tcg ^
    -cpu qemu64 ^
    -smp 2 ^
    -m 2048 ^
    -rtc base=utc ^
    -drive file="alpine.qcow2",if=virtio,format=qcow2 ^
    -boot order=cd,menu=on ^
    -display gtk ^
    -device virtio-vga ^
    -nic user,id=NAT,model=virtio-net-pci,mac=02:00:00:00:00:01 ^
    -device qemu-xhci ^
    -device usb-tablet ^
    -cdrom "alpine-virt-3.16.2-x86_64.iso"

echo QEMU has finished
pause

Looking at the above example, the qemu-system-x86_64 command is split over multiple lines for readability purposes. In order to make this command work on a single line when it gets executed, we must end the line with the caret (^) symbol, which is Shift+6 on a US keyboard.

At the end of the script, we have an “echo” statement to display a message that QEMU has exited. The “pause” command displays a “press any key to continue” message and waits. This way, we can see any error output from the qemu-system- command before the batch script execution window closes.

Alternative: PowerShell

The “modern” way to automate a command on Windows is to use PowerShell instead of batch files. However, this way is a bit more cumbersome. First, we have to enable PowerShell to run scripts on the local system by setting a security parameter. Run PowerShell as administrator, and issue the command:

Set-ExecutionPolicy RemoteSigned

Once PowerShell scripts are enabled, we can create a script by creating a text file and then renaming it with the .ps1 extension (the last character is the number 1). This example script does the same thing as the above batch file:

# Comments begin with the hash symbol (pound sign) in PowerShell

qemu-system-x86_64 `
    -name "Alpine Linux" `
    -machine type=pc-q35-6.0 `
    -accel tcg `
    -cpu qemu64 `
    -smp 2 `
    -m 2048 `
    -rtc base=utc `
    -drive file="alpine.qcow2",if=virtio,format=qcow2 `
    -boot order=cd,menu=on `
    -display gtk `
    -device virtio-vga `
    -nic user,id=NAT,model=virtio-net-pci,mac=02:00:00:00:00:01 `
    -device qemu-xhci `
    -device usb-tablet `
    -cdrom "alpine-virt-3.16.2-x86_64.iso"

echo "QEMU has finished"
echo "Press any key to exit"
$throwaway = $host.UI.RawUI.ReadKey("IncludeKeyDown,NoEcho")

In PowerShell, the line continuation character is the backtick, or `, which is the key above the Tab key on a typical US keyboard. Instead of the “pause” command, we have some PowerShell logic to wait for the user to press a key.

More Alternatives

If Windows Services for Linux are installed and active, it might be possible to use a Bourne shell script to run QEMU on Windows. This approach would more closely match most of my examples, which will be written in Bourne shell syntax. Of course, switching to a Linux host would be most convenient, since it would be easy to script and support the KVM accelerator.

Converting My Examples

Most of my example code will be in Bourne shell script. For example, the above example command would look like this:

#!/bin/sh
# Example in Bourne shell script

qemu-system-x86_64 \
    -name "Alpine Linux" \
    -machine type=pc-q35-6.0 \
    -accel tcg \
    -cpu qemu64 \
    -smp 2 \
    -m 2048 \
    -rtc base=utc \
    -drive file="alpine.qcow2",if=virtio,format=qcow2 \
    -boot order=cd,menu=on \
    -display gtk \
    -device virtio-vga \
    -nic user,id=NAT,model=virtio-net-pci,mac=02:00:00:00:00:01 \
    -device qemu-xhci \
    -device usb-tablet \
    -cdrom "alpine-virt-3.16.2-x86_64.iso"

echo "QEMU has finished. Press Enter to continue."
read throwaway

All you need to do when converting my examples to batch files or PowerShell scripts is to extract the qemu-system-ARCH (where ARCH is the architecture: x86_64 in this case) command from the Bourne shell example. Change the backslash (\) line continuation characters to ^ if using batch or ` if using PowerShell. The commands to notify that QEMU has finished and wait for a key press will stay the same as in the batch file and PowerShell examples above.

In some cases, it might also be necessary to change some paths inside my commands. In particular, references to “/usr/share/qemu/” should be changed to “C:\Program Files\qemu\share" wherever they occur in my examples.

Creative Commons License
This work is licensed under a Creative Commons Attribution-ShareAlike 4.0 International License.