1. 程式人生 > 實用技巧 >【應用服務 App Service】NodeJS +Egg 釋出到App Service時遇見 [ERR_SYSTEM_ERROR]: A system error occurred:uv_os_get_passwd returned ENOENT(no such file or directory)

【應用服務 App Service】NodeJS +Egg 釋出到App Service時遇見 [ERR_SYSTEM_ERROR]: A system error occurred:uv_os_get_passwd returned ENOENT(no such file or directory)

問題情形

本地NodeJS應用使用Egg腳手架構建,本地執行測試完全沒有問題,釋出後App Service後不能執行。通過登入到kudu後(https://<your web site>.scm.chinacloudsites.cn)後,在日誌中發現找不到一個檔案或路徑的錯誤。通過在kudu的CMD視窗執行npm start命令,發現錯誤是一致,懷疑是對Egg中某個框架的不支援。

詳細日誌

Application has thrown an uncaught exception and is terminated:
SystemError [ERR_SYSTEM_ERROR]: A system error occurred: uv_os_get_passwd returned ENOENT (no such file or directory)
    at Object.userInfo (os.js:272:11)
    at module.exports (D:\home\site\wwwroot\pynode\node_modules\node-homedir\index.js:10:26)
at AppWorkerLoader.getHomedir (D:\home\site\wwwroot\pynode\node_modules\egg-core\lib\loader\egg_loader.js:163:36) at AppWorkerLoader.getAppInfo (D:\home\site\wwwroot\pynode\node_modules\egg-core\lib\loader\egg_loader.js:174:23) at new EggLoader (D:\home\site\wwwroot\pynode\node_modules\egg-core\lib\loader\egg_loader.js:87:25) at new AppWorkerLoader (D:\home\site\wwwroot\pynode\node_modules\egg\lib\loader\app_worker_loader.js:9:1) at new EggCore (D:\home\site\wwwroot\pynode\node_modules\egg-core\lib\egg.js:118:19) at new EggApplication (D:\home\site\wwwroot\pynode\node_modules\egg\lib\egg.js:43:5) at new Application (D:\home\site\wwwroot\pynode\node_modules\egg\lib\application.js:60:5) at Object.<anonymous> (D:\home\site\wwwroot\pynode\index.js:3:13)

在詳細的log檔案中,可以看見全面的錯誤資訊。並指出了報錯的原始檔為:(D:\home\site\wwwroot\pynode\node_modules\node-homedir\index.js:10:26),在原始碼中,找出了問題的根源。

問題原因

node_modules\node-homedir\index.js 原始碼:

 1 'use strict';
 2 
 3 const os = require('os');
 4 
 5 module.exports = () => {
 6   if (process.env.MOCK_HOME_DIR) return process.env.MOCK_HOME_DIR;
7 8 if (typeof os.userInfo === 'function') { 9 try { 10 const homedir =os.userInfo().homedir; 11 if (homedir) return homedir; 12 } catch (err) { 13 if (err.code !== 'ENOENT') throw err; 14 } 15 } 16 17 if (typeof os.homedir === 'function') { 18 return os.homedir(); 19 } 20 21 return process.env.HOME; 22 };

在第十行程式碼中,使用了os物件,而在App Service中,由於是sandbox 模式下,所以某些操作被禁止了。關於禁止的說明可以參考:https://github.com/projectkudu/kudu/wiki/Azure-Web-App-sandbox#general-sandbox-restrictions

解決方案

在檢視原始碼後,想解決它就有兩種辦法:

1)在修改node-homedir\index.js中的原始碼,把裡面os.userInfo().homedir 的部分替換成在App Service中的Homedir路徑,hardcode這一部分。如const homedir =”D:\home\site\wwwroot\“;//os.userInfo().homedir;

2) 最快速且無程式碼改動方案。在App Service的應用程式設定中(Applicaiton Settings)新增一個名MOCK_HOME_DIR的設定,並設定其值為D:\home\site\wwwroot\ (為應用程式釋出的預設路徑)。 這樣node-homedir的原始碼就不會進入到os部分。直接在第一行就返回需要的homedir.

PS: 這裡是把NodeJS的應用釋出在Windows的環境中遇見的問題,如釋出在App Service For Linux則可以避免類似問題。