如何在 M1 Macbook 順利執行 Azure Functions (無需 Rosetta)

Alex Lau 劉光曆

Alex Lau 劉光曆

2022-02-09

Azure Functions 其中一個令我最愛的功能,就是有十分完整的工具配套,讓我很方便就可以在本地進行不同的測試,模擬到實際 Azure Functions 的環境,而不需要費時不斷 deploy 上雲端。

最近購入了 M1 Macbook,心血來潮嘗試重啟一些 Azure Functions 的專案,怎料畫面都一遍紅,即使在全新的專案也遇到同樣情況!

> azure-night-functions@1.0.0 build /Users/pak/Documents/azure-night-functions
> tsc

$ func start

Azure Functions Core Tools
Core Tools Version:       3.0.3904 Commit hash: c345f7140a8f968c5dbc621f8a8374d8e3234206  (64-bit)
Function Runtime Version: 3.3.1.0

[2022-02-09T04:24:02.757Z] Cannot create directory for shared memory usage: /dev/shm/AzureFunctions
[2022-02-09T04:24:02.766Z] System.IO.FileSystem: Access to the path '/dev/shm/AzureFunctions' is denied. Operation not permitted.
[2022-02-09T04:24:10.460Z] internal/modules/cjs/loader.js:905
[2022-02-09T04:24:10.472Z]   throw err;
[2022-02-09T04:24:10.474Z]   ^
[2022-02-09T04:24:10.475Z] Error: Cannot find module './Worker.js'
[2022-02-09T04:24:10.477Z] Require stack:
[2022-02-09T04:24:10.477Z] - /Users/pak/Documents/azure-night-functions/node_modules/azure-functions-core-tools/bin/workers/node/dist/src/nodejsWorker.js
[2022-02-09T04:24:10.477Z]     at Function.Module._resolveFilename (internal/modules/cjs/loader.js:902:15)
[2022-02-09T04:24:10.477Z]     at Function.Module._load (internal/modules/cjs/loader.js:746:27)
[2022-02-09T04:24:10.477Z]     at Module.require (internal/modules/cjs/loader.js:974:19)
[2022-02-09T04:24:10.477Z]     at require (internal/modules/cjs/helpers.js:93:18)
[2022-02-09T04:24:10.477Z]     at Object.<anonymous> (/Users/pak/Documents/azure-night-functions/node_modules/azure-functions-core-tools/bin/workers/node/dist/src/nodejsWorker.js:45:14)
[2022-02-09T04:24:10.477Z]     at Module._compile (internal/modules/cjs/loader.js:1085:14)
[2022-02-09T04:24:10.477Z]     at Object.Module._extensions..js (internal/modules/cjs/loader.js:1114:10)
[2022-02-09T04:24:10.477Z]     at Module.load (internal/modules/cjs/loader.js:950:32)
[2022-02-09T04:24:10.477Z]     at Function.Module._load (internal/modules/cjs/loader.js:790:12)
[2022-02-09T04:24:10.477Z]     at Function.executeUserEntryPoint [as runMain] (internal/modules/run_main.js:76:12) {
[2022-02-09T04:24:10.477Z]   code: 'MODULE_NOT_FOUND',
[2022-02-09T04:24:10.477Z]   requireStack: [
[2022-02-09T04:24:10.478Z]     '/Users/pak/Documents/azure-night-functions/node_modules/azure-functions-core-tools/bin/workers/node/dist/src/nodejsWorker.js'
[2022-02-09T04:24:10.478Z]   ]
[2022-02-09T04:24:10.478Z] }
[2022-02-09T04:24:10.479Z] Expected directory: node-v83-darwin-arm64-unknown
[2022-02-09T04:24:10.479Z] Found: [node-v57-darwin-ia32-unknown, node-v57-darwin-x64-unknown, node-v57-linux-ia32-glibc, node-v57-linux-x64-glibc, node-v57-win32-ia32-unknown, node-v57-win32-x64-unknown, node-v64-darwin-ia32-unknown, node-v64-darwin-x64-unknown, node-v64-linux-ia32-glibc, node-v64-linux-x64-glibc, node-v64-win32-ia32-unknown, node-v64-win32-x64-unknown, node-v72-darwin-ia32-unknown, node-v72-darwin-x64-unknown, node-v72-linux-ia32-glibc, node-v72-linux-x64-glibc, node-v72-win32-ia32-unknown, node-v72-win32-x64-unknown, node-v83-darwin-ia32-unknown, node-v83-darwin-x64-unknown, node-v83-linux-ia32-glibc, node-v83-linux-x64-glibc, node-v83-win32-ia32-unknown, node-v83-win32-x64-unknown]
[2022-02-09T04:24:10.480Z] This problem can often be fixed by running "npm rebuild" on the current system
[2022-02-09T04:24:10.480Z] Original error: Cannot find module '/Users/pak/Documents/azure-night-functions/node_modules/azure-functions-core-tools/bin/workers/node/grpc/src/node/extension_binary/node-v83-darwin-arm64-unknown/grpc_node.node'
[2022-02-09T04:24:10.480Z] Require stack:
[2022-02-09T04:24:10.481Z] - /Users/pak/Documents/azure-night-functions/node_modules/azure-functions-core-tools/bin/workers/node/worker-bundle.js
[2022-02-09T04:24:10.481Z] - /Users/pak/Documents/azure-night-functions/node_modules/azure-functions-core-tools/bin/workers/node/dist/src/nodejsWorker.js
[2022-02-09T04:24:10.620Z] Expected directory: node-v83-darwin-arm64-unknown
[2022-02-09T04:24:10.621Z] Found: [node-v57-darwin-ia32-unknown, node-v57-darwin-x64-unknown, node-v57-linux-ia32-glibc, node-v57-linux-x64-glibc, node-v57-win32-ia32-unknown, node-v57-win32-x64-unknown, node-v64-darwin-ia32-unknown, node-v64-darwin-x64-unknown, node-v64-linux-ia32-glibc, node-v64-linux-x64-glibc, node-v64-win32-ia32-unknown, node-v64-win32-x64-unknown, node-v72-darwin-ia32-unknown, node-v72-darwin-x64-unknown, node-v72-linux-ia32-glibc, node-v72-linux-x64-glibc, node-v72-win32-ia32-unknown, node-v72-win32-x64-unknown, node-v83-darwin-ia32-unknown, node-v83-darwin-x64-unknown, node-v83-linux-ia32-glibc, node-v83-linux-x64-glibc, node-v83-win32-ia32-unknown, node-v83-win32-x64-unknown]
[2022-02-09T04:24:10.621Z] This problem can often be fixed by running "npm rebuild" on the current system
[2022-02-09T04:24:10.621Z] Original error: Cannot find module '/Users/pak/Documents/azure-night-functions/node_modules/azure-functions-core-tools/bin/workers/node/grpc/src/node/extension_binary/node-v83-darwin-arm64-unknown/grpc_node.node'
[2022-02-09T04:24:10.621Z] Require stack:
[2022-02-09T04:24:10.621Z] - /Users/pak/Documents/azure-night-functions/node_modules/azure-functions-core-tools/bin/workers/node/worker-bundle.js
[2022-02-09T04:24:10.621Z] - /Users/pak/Documents/azure-night-functions/node_modules/azure-functions-core-tools/bin/workers/node/dist/src/nodejsWorker.js
[2022-02-09T04:24:10.621Z] internal/modules/cjs/loader.js:905
[2022-02-09T04:24:10.621Z]   throw err;
[2022-02-09T04:24:10.621Z]   ^
[2022-02-09T04:24:10.621Z] Error: Cannot find module './Worker.js'
[2022-02-09T04:24:10.621Z] Require stack:
[2022-02-09T04:24:10.622Z] - /Users/pak/Documents/azure-night-functions/node_modules/azure-functions-core-tools/bin/workers/node/dist/src/nodejsWorker.js
[2022-02-09T04:24:10.622Z]     at Function.Module._resolveFilename (internal/modules/cjs/loader.js:902:15)
[2022-02-09T04:24:10.622Z]     at Function.Module._load (internal/modules/cjs/loader.js:746:27)
[2022-02-09T04:24:10.622Z]     at Module.require (internal/modules/cjs/loader.js:974:19)
[2022-02-09T04:24:10.622Z]     at require (internal/modules/cjs/helpers.js:93:18)
[2022-02-09T04:24:10.622Z]     at Object.<anonymous> (/Users/pak/Documents/azure-night-functions/node_modules/azure-functions-core-tools/bin/workers/node/dist/src/nodejsWorker.js:45:14)
[2022-02-09T04:24:10.622Z]     at Module._compile (internal/modules/cjs/loader.js:1085:14)
[2022-02-09T04:24:10.622Z]     at Object.Module._extensions..js (internal/modules/cjs/loader.js:1114:10)
[2022-02-09T04:24:10.622Z]     at Module.load (internal/modules/cjs/loader.js:950:32)
[2022-02-09T04:24:10.622Z]     at Function.Module._load (internal/modules/cjs/loader.js:790:12)
[2022-02-09T04:24:10.622Z]     at Function.executeUserEntryPoint [as runMain] (internal/modules/run_main.js:76:12) {
[2022-02-09T04:24:10.622Z]   code: 'MODULE_NOT_FOUND',
[2022-02-09T04:24:10.622Z]   requireStack: [
[2022-02-09T04:24:10.622Z]     '/Users/pak/Documents/azure-night-functions/node_modules/azure-functions-core-tools/bin/workers/node/dist/src/nodejsWorker.js'
[2022-02-09T04:24:10.622Z]   ]

即使最後仍能看到 endpoint 的 URL,但是 function 都是不會執行起來,最後還會有 timeout 的情況出現。而從以上的錯誤信息可以看到,其中一個重點就是 M1 的 arm64 結構導致問題發生:

[2022-02-09T04:24:10.479Z] Expected directory: node-v83-darwin-arm64-unknown
[2022-02-09T04:24:10.479Z] Found: [node-v57-darwin-ia32-unknown, node-v57-darwin-x64-unknown, node-v57-linux-ia32-glibc, node-v57-linux-x64-glibc, node-v57-win32-ia32-unknown, node-v57-win32-x64-unknown, node-v64-darwin-ia32-unknown, node-v64-darwin-x64-unknown, node-v64-linux-ia32-glibc, node-v64-linux-x64-glibc, node-v64-win32-ia32-unknown, node-v64-win32-x64-unknown, node-v72-darwin-ia32-unknown, node-v72-darwin-x64-unknown, node-v72-linux-ia32-glibc, node-v72-linux-x64-glibc, node-v72-win32-ia32-unknown, node-v72-win32-x64-unknown, node-v83-darwin-ia32-unknown, node-v83-darwin-x64-unknown, node-v83-linux-ia32-glibc, node-v83-linux-x64-glibc, node-v83-win32-ia32-unknown, node-v83-win32-x64-unknown]
[2022-02-09T04:24:10.480Z] This problem can often be fixed by running "npm rebuild" on the current system

似乎就是相關的工具還沒有支援到 arm64, 但 M1 都推出了一年多了,相信微軟不會放棄我們這批用戶那麼久吧?幸好最後解決方法是出現在一個微細處!

我所安裝的工具

若然你是第一次接觸 Azure Functions,或者遇到同樣問題來到這裡,也先確認一下我們的環境是同樣的!我剛剛測試的時候,使用了以下的工具:

  • Macbook Pro M1
  • Visual Studio Code
  • Extension: Azure functions
  • Node.js 14 LTS (arm64)
  • 透過 npm 安裝了 azure-functions-core-tools

嗯,在上一段落,就是最後一行我透過 npm 安裝了 azure-functions-core-tools,因為我自己較喜歡把各個專案的 dependencies 都分開(就算使用 python 也特別鍾情 venv),所以順利成章就使用 npm 來執行 func 這個屬於 azure-functions-core-tools 用來本地測試的指令。

問題所在

本身也覺得什麼不妥當,忽然想到可能是 node.js 版本的問題,於是我便升級至 node.js 16,問題就出現了!竟然說不支援 node.js 16,細心一看,原來我執行的 Azure Function Runtime 仍然停留在 3.3.1.0

Azure Functions Core Tools
Core Tools Version:       3.0.3904 Commit hash: c345f7140a8f968c5dbc621f8a8374d8e3234206  (64-bit)
Function Runtime Version: 3.3.1.0

[2022-02-09T04:42:31.036Z] Cannot create directory for shared memory usage: /dev/shm/AzureFunctions
[2022-02-09T04:42:31.044Z] System.IO.FileSystem: Access to the path '/dev/shm/AzureFunctions' is denied. Operation not permitted.
[2022-02-09T04:42:38.213Z] /Users/pak/Documents/azure-night-functions/node_modules/azure-functions-core-tools/bin/workers/node/dist/src/nodejsWorker.js:35
[2022-02-09T04:42:38.225Z]         throw message;
[2022-02-09T04:42:38.225Z]         ^
[2022-02-09T04:42:38.226Z] Incompatible Node.js version (v16.14.0). Refer to our documentation to see the Node.js versions supported by each version of Azure Functions: https://aka.ms/functions-node-versions
[2022-02-09T04:42:38.226Z] (Use `node --trace-uncaught ...` to show where the exception was thrown)
[2022-02-09T04:42:38.316Z] /Users/pak/Documents/azure-night-functions/node_modules/azure-functions-core-tools/bin/workers/node/dist/src/nodejsWorker.js:35
[2022-02-09T04:42:38.318Z]         throw message;
[2022-02-09T04:42:38.318Z]         ^
[2022-02-09T04:42:38.318Z] Incompatible Node.js version (v16.14.0). Refer to our documentation to see the Node.js versions supported by each version of Azure Functions: https://aka.ms/functions-node-versions
[2022-02-09T04:42:38.318Z] (Use `node --trace-uncaught ...` to show where the exception was thrown)

查看一次 azure-functions-core-tools 的 github 專頁 ,終於水落石出,原來自從版本 4 之後,安裝的方法不同了!

當我使用了 homebrew 的方法安裝到最新版本的 azure-functions-core-tools 後,問題就迎刃而解,所有 Functions 都順順利執行囉!

解決方法: 使用 brew 安裝最新的 azure-functions-core-tools 工具

換句話說,暫時只有 version 4 的 azure-functions-core-tools 能支援 M1 Macbook, 不論是 node.js 14 或 16 都能夠使用。

而且切記不要使用 npm 來安裝 azure-functions-core-tools,即使之前的專案使用了這個方法,都謹記要先移除舊版本的 tools!

azure-functions-m1-screen-cap.png

留言