Win10 Vagrant环境创建软链接报Input/output error故障排查
Vagrant(Win10宿主机)共享目录创建软链接报Input/output error排查
问题背景
- 宿主机环境:Windows 10
- 环境方案:Vagrant自动化配置Linux运行环境
- 前置已解决问题:首次
vagrant up触发的NTFS相关错误、第二次启动遇到的跨系统换行符兼容问题 - 当前故障:部署过程中创建符号链接时抛出
Input/output error,分别以管理员身份在PhpStorm内置终端、系统CMD中执行操作均稳定复现
核心报错
软链接创建阶段报错信息如下:
default: ln: failed to create symbolic link '/var/xxxxxx-api-v2/deploy/helper/update_composer.sh': Input/output error
前置关联日志
报错触发前,终端在Composer依赖安装阶段已输出异常:
default: - Installing aws/aws-sdk-php (3.185.10): Extracting archive default: - Installing google/apiclient-services (v0.255.0): Extracting archive default: 0/2 [>---------------------------] 0% Install of aws/aws-sdk-php failed default: Install of google/apiclient-services failed default: default: In Filesystem.php line 330: default: default: Could not delete /var/xxxxxx-api-v2/app/vendor/composer/5316bb55/aws-aws-sd default: k-php-667a83e/src/data:
上述Composer依赖安装失败、临时文件无法删除的问题,和后续软链接创建报错为同一根因导致的连锁故障,不存在先后因果关系。
疑似触发点
经排查,部署脚本中执行失败的为以下两条软链接创建命令之一:
sudo -u www-data ln -s /var/${PROJECT_NAME}/deploy/helper/update_composer_dev.sh /var/${PROJECT_NAME}/deploy/helper/update_composer.sh
sudo -u www-data ln -s /var/${PROJECT_NAME}/deploy/helper/update_composer_prod.sh /var/${PROJECT_NAME}/deploy/helper/update_composer.sh
关联脚本说明
上述命令涉及的两个脚本仅运行参数存在差异:
- 开发版
update_composer_dev.sh内容:
#!/bin/bash cd ${0%/*} PROJECT_NAME=$(cat ../../deploy/config/project_name) cd ../../app sudo -u www-data COMPOSER_HOME=/var/tmp/${PROJECT_NAME}/.composer HOME=/var/tmp/${PROJECT_NAME} php composer.phar self-update --2 sudo -u www-data COMPOSER_HOME=/var/tmp/${PROJECT_NAME}/.composer php composer.phar update
- 生产版
update_composer_prod.sh差异点:移除self-update后的--2参数,最后一行composer.phar update命令追加--no-dev参数,其余内容与开发版完全一致。
根因说明
故障核心原因是Vagrant默认挂载的Windows宿主机共享目录存在两个配置缺陷:
- VirtualBox默认未开启共享目录的软链接支持,哪怕Windows端用管理员身份运行终端,虚拟机内部发起的软链接创建请求也会被宿主机拦截,直接返回IO错误
- 默认挂载配置下共享目录的属主、权限与虚拟机内www-data用户不匹配,导致Composer解压依赖、删除临时文件时权限不足,触发安装失败、文件无法删除的报错
修复步骤
- 执行
vagrant halt完全关闭运行中的虚拟机,确保配置修改生效 - 打开项目根目录下的Vagrantfile,修改共享目录挂载配置,将目录属主直接映射为www-data用户(Debian/Ubuntu系下www-data的默认uid/gid均为33),同时设置统一的文件、目录权限:
config.vm.synced_folder ".", "/var/xxxxxx-api-v2", type: "virtualbox", mount_options: ["dmode=775,fmode=775,uid=33,gid=33"] - 在Vagrantfile中追加VirtualBox底层配置,开启对应共享目录的软链接支持:
config.vm.provider "virtualbox" do |vb| vb.customize ["setextradata", :id, "VBoxInternal2/SharedFoldersEnableSymlinksCreate/#{File.basename(Dir.pwd)}", "1"] end - 执行
vagrant reload重新加载虚拟机配置,重启完成后重新触发部署流程即可。
性能优化备选方案
如果修改配置后仍偶发共享目录IO错误,可将Composer依赖目录、运行时缓存目录这类需要大量写入操作的路径挂载为虚拟机本地tmpfs,完全绕过Windows与Linux的文件系统兼容问题,同时能大幅提升Composer、应用运行速度:
config.vm.synced_folder "app/vendor", "/var/xxxxxx-api-v2/app/vendor", type: "tmpfs" config.vm.synced_folder "app/runtime", "/var/xxxxxx-api-v2/app/runtime", type: "tmpfs"
注意:tmpfs为内存存储,虚拟机重启后目录内的内容会清空,需要在部署流程中重新执行Composer依赖安装操作。
内容的提问来源于stack exchange,提问作者Dylan Warwick
相关产品推荐
相关产品推荐

