Caution: This walkthrough guide contains outdated workflows using the Fuchsia SDK released in early 2023.
This guide walks through the basic workflows of building, running, debugging, and testing Fuchsia components using a Fuchsia SDK setup on Visual Studio Code (VS Code).
Complete the following sections:
Found an issue? Please let us know{:.external}.
This guide requires that your host machine meets the following criteria:
Clone the SDK samples repository on your host machine. This repository contains the Bazel-based Fuchsia SDK and sample components.
The tasks include:
ffx commands.Important: If you have a remote VS Code setup, you need to be on a VS Code window that is connected to your remote machine.
In VS Code, do the following:
Click Terminal > New Terminal.
In the terminal, change to your home directory:
cd
Clone the Fuchsia samples repository:
git clone https://fuchsia.googlesource.com/sdk-samples/getting-started fuchsia-getting-started --recurse-submodules
This git clone command creates a new directory named fuchsia-getting-started and clones the content of the SDK samples repository{:.external}.
Go to the new directory:
cd fuchsia-getting-started
Run the bootstrap script to install Bazel and other required dependencies:
scripts/bootstrap.sh
Download the SDK toolchain:
tools/bazel build @fuchsia_sdk//:fuchsia_toolchain_sdk
This command may take a few minutes to download all the tools and dependencies, such as Clang{:.external} and Fuchsia IDK (which includes the ffx tool).
When finished successfully, it prints output similar to the following:
$ tools/bazel build @fuchsia_sdk//:fuchsia_toolchain_sdk ... INFO: Elapsed time: 25.063s, Critical Path: 0.03s INFO: 1 process: 1 internal. INFO: Build completed successfully, 1 total action
To verify that you can use the ffx tool in your environment, run the following command:
tools/ffx sdk version
This command prints output similar to the following:
$ tools/ffx sdk version 11.20230109.3.1
At this point, you only need to confirm that you can run ffx commands without error.
Note: The output above shows the version 11.20230109.3.1, which indicates that this SDK was built and published on January 9, 2023.
The Fuchsia SDK samples repository includes a getting-started.code-workspace file. This configuration file sets up a VS Code workspace for the Fuchsia SDK and recommends Fuchsia-specific VS Code extensions.
In VS Code, do the following:
Click File > Open Workspace from File.
This opens the host machine's home directory.
Go to your fuchsia-getting-started directory.
Select the getting-started.code-workspace file.
Click Yes, I trust the authors.
A pop-up message appears at the bottom right corner of VS Code.
Click Install.
This installed the following extensions:
Note: You may see more pop-ups recommending other extensions while using VS Code. However, you can safely ignore them for the rest of this guide.
The layout diagram below shows the parts in VS Code that are relevant in this guide:
Start the Fuchsia emulator on the host machine. This guide uses an instance of the Fuchsia emulator as the target device for running and testing Fuchsia software. And to be able to supply new Fuchsia software to the target device, you also need to start the Fuchsia package server on the host machine.
The tasks include:
ffx commands can connect to the emulator instance.In VS Code, do the following:
Click Terminal > New Terminal.
In the terminal, download the latest Fuchsia Workstation prebuilt image for the emulator:
tools/ffx product-bundle get workstation_eng.qemu-x64 --force-repo --repository workstation-packages
This command may take a few minutes to download the image and product metadata.
Once the download is finished, the ffx product-bundle get command creates a local Fuchsia package repository named workstation-packages on your host machine. This package repository hosts additional system packages for this Workstation prebuilt image. Later in step 10 you’ll register this package repository to the emulator instance.
Stop all running emulator instances:
tools/ffx emu stop --all
Start a new Fuchsia emulator instance:
Note: If your Linux machine does not support KVM hardware virtualization, start the emulator with the following command instead: tools/ffx emu start workstation_eng.qemu-x64 --engine qemu --startup-timeout 720 --accel none --device qemu-x64-emu-min --headless
tools/ffx emu start workstation_eng.qemu-x64 --headless
This command starts a headless emulator instance running the Workstation prebuilt image.
When the instance is up and running, the command prints output similar to the following:
$ tools/ffx emu start workstation_eng.qemu-x64 --headless ... Logging to "/home/alice/.local/share/Fuchsia/ffx/emu/instances/fuchsia-emulator/emulator.log" Waiting for Fuchsia to start (up to 60 seconds)........... Emulator is ready.
Click the Not connected icon at the bottom of VS Code.
{: .screenshot}
This opens the Command Palette at the top of VS Code.
Click Set fuchsia-emulator as default in the Command Palette.
This sets fuchsia-emulator as the default target at the bottom of VS Code:
{: .screenshot}
In the terminal, to verify that you can establish an SSH connection to the emulator instance, run the following command:
tools/ffx target show
This command prints output similar to the following:
$ tools/ffx target show Target: Name: "fuchsia-emulator" SSH Address: "127.0.0.1:37787" Board: Name: "default-board" Revision: "1" Instruction set: "x64" Device: ... Build: Version: "11.20230109.3.1" Product: "workstation_eng" Board: "qemu-x64" Commit: "2023-01-09T20:03:45+00:00" Last Reboot: Graceful: "false" Reason: "Cold" ...
The example output above shows that the target device is running a workstation_eng.qemu-x64 prebuilt image.
Start the Fuchsia package server:
tools/ffx repository server start
This command prints output similar to the following:
$ tools/ffx repository server start ffx repository server is listening on [::]:8083
Check the list of Fuchsia package repositories available on your host machine:
tools/ffx repository list
This command prints output similar to the following:
$ tools/ffx repository list +-----------------------+------+-------------------------------------------------------------------------------------------------+ | NAME | TYPE | EXTRA | +=======================+======+=================================================================================================+ | workstation-packages* | pm | /home/alice/.local/share/Fuchsia/ffx/pbms/4751486831982119909/workstation_eng.qemu-x64/packages | +-----------------------+------+-------------------------------------------------------------------------------------------------+
Notice a package repository named workstation-packages is created for the Workstation prebuilt image.
Register the workstation-packages package repository to the target device:
tools/ffx target repository register -r workstation-packages --alias fuchsia.com --alias chromium.org
This command exits silently without output.
Build and run the C++ Hello World component{:.external} included in the SDK samples repository. Components are the basic unit of executable software on Fuchsia.
The tasks include:
In VS Code, do the following:
Click the Explorer icon on the left side of VS Code.
{: .screenshot width=“50”}
Open the getting-started.code-workspace file.
Verify that this file includes the following launch configuration:
"launch": { "version": "0.2.0", "configurations": [ { "name": "Fuchsia Hello World", "type": "zxdb", "request": "launch", "launchCommand": "tools/bazel run //src/hello_world:pkg.component", "process": "hello_world" } ] }
This configuration is set to build and run the hello_world sample component.
Click the Run and Debug icon on the left side of VS Code.
{: .screenshot width=“50”}
At the top of the Run and Debug panel, select the Fuchsia Hello World option in the dropdown memu.
{: .screenshot width=“350”}
Click Run > Run Without Debugging.
This starts a debug session (but without actually running a debugger) that launches the hello_world component. The bazel run command used to launch the component prints output similar to the following in the terminal:
$ tools/bazel run //src/hello_world:pkg.component ... INFO: Build completed successfully, 155 total actions Running workflow: pkg.component_base Running task: pkg.debug_symbols_base (step 1/2) Running task: pkg.component.run_base (step 2/2) added repository bazel.pkg.component.runnable URL: fuchsia-pkg://bazel.pkg.component.runnable/hello_world#meta/hello_world.cm Moniker: /core/ffx-laboratory:hello_world.cm Creating component instance... Resolving component instance... Starting component instance... Started component instance!
In the terminal, check the status of the hello_world component:
tools/ffx component show hello_world
This command prints output similar to the following:
$ tools/ffx component show hello_world Moniker: /core/ffx-laboratory:hello_world.cm URL: fuchsia-pkg://bazel.pkg.component.runnable/hello_world#meta/hello_world.cm Instance ID: None Type: CML Component Component State: Resolved Incoming Capabilities: /svc/fuchsia.logger.LogSink Exposed Capabilities: Merkle root: eebd529bd8ac6d2fd8a467279719f74c76643ebee2e94ebf594ffcbaac02fe8f Execution State: Stopped
The output shows that the hello_world component has run and is now terminated (Stopped).
In the debug toolbar at the top of VS Code, click the Stop icon to close the current debug session.
{: .screenshot width=“250”}
Note: You can safely ignore the Error: connection closed pop-up message at the bottom of VS Code for now.
Click the fuchsia-emulator icon at the bottom of VS Code.
{: .screenshot}
This opens the Command Palette at the top of VS Code.
Click Show log for fuchsia-emulator in the Command Palette.
This opens the FUCHSIA LOGS panel and streams the device logs of your current Fuchsia target.
{: .screenshot}
Note: It may take a few minutes to load all the logs cached on the host machine. To stop the streaming of logs, click the pause icon at the top right corner of the FUCHSIA LOGS panel.
To fit the messages on the panel, click the Wrap logs icon at the top right corner of the FUCHSIA LOGS panel.
{: .screenshot width=“200”}
In the Filter logs text box, type hello_world and press Enter.
{: .screenshot}
Notice that Hello, World! is printed from the hello_world component.
Note: For more information on filtering syntax, see Filter Fuchsia logs.
Click the Explorer icon on the left side of VS Code.
Open the src/hello_world/hello_world.cc file.
Edit the message to "Hello again, World!".
The main() method now should look like below:
int main() { {{ '<strong>' }}std::cout << "Hello again, World!\n";{{ '</strong>' }} return 0; }
To save the file, press CTRL+S (or Command+S on macOS).
Click Run > Run Without Debugging.
This builds and runs the hello_world component again.
Click the FUCHSIA LOGS tab on the VS Code panel.
Verify that Hello again, World! is printed in the logs.
{: .screenshot}
In the debug toolbar at the top of VS Code, click the Stop icon.
Examine the symbolized logs (that is, human readable stack traces) of a crashed component.
The tasks include:
In VS Code, do the following:
Select the src/hello_world/hello_world.cc file from the OPEN EDITORS view at the top of VS Code.
Above the line return 0;, add the following line:
abort();
The main() method now should look like below:
int main() { std::cout << "Hello again, World!\n"; {{ '<strong>' }}abort();{{ '</strong>' }} return 0; }
This update will cause the component to crash immediately after printing a message.
To save the file, press CTRL+S (or Command+S on macOS).
Click Run > Run Without Debugging.
Building a component automatically generates and registers its debug symbols in the development environment.
In the debug toolbar at the top of VS Code, click the Stop icon.
In the terminal, restart the ffx daemon:
Note: Today, this workaround is required for newly registered symbols to be discovered in the environment. This issue is being tracked in Issue 94614{:.external}.
tools/ffx daemon stop
A new instance of the ffx daemon starts the next time you run a ffx command or view device logs in VS Code.
Click the FUCHSIA LOGS tab on the VS Code panel.
In the Filter logs text box, type moniker:klog and press Enter.
Verify that the sample component's crash stack is symbolized in the kernel logs.
{: .screenshot}
The symbolized logs above show the exact filenames and line numbers (for example, main() src/hello_world/hello_world.cc:9) that might have caused the component to crash.
Start the Fuchsia debugger (zxdb) in VS Code and debug the sample component, which is now updated to crash when it runs.
The tasks include:
In VS Code, do the following:
Select the src/hello_world/hello_world.cc file from the OPEN EDITORS view at the top of VS Code.
To set a breakpoint at the main() method, click the space to the left of the line number.
{: .screenshot width=“500”}
When a breakpoint is set, a red dot appears.
Click Run > Start Debugging.
This starts a debug session that launches the hello_world component. The debugger then pauses at the line where the breakpoint is set in the src/hello_world/hello_world.cc file.
Click the DEBUG CONSOLE tab on the VS Code panel.
{: .screenshot}
This shows the console output of the Fuchsia debugger (zxdb).
Click the FUCHSIA LOGS tab on the VS Code panel.
At the top right corner of the FUCHSIA LOGS panel, click the Clear logs icon.
In the Filter logs text box, type hello_world and press Enter.
In the debug toolbar at the top of VS Code, click the Step Over icon.
{: .screenshot width=“250”}
In the FUCHSIA LOGS panel, verify that a new Hello again, World! entry is printed in the logs.
{: .screenshot}
In the debug toolbar at the top of VS Code, click the Stop icon.
This causes the component to finish the execution of the rest of the code.
Retrieve a component‘s data exposed by Fuchsia’s Inspect API. This data can be any set of specialized information that a Fuchsia component is programmed to collect while it is running on the device.
Note: For a component to collect and expose inspect data, the implementation of inspect operations and data types must be placed in the component’s code. Developers use this inspect feature to collect and expose information that will be helpful for debugging the component or the system. For details, see Fuchsia component inspection overview.
The tasks include:
bootstrap/archivist component).bootstrap/archivist component.bootstrap/archivist component.In VS Code, do the following:
Click the TERMINAL tab on the VS Code panel.
In the terminal, view the list of components on the device that expose inspect data:
tools/ffx inspect list
This command prints output similar to the following:
$ tools/ffx inspect list <component_manager> bootstrap/archivist bootstrap/driver_manager bootstrap/fshost bootstrap/fshost/blobfs bootstrap/fshost/fxfs ... core/ui/scenic core/vulkan_loader core/wlancfg core/wlandevicemonitor core/wlanstack
Notice that the bootstrap/archivist component is on the list.
View all available selectors for the bootstrap/archivist component:
tools/ffx inspect selectors bootstrap/archivist
This command prints output similar to the following:
$ tools/ffx inspect selectors bootstrap/archivist bootstrap/archivist:root/archive_accessor_stats/all/inspect/batch_iterator/get_next:errors bootstrap/archivist:root/archive_accessor_stats/all/inspect/batch_iterator/get_next:requests bootstrap/archivist:root/archive_accessor_stats/all/inspect/batch_iterator/get_next:responses ...
Each of these selectors represents a different type of data you can inspect.
Inspect the bootstrap/archivist component for the recent events data:
tools/ffx inspect show bootstrap/archivist:root/events/recent_events
This command prints output similar to the following:
$ tools/ffx inspect show bootstrap/archivist:root/events/recent_events bootstrap/archivist: metadata: filename = fuchsia.inspect.Tree component_url = fuchsia-boot:///#meta/archivist.cm timestamp = 705335717538 payload: root: events: recent_events: 361: @time = 6272744049 event = component_stopped moniker = core/trace_manager/cpuperf_provider 362: @time = 6283370267 event = log_sink_requested moniker = core/session-manager ... 556: @time = 415796882099 event = log_sink_requested moniker = core/debug_agent 557: @time = 453898419738 event = component_started moniker = core/ffx-laboratory:hello_world 558: @time = 453899964568 event = log_sink_requested moniker = core/ffx-laboratory:hello_world 559: @time = 453900332656 event = log_sink_requested moniker = core/ffx-laboratory:hello_world 560: @time = 495458923475 event = component_stopped moniker = core/ffx-laboratory:hello_world
This data records all the events triggered by components on the device so far.
Run tests on the device by launching test components, which are included in the SDK samples repository{:.external}.
The tasks include:
In VS Code, do the following:
In the terminal, build and run the sample test components:
tools/bazel test --test_output=all //src/hello_world:test_pkg
This command runs all the tests in the Hello World component’s test package (hello_world:test_pkg{:.external}).
The command prints output similar to the following:
$ tools/bazel test --test_output=all //src/hello_world:test_pkg ... INFO: From Testing //src/hello_world:test_pkg ==================== Test output for //src/hello_world:test_pkg: Error: Invalid build directory BUILD_WORKSPACE_DIRECTORY added repository bazel.test.pkg.hello.gtest.runnable Running test 'fuchsia-pkg://bazel.test.pkg.hello.gtest.runnable/hello_test#meta/hello_gtest_autogen_cml.cm' [RUNNING] HelloTest.BasicAssertions [stdout - HelloTest.BasicAssertions] Running main() from gmock_main.cc Example stdout. [PASSED] HelloTest.BasicAssertions 1 out of 1 tests passed... fuchsia-pkg://bazel.test.pkg.hello.gtest.runnable/hello_test#meta/hello_gtest_autogen_cml.cm completed with result: PASSED added repository bazel.test.pkg.hello.test.runnable Running test 'fuchsia-pkg://bazel.test.pkg.hello.test.runnable/hello_test#meta/hello_test_autogen_cml.cm' [RUNNING] main [PASSED] main [stdout - main] Example stdout. 1 out of 1 tests passed... fuchsia-pkg://bazel.test.pkg.hello.test.runnable/hello_test#meta/hello_test_autogen_cml.cm completed with result: PASSED Running workflow: test_pkg_workflow_base Running task: test_pkg.debug_symbols_base (step 1/3) Running task: test_pkg.hello_gtest.run_base (step 2/3) Running task: test_pkg.hello_test.run_base (step 3/3) ================================================================================ //src/hello_world:test_pkg (cached) PASSED in 4.7s Executed 0 out of 1 test: 1 test passes. INFO: Build completed successfully, 1 total action
Click the Explorer icon on the left side of VS Code.
Open the src/hello_world/hello_gtest.cc file.
Edit the file to replace EXPECT_STRNE() with EXPECT_STREQ().
The test now should look like below:
TEST(HelloTest, BasicAssertions) { std::cout << "Example stdout." << std::endl; // Expect two strings not to be equal. {{ '<strong>' }}EXPECT_STREQ("hello", "world");{{ '</strong>' }} // Expect equality. EXPECT_EQ(7 * 6, 42); }
This change will cause the GoogleTest{:.external} (hello_gtest) to fail.
To save the file, press CTRL+S (or Command+S on macOS).
In the terminal, to verify that the updated test now fails, build and run the hello_gtest component:
tools/bazel test --test_output=all //src/hello_world:test_pkg.hello_gtest
This command prints output similar to the following:
$ tools/bazel test --test_output=all //src/hello_world:test_pkg.hello_gtest ... INFO: From Testing //src/hello_world:test_pkg.hello_gtest: ==================== Test output for //src/hello_world:test_pkg.hello_gtest: Error: Invalid build directory BUILD_WORKSPACE_DIRECTORY added repository bazel.test.pkg.hello.gtest.runnable Running test 'fuchsia-pkg://bazel.test.pkg.hello.gtest.runnable/hello_test#meta/hello_gtest_autogen_cml.cm' [RUNNING] HelloTest.BasicAssertions [stdout - HelloTest.BasicAssertions] Running main() from gmock_main.cc Example stdout. src/hello_world/hello_gtest.cc:14: Failure Expected equality of these values: "hello" "world" [FAILED] HelloTest.BasicAssertions Failed tests: HelloTest.BasicAssertions 0 out of 1 tests passed... fuchsia-pkg://bazel.test.pkg.hello.gtest.runnable/hello_test#meta/hello_gtest_autogen_cml.cm completed with result: FAILED Tests failed. More information may be available in ffx host logs in directory: /usr/local/google/home/alice/.local/share/Fuchsia/ffx/cache/logs Fatal: Shell task ['/usr/local/google/home/alice/.cache/bazel/_bazel_alice/ea119f1048230a864836be3d62fead2c/execroot/__main__/bazel-out/x86_64-fastbuild-ST-1ad63a09c27b/bin/src/hello_world/test_pkg.hello_gtest_runnable_run_component.sh'] failed. Running workflow: test_pkg.hello_gtest_base Running task: test_pkg.debug_symbols_base (step 1/2) Running task: test_pkg.hello_gtest.run_base (step 2/2) Error: Task test_pkg.hello_gtest.run_base (step 2/2) failed to run. ================================================================================ Target //src/hello_world:test_pkg.hello_gtest up-to-date: bazel-out/x86_64-fastbuild-ST-1ad63a09c27b/bin/src/hello_world/test_pkg.hello_gtest_base.sh bazel-out/x86_64-fastbuild-ST-1ad63a09c27b/bin/src/hello_world/test_pkg.hello_gtest_base_workflow.json INFO: Elapsed time: 4.922s, Critical Path: 4.50s INFO: 16 processes: 8 internal, 6 linux-sandbox, 2 local. INFO: Build completed, 1 test FAILED, 16 total actions //src/hello_world:test_pkg.hello_gtest FAILED in 2.5s /usr/local/google/home/alice/.cache/bazel/_bazel_alice/ea119f1048230a864836be3d62fead2c/execroot/__main__/bazel-out/k8-fastbuild/testlogs/src/hello_world/test_pkg.hello_gtest/test.log INFO: Build completed, 1 test FAILED, 16 total actions
Congratulations! You're now all set with the Fuchsia SDK!
Learn more about the Fuchsia platform and tools in Fuchsia SDK Fundamentals.
To update your development environment to use the latest version of the Fuchsia SDK, do the following:
In a terminal, go to your fuchsia-getting-started directory:
cd $HOME/fuchsia-getting-started
Update the project repository and its submodules to the latest version:
git pull --rebase --recurse-submodules
Update the Fuchsia SDK toolchain and dependencies:
tools/bazel build @fuchsia_sdk//:fuchsia_toolchain_sdk
Check the new version of the Fuchsia SDK:
tools/ffx sdk version
Verify that the SDK version is now the latest release version.
If you run into a problem while following this guide and decide to start over from the beginning, consider running the commands below to clean up your development environment (that is, to clean up directories, build artifacts, downloaded files, symlinks, configuration settings, and more).
Remove the package repositories created in this guide:
tools/ffx repository remove workstation-packages
tools/ffx repository server stop
Remove all existing configurations and data of ffx:
{Linux}
tools/ffx daemon stop
rm -rf $HOME/.local/share/Fuchsia/ffx
{macOS}
tools/ffx daemon stop
rm -rf $HOME/Library/Caches/Fuchsia/ffx
rm -rf $HOME/Library/Fuchsia/ffx
rm -rf $HOME/Library/Preferences/Fuchsia/ffx
rm -rf $HOME/Library/Application\ Support/Fuchsia/ffx
When Bazel fails to build, try the commands below:
{Linux}
Note: Running bazel clean or deleting the $HOME/.cache/bazel directory deletes artifacts downloaded by Bazel, which can be around 4 GB. This means Bazel will need to download dependencies again next time you run bazel build.
tools/bazel clean --expunge
tools/bazel shutdown && rm -rf $HOME/.cache/bazel
{macOS}
Note: Running bazel clean or deleting the /private/var/temp/bazel$USER directory deletes artifacts downloaded by Bazel, which can be around 4 GB. This means Bazel will need to download dependencies again next time you run bazel build.
tools/bazel clean --expunge
tools/bazel shutdown && rm -rf /private/var/tmp/bazel$USER
Remove the fuchsia-getting-started directory and its artifacts:
Caution: If the SDK samples repository is cloned to a different location than $HOME/fuchsia-getting-started, adjust the directory in the command below. Be extremely careful with the directory path when you run the rm -rf <DIR> command.
rm -rf $HOME/fuchsia-getting-started
Other clean up commands:
killall ffx
killall pm
When you launch the sample component (for instance, using the command tools/bazel run), you might run into an issue where the command hangs for a long time and eventually fails with the following error:
Lifecycle protocol could not start the component instance: InstanceCannotResolve
In that case, you may need to update the firewall rules on your host machine.
If you’re using the ufw firewall, run the following commands:
sudo ufw allow proto tcp from fe80::/10 to any port 8083 comment 'Fuchsia Package Server'
sudo ufw allow proto tcp from fc00::/7 to any port 8083 comment 'Fuchsia Package Server'
However, for other non-ufw-based firewalls, you will need to ensure that port 8083 is available for the Fuchsia package server.
To check if your Linux machine supports KVM hardware virtualization, run the following command:
lscpu
This command prints output similar to the following:
$ lscpu Architecture: x86_64 CPU op-mode(s): 32-bit, 64-bit Address sizes: 46 bits physical, 48 bits virtual Byte Order: Little Endian ... Virtualization features: {{ '<strong>' }}Virtualization: VT-x{{ '</strong>' }} Hypervisor vendor: KVM Virtualization type: full ...
If you see the following field in the output, your machine supports KVM hardware virtualization:
Virtualization: VT-x
Note: If your machine supports KVM hardware virtualization, see Set up KVM virtualization on a Linux machine to verify that KVM is configured correctly.
On the other hand, for machines that support AMD virtualization, you may see the following field in the output:
Virtualization: AMD-V
However, if your output does not have the Virtualization field at all, while the Hypervisor vendor and Virtualization type fields may still be shown (see the example output below), your machine does not support hardware virtualization.
$ lscpu ... Virtualization features: Hypervisor vendor: KVM Virtualization type: full ...
Note: The instructions in this section require that your Linux machine supports KVM hardware virtualization.
To verify that KVM is configured correctly on your Linux machine, run the following bash shell script:
if [[ -w /dev/kvm ]] && grep '^flags' /proc/cpuinfo | grep -qE 'vmx|svm'; then echo 'KVM is working'; else echo 'KVM not working'; fi
Verify that this shell script prints the following output:
KVM is working
If the output is KVM is working, KVM hardware virtualization is enabled on your Linux machine.
However, if the output is KVM not working, do the following to enable KVM hardware virtualization:
Add yourself to the kvm group on your Linux machine:
sudo usermod -a -G kvm ${USER}
Reboot the machine.
Run the bash shell script above again.
Verify that the output now prints KVM is working.