从命令行检测苹果芯片的方法

70

如何从一个shell脚本中检测它是否正在运行M1苹果硬件上?

我想运行一个命令行命令,以便编写一个if语句,只有在使用M1处理器的Mac(自然是至少macOS Big Sur)上运行时才执行其主体。


4
uname -p 可能会给你想要的信息,但我没有 M1 进行测试。 - chepner
1
测试过了。它有效。 - aheze
没错,这次翻译得更好了。把它作为答案发布,我会接受它的。 - Klas Mellbourn
4个回答

93
uname -m

将返回 arm64,而不是 x86_64

if [[ $(uname -m) == 'arm64' ]]; then
  echo M1
fi

或者,正如@chepner建议的那样

uname -p

将返回 arm 而不是 i386

if [[ $(uname -p) == 'arm' ]]; then
  echo M1
fi

还有一种工具叫做arch

if [[ $(arch) == 'arm64' ]]; then
  echo M1
fi

23
请注意,M1用户可以在Rosetta模式下运行终端。在这种情况下,“uname -m”返回“x86_64”。 - Nusatad
9
不仅在Rosetta中运行终端,而且无论运行脚本的任何进程是否也在Rosetta中运行,都会出现问题。如果某人通过由Rosetta运行的RMM部署的脚本运行此脚本,将得到“x86_64”结果。我认为使用“sysctl”方法搜索字符串中的“Apple”是最佳解决方案:[[ $(sysctl -n machdep.cpu.brand_string)=~“Apple” ]] - bheinz
1
这根本不起作用!如果你在VSCode Jupyter内核中,它会显示x86_64,即使我使用的是M2 Max。sysctl -n machdep.cpu.brand_string是最好的命令。 - Maziyar
1
@Maziyar “完全不起作用”是一种夸张的说法。如果您的“VSCode Jupyter”报告“x86_64”,那么该进程会通过Rosetta仿真器运行,这可能不是您想要的,因为VSCode和Jupyter都支持Apple Silicon。 - Klas Mellbourn
我明白了,我应该说它的可靠性取决于它在哪里被执行。 - Maziyar

27

我发现即使在 Rosetta 下运行,sysctl -n machdep.cpu.brand_string 仍然报告了 Apple M1

更新:准备好迎接 Apple M1 ProApple M2Apple M2 Max 等等!


3
这就是干净地回答“我能否通过arch -arm64 bash的方式离开这里”的必要条件。难以置信arch没有-l来列出当前可用的机器架构。 - Joe
应该是被接受的答案,但事实上在Linux上无法运行。 - airtonix
1
小心不要进行精确匹配。我的笔记本返回“Apple M1 Pro”。 - Mark
1
一台2023年的MacBook Pro 16英寸(搭载M2 Max处理器)将会响应Apple M2 Max - Klas Mellbourn

12
当使用本地shell时,输入/bin/bash -i/bin/zsh -iKlas Mellbournanswer将按预期工作。
如果使用通过Intel/Rosetta Homebrew安装的shell,则uname -p返回i386uname -m返回x86_64,如Datasuncomment所示。
为了让某些东西能够在不同的环境中运行(如:Apple Silicon原生、Rosetta Shell、Linux、Raspberry Pi 4s),我使用以下来自dorothy dotfile生态系统的内容:
is-mac && test "$(get-arch)" = 'a64'

如果您没有使用Dorothy,那么来自Dorothy的相关代码如下:

https://github.com/bevry/dorothy/blob/1c747c0fa6bb3e6c18cdc9bae17ab66c0603d788/commands/is-mac

test "$(uname -s)" = "Darwin"

https://github.com/bevry/dorothy/blob/1c747c0fa6bb3e6c18cdc9bae17ab66c0603d788/commands/get-arch

arch="$(uname -m)"  # -i is only linux, -m is linux and apple
if [[ "$arch" = x86_64* ]]; then
    if [[ "$(uname -a)" = *ARM64* ]]; then
        echo 'a64'
    else
        echo 'x64'
    fi
elif [[ "$arch" = i*86 ]]; then
    echo 'x32'
elif [[ "$arch" = arm* ]]; then
    echo 'a32'
elif test "$arch" = aarch64; then
    echo 'a64'
else
    exit 1
fi

Jatin Mehrotra关于重复问题答案提供了如何获得特定CPU而不是架构的详细信息。在我的M1 Mac Mini上使用sysctl -n machdep.cpu.brand_string输出Apple M1,但在树莓派4 Ubuntu服务器上输出如下:
> sysctl -n machdep.cpu.brand_string
Command 'sysctl' is available in the following places
 * /sbin/sysctl
 * /usr/sbin/sysctl
The command could not be located because '/sbin:/usr/sbin' is not included in the PATH environment variable.
This is most likely caused by the lack of administrative privileges associated with your user account.
sysctl: command not found

> sudo sysctl -n machdep.cpu.brand_string
sysctl: cannot stat /proc/sys/machdep/cpu/brand_string: No such file or directory

1
如果 uname -m 返回 x86_64,我认为你可能是通过 Rosetta 运行终端。你是否在终端程序的“获取信息”对话框中检查了“使用 Rosetta 打开”? - Klas Mellbourn
2
未勾选“使用 Rosetta 打开”: https://www.dropbox.com/s/lrhxgkxtmi2wv74/CleanShot%202021-06-28%20at%2006.24.52%402x.png?dl=0如果我运行一个新的命令 /bin/bash -i ,然后运行 uname -m ,它会返回 arm64 ,而 uname -p 返回 arm ,这是由于我的默认 shell 是通过 rosetta 运行的,该 shell 是由 homebrew 安装的。感谢您帮助我找到问题所在。我已更新了解答。 - balupton

0
/usr/bin/arch就是你所需要的。既然已经有一个程序可以为你完成这个任务,为什么要把事情搞得复杂呢?

1
https://dev59.com/KFEG5IYBdhLWcg3wfPPB#65259353 已经提供了这个信息。为什么要再次添加呢? - ikaerom

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接