Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Updater fails when system folder and webroot folder are on different filesystems #4265

Open
naaador opened this issue Apr 22, 2024 · 0 comments
Assignees

Comments

@naaador
Copy link

naaador commented Apr 22, 2024

Description of the problem
When running the updater and the EE system directory is on a different filesystem from the webroot directory the update will fail when attempting to move the updated theme files into place. I was updating from the CLI, however after reviewing the relevant updater code I believe this would affect upgrades from the control panel as well.

How To Reproduce
Steps to reproduce the behavior:

  1. Create a new deployment from an EE version that isn't current
  2. Relocate the webroot directory to a different filesystem
  3. run "php eecli.php update" and confirm the update
  4. The update process will fail with the error below

Error Messages
image


Error caught:
Class 'ExpressionEngine\Updater\Service\Updater\UpdaterException' not found
ee/updater/ExpressionEngine/Updater/Service/Updater/FileUpdater.php:52
#0 ee/updater/ExpressionEngine/Updater/Service/Updater/Runner.php(48): ExpressionEngine\Updater\Service\Updater\FileUpdater->updateFiles()
#1 [internal function]: ExpressionEngine\Updater\Service\Updater\Runner->updateFiles()
#2 ee/updater/ExpressionEngine/Updater/Service/Updater/SteppableTrait.php(94): call_user_func_array()
#3 ee/updater/ExpressionEngine/Updater/Service/Updater/Runner.php(316): ExpressionEngine\Updater\Service\Updater\Runner->runStepParent()
#4 ee/ExpressionEngine/Cli/Commands/CommandUpdate.php(132): ExpressionEngine\Updater\Service\Updater\Runner->runStep()
#5 ee/ExpressionEngine/Cli/Commands/CommandUpdate.php(102): ExpressionEngine\Cli\Commands\CommandUpdate->updaterMicroapp()
#6 ee/ExpressionEngine/Cli/Commands/CommandUpdate.php(109): ExpressionEngine\Cli\Commands\CommandUpdate->runUpdater()
#7 ee/ExpressionEngine/Cli/Commands/CommandUpdate.php(434): ExpressionEngine\Cli\Commands\CommandUpdate->runUpdater()
#8 ee/ExpressionEngine/Cli/Commands/CommandUpdate.php(329): ExpressionEngine\Cli\Commands\CommandUpdate->upgradeFromDownloadedVersion()
#9 ee/ExpressionEngine/Cli/Commands/CommandUpdate.php(88): ExpressionEngine\Cli\Commands\CommandUpdate->runUpgrade()
#10 ee/ExpressionEngine/Cli/Cli.php(158): ExpressionEngine\Cli\Commands\CommandUpdate->handle()
#11 ee/ExpressionEngine/Core/Core.php(141): ExpressionEngine\Cli\Cli->process()
#12 ee/ExpressionEngine/Core/Core.php(113): ExpressionEngine\Core\Core->bootCli()
#13 ee/ExpressionEngine/Boot/boot.php(161): ExpressionEngine\Core\Core->run()
#14 ee/eecli.php(105): require_once('...')
#15 {main}

Environment Details:

  • Version: Encountered when updating to EE 6.4.17, but I've reviewed the area of the updater where the failure occurred and it doesn't appear this has been changed recently.
  • PHP Version: 8.1.27
  • MySQL Version: MariaDB 10.6.12
  • OS: Ubuntu 22.04
  • Web Server: nginx 1.18.0

Possible Solution
This issue appears to be caused by the use of the PHP "rename" function in Filesystem.php's rename, which in turn is being called by the move function in FileUpdater.php

The php rename function does not support moving directories between filesystems, which is documented in this PHP bug report. This can be illustrated with the following snippet:


<?php

$source = "/tmp/testdir";
// where 'externalfs' is a mount point for a different filesystem than /tmp is located on
$dest = "/mnt/externalfs/testdirmoved";

rename($source, $dest);

Which will result in the error:


PHP Warning:  rename(): The first argument to copy() function cannot be a directory in /root/test.php on line 7
PHP Warning:  rename(/tmp/testdir,/mnt/externalfs/testdirmoved): Invalid cross-device link in /root/test.php on line 7

A possible solution would be performing a copy, then delete, with the disadvantage that this would be less efficient when the source and destination are on the same filesystem. It could be possible to first check whether the source and target are on the same filesystem using stat().

Additional context
My webroot directory is on shared filesystem, while each server in the cluster has its own copy of the system files (for performance reasons). I was able to work around this issue by unmounting my webroot directory and copying the themes directory from the share, then copying the themes directory back to the share and re-mounting after the update completed.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

2 participants