如何检查是否在 Cygwin、Mac 还是 Linux 中运行?
我有一个可在 Windows/Cygwin 以及 Mac 和 Linux 上使用的 shell 脚本。每个版本需要稍微不同的变量。
shell/bash 脚本如何检测它是在 Cygwin、Mac 还是 Linux 中运行?
I have a shell script that is used both on Windows/Cygwin and Mac and Linux. It needs slightly different variables for each versions.
How can a shell/bash script detect whether it is running in Cygwin, on a Mac or in Linux?
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(11)
通常,
uname
及其各种选项会告诉您正在运行的环境:并且,根据非常有用的
schot
(在评论中),uname -s
为 OSX 提供Darwin
,为 Linux 提供Linux
,而我的 Cygwin 提供CYGWIN_NT-5.1
。但您可能必须尝试各种不同的版本。因此,执行此类检查的 bash 代码将类似于:
请注意,我假设您实际上在 CygWin 内运行(
bash
shell),因此路径应该已经正确设置。正如一位评论者指出的那样,您可以从 cmd 本身运行 bash 程序并传递脚本,这可能会导致路径未根据需要设置。如果您这样做,则您有责任确保调用正确的可执行文件(即CygWin),可能通过预先修改路径或完全指定可执行文件位置(例如,
/c/cygwin/bin/uname
)。Usually,
uname
with its various options will tell you what environment you're running in:And, according to the very helpful
schot
(in the comments),uname -s
givesDarwin
for OSX andLinux
for Linux, while my Cygwin givesCYGWIN_NT-5.1
. But you may have to experiment with all sorts of different versions.So the
bash
code to do such a check would be along the lines of:Note that I'm assuming here that you're actually running within CygWin (the
bash
shell of it) so paths should already be correctly set up. As one commenter notes, you can run thebash
program, passing the script, fromcmd
itself and this may result in the paths not being set up as needed.If you are doing that, it's your responsibility to ensure the correct executables (i.e., the CygWin ones) are being called, possibly by modifying the path beforehand or fully specifying the executable locations (e.g.,
/c/cygwin/bin/uname
).检测三种不同的操作系统类型(GNU/Linux、Mac OS X、Windows NT)
注意
#!/usr/bin/env bash
而不是#!/bin/ sh
来防止/bin/sh
链接到不同平台的不同默认shell引起的问题,否则会出现意外的操作符之类的错误,这就是发生的情况在我的电脑上(Ubuntu 64 位 12.04)。expr
程序,除非你安装它,所以我只使用uname
。设计
uname
获取系统信息(-s
参数)。expr
和substr
来处理字符串。if
elif
fi
来完成匹配工作。uname -s
规范即可。实施
测试
我学到了什么
参考文献
Detect three different OS types (GNU/Linux, Mac OS X, Windows NT)
Notes
#!/usr/bin/env bash
instead of#!/bin/sh
to prevent the problem caused by/bin/sh
linked to different default shell in different platforms, or there will be error like unexpected operator, that's what happened on my computer (Ubuntu 64 bits 12.04).expr
program unless you install it, so I just useuname
.Design
uname
to get the system information (-s
parameter).expr
andsubstr
to deal with the string.if
elif
fi
to do the matching job.uname -s
specification.Implementation
Testing
What I learned
References
使用
uname -s
(--kernel-name
) 因为uname -o
(--operating-system
) 在某些操作系统上不受支持,例如 Mac OS 和 Solaris。您也可以仅使用uname
而不带任何参数,因为默认参数是-s
(--kernel-name
)。为了区分 WSL 和 Linux,einarmagnus 建议
uname -sr
(--kernel-name --kernel-release
),如建议的那样以下脚本。Use
uname -s
(--kernel-name
) becauseuname -o
(--operating-system
) is not supported on some Operating Systems such as Mac OS and Solaris. You may also use justuname
without any argument since the default argument is-s
(--kernel-name
).To distinguish WSL from Linux, einarmagnus recommends
uname -sr
(--kernel-name --kernel-release
) as proposed in the following script. ????The following
Makefile
is inspired from Git project (config.mak.uname
).See also this complete answer about
uname -s
andMakefile
.The correspondence table in the bottom of this answer is from Wikipedia article about
uname
. Please contribute to keep it up-to-date (edit the answer or post a comment). You may also update the Wikipedia article and post a comment to notify me about your contribution ;-)Bash 设置 shell 变量 OSTYPE。来自
man bash
:与
uname
相比,这有一个微小的优势,因为它不需要启动新进程,因此执行速度会更快。但是,我无法找到权威的预期值列表。对于 Ubuntu 14.04 上的我来说,它设置为“linux-gnu”。我在网上搜寻了一些其他值。因此:
星号在某些情况下很重要 - 例如 OSX 在“darwin”后面附加操作系统版本号。有人告诉我,“win”值实际上是“win32” - 也许有一个“win64”?
也许我们可以一起填写一个经过验证的值表:
linux-gnu
cygwin
msys
darwin22。 0
(如果与现有条目不同,请附加您的值)
Bash sets the shell variable OSTYPE. From
man bash
:This has a tiny advantage over
uname
in that it doesn't require launching a new process, so will be quicker to execute.However, I'm unable to find an authoritative list of expected values. For me on Ubuntu 14.04 it is set to 'linux-gnu'. I've scraped the web for some other values. Hence:
The asterisks are important in some instances - for example OSX appends an OS version number after the 'darwin'. The 'win' value is actually 'win32', I'm told - maybe there is a 'win64'?
Perhaps we could work together to populate a table of verified values here:
linux-gnu
cygwin
msys
darwin22.0
(Please append your value if it differs from existing entries)
如果 uname -s 命令的前 6 个字符是“CYGWIN”,则假定为 cygwin 系统
If the 6 first chars of uname -s command is "CYGWIN", a cygwin system is assumed
为了以 Albert 的答案为基础,我喜欢使用
$COMSPEC
来检测 Windows:这可以避免解析
$OS
的 Windows 名称变体,以及解析uname< 的变体。 /code> 如 MINGW、Cygwin 等。
背景:
%COMSPEC%
是一个 Windows 环境变量,指定命令处理器(也称为 Windows shell)的完整路径。此变量的值通常为%SystemRoot%\system32\cmd.exe
,其计算结果通常为C:\Windows\system32\cmd.exe
。To build upon Albert's answer, I like to use
$COMSPEC
for detecting Windows:This avoids parsing variants of Windows names for
$OS
, and parsing variants ofuname
like MINGW, Cygwin, etc.Background:
%COMSPEC%
is a Windows environmental variable specifying the full path to the command processor (aka the Windows shell). The value of this variable is typically%SystemRoot%\system32\cmd.exe
, which typically evaluates toC:\Windows\system32\cmd.exe
.https://en.wikipedia.org/wiki/Uname
您将得到的所有信息需要。谷歌是你的朋友。
使用
uname -s
查询系统名称。Darwin
CYGWIN_...
LINUX
适用于大多数https://en.wikipedia.org/wiki/Uname
All the info you'll ever need. Google is your friend.
Use
uname -s
to query the system name.Darwin
CYGWIN_...
LINUX
for most当提出这个问题时,Linux 的 Windows 子系统还不存在。它在我的测试中给出了以下结果:
这意味着您需要 uname -r 来将其与本机 Linux 区分开来。
Windows Subsystem for Linux did not exist when this question was asked. It gave these results in my test:
This means that you need uname -r to distinguish it from native Linux.
好的,这是我的方法。
例如,
我在我的 dotfiles 中使用它
Ok, here is my way.
e.g.
I use this in my dotfiles
我想 uname 的答案是无与伦比的,主要是在清洁方面。
尽管执行起来需要很长的时间,但我发现测试特定文件的存在也给了我更好、更快的结果,因为我没有调用可执行文件:
所以,
[ -f /usr/bin/cygwin1.dll ]&& echo 是的,Cygwin 运行
只是使用快速 Bash 文件存在检查。由于我现在使用的是 Windows,因此我无法从脑海中告诉您任何适用于 Linux 和 Mac OS X 的特定文件,但我很确定它们确实存在。 :-)
I guess the uname answer is unbeatable, mainly in terms of cleanliness.
Although it takes a ridiculous time to execute, I found that testing for specific files presence also gives me good and quicker results, since I'm not invoking an executable:
So,
[ -f /usr/bin/cygwin1.dll ] && echo Yep, Cygwin running
just uses a quick Bash file presence check. As I'm on Windows right now, I can't tell you any specific files for Linuxes and Mac OS X from my head, but I'm pretty sure they do exist. :-)
非常令人惊讶的是没有人提到 GNU
config.guess
为了完整性。鉴于
bash
已经预期可以工作,应该不会有什么麻烦,因为config.guess
主要是用 shell 语言实现的,并且预期可以正常工作。它确实依赖于一些有效的uname
命令,但该命令几乎总是由可用bash
的安装提供。并且几乎没有任何替代方案可以拥有更全面的支持平台集(除了基于它的平台,例如GNU Autoconf)。事实上,与通常的需要相比,它往往太长了。您可能拥有其中的一些有限子集。当许可证有问题时,您也可以避免直接使用它。但针对 Windows 的一些注意事项:
cygwin1.dll
或msys-2.0.dll
这样的子系统 DLL(除了 Win32) 。 MinGW 程序通常使用与 MSVC 构建的程序完全相同的 DLL 集(即使使用相同的 libc),只是它们可能具有不同的 C++ 运行时依赖项(例如libstdc++-6.dll
+libgcc_s_ [sjlj/dw/seh]-X.dll
与msvcpXXX.dll
/vcruntimeXXX_1.dll
),因为使用了不同的工具链。$PATH
中可能还有其他本机 Win32 程序,包括uname.exe
。 (实际上,这是 MSYS2 安装 运行 MinGW 环境之一 的预期情况,其中是使用bash
和其他 MSYS2 工具以及 MinGW32 本机工具链的核心机制。)您应该在报告CYGWIN
的路径中有一个uname.exe
> 或MSYS
作为系统,而不是MINGW
如果您的目标程序是bash
而不是本机 Win32 程序。Quite surprising that no one mentions GNU
config.guess
for completeness.Given that
bash
is already expected working, there should be few troubles becauseconfig.guess
is mostly implemented in the shell language and it is expected just work. It does relies on some workinguname
command, but that should almost always provided by the installation wherebash
is available. And there are almost no alternatives can have a more comprehensive sets of supported platforms (except something based on it, e.g. GNU Autoconf). In fact it is often too lengthy compared to the usual needs. You may have some limited subset of it. You may also avoid to use it directly when the license is a problem.But some caveats for Windows:
cygwin1.dll
ormsys-2.0.dll
. MinGW programs typically use exactly the same set of DLLs as programs built by MSVC (even with same libc), except that they may have different C++ runtime dependencies (e.g.libstdc++-6.dll
+libgcc_s_[sjlj/dw/seh]-X.dll
vs.msvcpXXX.dll
/vcruntimeXXX_1.dll
) due to different toolchains are used.$PATH
, includinguname.exe
. (Actually this is the expected case for MSYS2 a installation running one of the MinGW environments, which is the core mechanism to usebash
and other MSYS2 tools together with MinGW32 native toolchains.) You should have auname.exe
in the path reportingCYGWIN
orMSYS
as the system, notMINGW
one if you are targetting programs asbash
rather than native Win32 ones.cygming
stuff for common PE targets running on Windows. Normally they are better to be detected separately and then delegated to some common logic when needed.