Michael Smith
Michael Smith

Reputation: 193

Most efficient if statement in .zshrc to check whether Linux OS is running on WSL?

In my .zshrc file I conditionally set my PATH variable depending on whether I'm running on Linux or macOS - I'm now trying to figure out if there's a way I can efficiently detect from my .zshrc if I'm working on Linux running on WSL.

I'm wondering if I can somehow check for the existence of /mnt/c/Program Files or similar - but figure there must be a better way?

Example of my current .zshrc:

PATH="/usr/local/sbin:$PATH" 
if ! [[ "$OSTYPE" == "darwin"* ]]; then
  export PATH="$HOME/.nodenv/bin:$HOME/.rbenv/bin:$PATH"
fi
eval "$(rbenv init -)"
eval "$(nodenv init -)"
PATH="$HOME/.bin:$PATH"
if [[ "$OSTYPE" == "darwin"* ]]; then
  export ANDROID_SDK_ROOT="$HOME/Library/Android/sdk"
  export PATH="$PATH:$ANDROID_SDK_ROOT/tools:$ANDROID_SDK_ROOT/tools/bin:$ANDROID_SDK_ROOT/platform-tools:$ANDROID_SDK_ROOT/build-tools:$ANDROID_SDK_ROOT/tools/lib/x86_64"
  export PATH="$PATH:/usr/local/share/dotnet"
fi

If anyone has any better ideas than somehow checking for the existence of /mnt/c/Program Files I'd very much appreciate it!

Upvotes: 1

Views: 4016

Answers (4)

hitshy_dev
hitshy_dev

Reputation: 133

Short/current answer:

To detect either WSL1 or WSL2, you can use a modified version of @MichaelSmith's answer:

#!/bin/zsh

if [[ $(uname -r) == (#s)*[mM]icrosoft*(#e) ]]; then
  echo test
fi

More detail:

When this question was originally asked, only WSL1 existed, and uname -r would return something like:

4.4.0-22000-Microsoft

This is not a "real" kernel in WSL1, but just the number/name that Microsoft chooses to provide in response to that particular syscall. The 22000, in this case, is the Windows build number, which currently corresponds to the WSL release. Note that this is the case even in the current WSL Preview in the Microsoft Store, even though it is decoupled from the Windows release.

With WSL2, however, Microsoft provides a real Linux kernel, which returns something like:

5.10.102.1-microsoft-standard-WSL2

Earlier versions may have left off the -WSL2 portion.

Of course, if you build your own WSL2 kernel, you should update the test to match the kernel name you provide.

Upvotes: 1

Patrick Wu
Patrick Wu

Reputation: 41

In WSL, there is a special file for checking interoperability called /proc/sys/fs/binfmt_misc/WSLInterop which is WSL specific file. You can check using the following command:

#!/bin/bash
if [ -f /proc/sys/fs/binfmt_misc/WSLInterop ]; then
  echo True
fi

or more simple one-line code(in bash):

[ -f /proc/sys/fs/binfmt_misc/WSLInterop ]

This will return exit code 0 if true, exit code 1 if false.

Upvotes: 2

Biswapriyo
Biswapriyo

Reputation: 4281

There are many possible way to check WSL in any shell. Most reliable ways are:

  1. From uname -r command output.
  2. From /proc/version file.
  3. From /proc/sys/kernel/osrelease file.
#!/bin/bash

if uname -r |grep -q 'Microsoft' ; then
    echo True
fi

if grep -q -i 'Microsoft' /proc/version ; then
    echo True
fi

if grep -q -i 'Microsoft' /proc/sys/kernel/osrelease ; then
    echo True
fi

Also there are many file existence can be checked with shell script. For example, only WSL has 1. /dev/lxss 2. /bin/wslpath 3. /sbin/mount.drvfs 4. /proc/sys/fs/binfmt_misc/WSLInterop 5. /etc/wsl.conf files but GNU/Linux distributions has not.

See more:

Upvotes: 5

Michael Smith
Michael Smith

Reputation: 193

Thanks to Biswapiryo's comment - I came up with this solution to detect WSL:

if [[ $(uname -r)] == ^*Microsoft$ ]]; then
  # Code goes here
fi

Upvotes: 1

Related Questions