AWS启动模板UserData中npm install执行目录错误如何解决
问题根因
出现这个问题的核心原因有三个:
su -属于登录式用户切换,启动的子shell会自动将工作目录重置为ec2-user的家目录/home/ec2-user,你在外层root上下文执行的cd /home/ec2-user/xdf操作,仅对root进程生效,完全不会影响su拉起的ec2-user子shell的工作路径。su -c启动的是非交互式shell,默认不会自动加载用户目录下.bashrc中配置的nvm环境变量,你之前写的nvm use命令实际没有把nvm安装的node/npm路径加载到执行环境中,就算去掉su直接执行npm,调用的也不是nvm安装的版本,执行路径同样会异常。- 跨用户切换操作同一份目录文件,还会引发权限混乱:root创建的文件ec2-user无修改权限,ec2-user创建的文件root操作也会报错,为后续服务运行埋下隐患。
修复方案
不要在外层root shell里切目录再切用户执行命令,把所有需要ec2-user身份执行的操作(nvm安装、node安装、代码拉取、依赖安装、服务启动)统一放到同一个su执行块里,在块内明确切换工作目录,同时手动加载nvm的环境变量。
修正后的完整UserData脚本如下:
#!/bin/bash nodev='8.11.2' nvmv='0.33.11' PROJECT_PATH="/home/ec2-user/xdf" # root权限安装系统依赖git yum install git -y # 所有ec2-user身份的操作统一在同一个子shell执行 su - ec2-user -c " # 先加载用户环境变量,保证nvm可被识别 source ~/.bashrc # 安装nvm curl -o- https://raw.githubusercontent.com/nvm-sh/nvm/v${nvmv}/install.sh | bash # 安装完nvm重新加载环境 source ~/.bashrc # 安装并切换到指定node版本 nvm install ${nodev} nvm use ${nodev} nvm alias default ${nodev} # 拉取代码 cd /home/ec2-user git clone https://github.com/xyz/xdf.git # 明确切换到项目目录再执行npm相关操作 cd ${PROJECT_PATH} npm install npm install pm2 -g # 启动服务 pm2 run index.js " # 生成test.txt后修正属主,避免权限问题 echo "test" > ${PROJECT_PATH}/test.txt chown ec2-user:ec2-user ${PROJECT_PATH}/test.txt
优化建议
- 不要在root和普通用户上下文来回切换操作同一个项目目录,很容易出现node_modules目录权限异常,导致服务启动失败。
- 如果需要服务开机自启,在pm2启动服务后追加
pm2 startup && pm2 save命令,否则实例重启后服务不会自动拉起。 - UserData脚本默认以root身份执行,所有路径尽量写绝对路径,不要依赖shell当前工作目录,避免路径错乱。
内容的提问来源于stack exchange,提问作者Prithvi Emmanuel Machado
相关产品推荐
相关产品推荐

