Как я могу проверить, является ли среда WSL из оболочки сценария?

Вопрос или проблема

В .bashrc у меня есть некоторая конфигурация для конкретных окружений, как это.

if [ "$(uname)" = 'Linux' ]; then
   . "$HOME/.bash.d/ubuntu"
fi

if [ "$(uname)" = 'Darwin' ]; then
   . "$HOME/.bash.d/osx"
fi

Чтобы узнать, находится ли текущее окружение под WSL, я использую файл /etc/wsl.conf, который обычно существует только в WSL.

if [ -f "/etc/wsl.conf" ]; then
   . "$HOME/.bash.d/wsl"
fi

Но, конечно, файл также может существовать и в других окружениях.

Как мне проверить, работает ли текущее окружение в WSL?

Нет “безошибочного” способа сделать это, поскольку каждый метод обнаружения может привести к ложным срабатываниям или ложным отрицаниям в определенных ситуациях. Тем не менее, если вы делаете это только для своих личных конфигурационных файлов, то, вероятно, у вас есть довольно хорошее представление о том, сработает ли тот или иной метод на вашей системе или нет.

Некоторые различные методы, со своими плюсами и минусами:

  • Наличие /proc/sys/fs/binfmt_misc/WSLInterop является довольно хорошим индикатором того, что вы находитесь в WSL. Этот может быть самым надежным методом, и именно его использует проект Snapd Ubuntu в качестве механизма обнаружения. Этот файл по умолчанию существует как в WSL1, так и в WSL2. Даже когда Interop отключен через /etc/wsl.conf, этот файл все равно будет создан WSL при запуске.

    Предостережения: Конечно, запись binfmt_misc можно настроить с именем WSLInterop, но это было бы крайне паталогично, что привело бы к ложному срабатыванию теста.

    Кроме того, возможно переопределить название Interop, как упоминается в моем ответе на Ask Ubuntu здесь. Это было бы необычным случаем, но мы использовали это, чтобы временно предотвратить обнаружение WSL Snapd, пока исправляли ошибку. Это создает ложное отрицание, конечно.

    В войне эскалации, вы можете “испередить-упреждение”, произвев поиск magic 4d5a в этой директории, но это может быть немного слишком 😉

  • Как @MBehrens упоминает, по умолчанию название ядра в WSL содержит строку “Microsoft” (или “microsoft”, в зависимости от версии). Использование uname -r или /proc/version) может быть использовано для обнаружения.

    Предостережения: Другие системы могут (я думаю о Azure) использовать ядро, собранное Microsoft, что может привести к ложному срабатыванию. И возможно собрать пользовательское ядро для WSL2 с другим именем, что приведет к ложному отрицанию.

  • Вы даже можете просто проверить переменную окружения $WSL_DISTRO_NAME. Эта переменная автоматически внедряется в окружение WSL.

    Предостережения: Вы всегда можете (паталогично) создать это имя переменной на любой системе, что приведет к ложным срабатываниям.

    Что более важно, есть случаи, когда эта переменная не будет доступна, например, если вы su - $USER.

Конечно, есть и другие методы (например, проверьте, исполняется ли $(which powershell.exe)), но вышеуказанные варианты должны дать вам представление о различных подходах.

Проверьте вывод команды

cat /proc/version

и

cat /proc/sys/kernel/osrelease

Например:

if [[ $(grep -i Microsoft /proc/version) ]]; then
echo "Bash работает в WSL"
fi

Если у вас включен systemd, вы можете попробовать

systemd-detect-virt

это должно вернуть

wsl

Хотя немного запоздало, но в WSL команда lscpu показывает строку:

  • Hypervisor vendor: Windows Subsystem for Linux

Это происходит как для обычного пользователя, так и при использовании sudo su.

WSL имеет свои собственные ядра – когда вы запускаете uname – будет показано специфическое для MS ядро, которое указывает на WSL2

uname  -r 
5.15.153.1-microsoft-standard-WSL2

Ответ или решение

Для проверки, работает ли среда в Windows Subsystem for Linux (WSL), можно использовать несколько методов в рамках оболочки bash. Каждая из этих техник имеет свои плюсы и минусы, и выбор метода может зависеть от ваших конкретных требований и сценариев использования. Рассмотрим наиболее распространенные и эффективные способы определения WSL.

1. Использование файла /proc/version

Одним из наиболее надёжных способов является проверка на наличие строки "Microsoft" в файле /proc/version. Этот файл содержит информацию о версии ядра и окружении.

if grep -qi microsoft /proc/version; then
    echo "Среда работает под WSL"
fi

2. Проверка по версии ядра с помощью uname

Вы также можете использовать команду uname -r, которая выводит информацию о текущем ядре. В WSL версия ядра содержит строку "microsoft":

if [[ "$(uname -r)" == *"microsoft"* ]]; then
    echo "Среда работает под WSL"
fi

3. Проверка наличия переменной окружения

Переменная окружения $WSL_DISTRO_NAME автоматически вводится в окружение WSL. Это может быть простым способом проверки:

if [ -n "$WSL_DISTRO_NAME" ]; then
    echo "Среда работает под WSL"
fi

4. Использование systemd-detect-virt

Если у вас включён systemd, вы можете использовать команду systemd-detect-virt. Эта команда должна вернуть "wsl", если вы работаете в WSL:

if [[ "$(systemd-detect-virt)" == "wsl" ]]; then
    echo "Среда работает под WSL"
fi

5. Проверка с помощью lscpu

Команда lscpu также может быть полезной. Она отображает информацию о архитектуре процессора, и если вы находитесь в WSL, вы увидите строку, указывающую на это:

if lscpu | grep -q "Hypervisor vendor:   Windows Subsystem for Linux"; then
    echo "Среда работает под WSL"
fi

6. Проверка наличия специфичных файлов

Как вы уже упомянули, файл /etc/wsl.conf обычно существует только в WSL. Однако, как вы правильно заметили, это не самый надежный метод, поскольку его наличие может быть случайно или намеренно создано в других окружениях. Тем не менее, для полной проверки можно его добавить:

if [ -f "/etc/wsl.conf" ]; then
    echo "Возможно, это WSL (но необходимо дополнительное подтверждение)"
fi

Заключение

Для наиболее надёжного определения среды WSL я рекомендую использовать комбинацию из вышеуказанных методов, например, проверку наличия строки "Microsoft" в /proc/version в сочетании с проверкой наличия переменной $WSL_DISTRO_NAME. Это позволит минимизировать риск ложных срабатываний.

Вот пример общего скрипта, который объединяет эти методы:

if grep -qi microsoft /proc/version || [[ "$(uname -r)" == *"microsoft"* ]] || [ -n "$WSL_DISTRO_NAME" ]; then
    echo "Среда работает под WSL"
else
    echo "Среда не WSL"
fi

Эти методы являются наиболее распространёнными и надёжными способами проверить, работает ли ваш скрипт в окружении WSL.

Оцените материал
Добавить комментарий

Капча загружается...