Detect Apple Silicon from command line
Asked Answered
P

4

77

How can I detect from a shell script that it is running on M1 Apple hardware?

I want to be able to run a command-line command so that I can write an if-statement whose body will only be executed when run on a mac with an M1 processor (and at least macOS Big Sur, naturally).

Postmaster answered 11/12, 2020 at 22:10 Comment(3)
uname -p will probably give you the information you want, but I don't have an M1 to test.Illuminati
Tested. It works.Scintillate
yep that was even better. Post it as an answer and I'll accept itPostmaster
P
105
uname -m

will return arm64 as opposed to x86_64

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

or, as @chepner suggested

uname -p

will return arm as opposed to i386

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

yet another tool is arch:

if [[ $(arch) == 'arm64' ]]; then
  echo M1
fi
Postmaster answered 11/12, 2020 at 22:15 Comment(5)
Note that M1 users can run Terminal in Rosetta mode. In this case "uname -m" returns "x86_64".Agency
it's not just if running Terminal in Rosetta, but also if whatever process runs the script happens to be running in Rosetta too. If someone runs this in a script deployed by, say, an RMM that is running via Rosetta you'll get x86_64. i think the sysctl approach is the best solution searching for 'Apple' in the string: [[ $(sysctl -n machdep.cpu.brand_string) =~ "Apple" ]]Azov
This doesn't work at all! If you are in VSCode Jupyter kernel it will say x86_64 even though I am on M2 Max. This sysctl -n machdep.cpu.brand_string is the best command.Vasculum
@Vasculum "doesn't work at all" is an overstatement. If your "VSCode Jupyter" is reporting x86_64, then that process runs through the Rosetta emulator, which is probably not what you want since both VSCode and Jupyter support Apple Silicon.Postmaster
point taken, I should have said not reliable depending on where it is being executed.Vasculum
B
32

I found that sysctl -n machdep.cpu.brand_string reported Apple M1 even though the process was run under Rosetta.

Update: be prepared for Apple M1 Pro, Apple M2, Apple M2 Max etc.!

Bless answered 5/11, 2021 at 12:11 Comment(4)
This is what's needed to cleanly answer 'can I arch -arm64 bash my way out of here. Hard to believe arch doesn't have a -l to list current machine available architectures.Midsection
should be the accepted answer, except for the fact that this doesn't work on linuxSurrebutter
Be careful not to do an exact match. My laptop returns Apple M1 Pro.Graveyard
A MacBook Pro 16" from 2023 (with M2 Max processor) will answer Apple M2 MaxPostmaster
K
13

When using the native shell say /bin/bash -i or /bin/zsh -i, Klas Mellbourn's answer works as expected.

If using a shell that was installed via an Intel/Rosetta Homebrew installation, then uname -p returns i386, and uname -m returns x86_64, as indicated by Datasun's comment.


To get something that works across environments (Apple Silicon Native, Rosetta Shell, Linux, Raspberry Pi 4s), I use the following from the dorothy dotfile ecosystem:

is-mac && test "$(get-arch)" = 'a64'

If you aren't using dorothy, the relevant code from dorothy is:

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's answer on a duplicate question gives details on how to get the specific CPU instead of the architecture. Using sysctl -n machdep.cpu.brand_string outputs Apple M1 on my M1 Mac Mini, however outputs the following on a Raspberry Pi 4 Ubuntu Server:

> 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
Kosygin answered 27/6, 2021 at 7:2 Comment(2)
If uname -m returns x86_64 I think you are probably running your terminal through Rosetta. Have you checked Open using Rosetta in the Get Info dialog for the terminal program?Postmaster
Open using Rosetta is unchecked: dropbox.com/s/lrhxgkxtmi2wv74/… If I run a new command /bin/bash -i and then run uname -m then it returns arm64 and uname -p returns arm. So is caused by my default shell, which is installed by homebrew, being run through rosetta. Thanks for helping me track this down. I've updated my answer.Kosygin
R
0

/usr/bin/arch is all you need. Why complicate things when there's already a program to do this for you.

Robson answered 29/6, 2023 at 8:23 Comment(1)
https://mcmap.net/q/264987/-detect-apple-silicon-from-command-line already provides this information. Why add it again?Outcaste

© 2022 - 2024 — McMap. All rights reserved.