Wenn euer DRUSH auch mit folgender Meldung den Dienst verweigert:Directory /tmp/drush exists, but is not writable. Please check directory permissions.
Drush must have a writable cache directory; please insure that one of the following locations is writable: /home/www/usrDummy,/tmp, habe ich einen Tipp für euch...
Ich wollte nur schnell das Drupal CMS auf einem meiner Testsysteme via Drupal Shell: DRUSH aktualisieren ("./drush up"), doch das sollte schwieriger werden als ich dachte!
Drush war nicht nutzbar und brach bei jedem Befehl mit der oberhalb dargestellten Meldung ab. Dabei lief es doch vor einigen Tagen noch!?!
Die Ursache:
Drush benötigt ein temporäres Cache Verzeichnis, um seine Arbeiten erfolgreich verrichten zu können. Dabei geht es insbesondere um das Zwischenspeichern von Verzeichnis-Backups, Downloads und ähnliches.
Dieses Verzeichnis wird von Drush automatisch in der Datei:
"drush/includes/environment.inc:"
ermittelt:
/*
* The path to the global cache directory.
*
* @param subdir
* Return the specified subdirectory inside the global
* cache directory instead. The subdirectory is created.
*/
function drush_directory_cache($subdir = '') {
$cache_locations = array();
if (getenv('CACHE_PREFIX')) {
$cache_locations[getenv('CACHE_PREFIX')] = 'cache';
}
$home = drush_server_home();
if ($home) {
$cache_locations[$home] = '.drush/cache';
}
$cache_locations[drush_find_tmp()] = 'drush/' . getenv('USER') . '/cache';
foreach ($cache_locations as $base => $dir) {
if (!empty($base) && is_writable($base)) {
$cache_dir = $base . '/' . $dir;
if (!empty($subdir)) {
$cache_dir .= '/' . $subdir;
}
if (drush_mkdir($cache_dir)) {
return $cache_dir;
}
else {
// If the base directory is writable, but the cache directory
// is not, then we will get an error. The error will be displayed,
// but we will still call drush_clear_error so that we can go
// on and try the next location to see if we can find a cache
// directory somewhere.
drush_clear_error();
}
}
}
return drush_set_error('DRUSH_NO_WRITABLE_CACHE', dt('Drush must have a writable cache directory; please insure that one of the following locations is writable: @locations',
array('@locations' => implode(',', array_keys($cache_locations)))));
}
?>
Der für uns interessante Code findet sich allerdings in der Funktion: "drush_find_tmp()" (drush/includes/filesystem.inc);
/**
* Returns the path to a temporary directory.
*
* This is a custom version of Drupal's file_directory_path().
* We can't directly rely on sys_get_temp_dir() as this
* path is not valid in some setups for Mac, and we want to honor
* an environment variable (used by tests).
*/
function drush_find_tmp() {
static $temporary_directory;
if (!isset($temporary_directory)) {
$directories = array();
// Operating system specific dirs.
if (drush_is_windows()) {
// get user specific and operating system temp folders from system environment variables
// see http://www.microsoft.com/resources/documentation/windows/xp/all/proddoc…
$tempdir = getenv('TEMP');
if (isset($tempdir)) {
$directories[] = $tempdir;
}
$tmpdir = getenv('TMP');
if (isset($tmpdir)) {
$directories[] = $tmpdir;
}
$windir = getenv('WINDIR');
if (isset($windir)) {
// WINDIR itself is not writable, but it always contains a /Temp dir,
// which is the system-wide temporary directory on older versions. Newer
// versions only allow system processes to use it.
$directories[] = $windir . '/Temp';
}
}
else {
$directories[] = '/tmp';
}
// This function exists in PHP 5 >= 5.2.1, but drush
// requires PHP 5 >= 5.2.0, so we check for it.
if (function_exists('sys_get_temp_dir')) {
$directories[] = sys_get_temp_dir();
}
foreach ($directories as $directory) {
if (is_dir($directory) && is_writable($directory)) {
$temporary_directory = $directory;
break;
}
}
if (empty($temporary_directory)) {
// If no directory has been found, create one in cwd.
$temporary_directory = drush_cwd() . '/tmp';
drush_mkdir($temporary_directory, TRUE);
if (!is_dir($directory)) {
return drush_set_error('DRUSH_UNABLE_TO_CREATE_TMP_DIR', dt("Unable to create a temporary directory."));
}
drush_register_file_for_deletion($temporary_directory);
}
}
return $temporary_directory;
}
?>
Wie der Code zeigt, wird das Verzeichnis automatisch ermittelt und (wenn es sich nicht um ein Windows System handelt) per Fallback auf "/tmp" gesetzt.
Das ist schade, denn Ergebnis dieser Analyse ist, dass wir keine gute Möglichkeit haben, das Verzeichnis beispielsweise in der "drushrc.php" manuell zu benennen / korrigieren.
1. Fazit: Mit Drush Konfiguration kommen wir nicht weit.
Also ging es ab in das Verzeichnis "/tmp" und hier war die Ursache schnell gefunden:
Auf dem Testsystem trenne ich die einzelnen System-User und ein anderer User hatte in dem gemeinsamen Verzeichnis "/tmp" bereits den Ordner "drush" sowie "drush-env" erstellt (siehe Screenshot im Anhang).
Die Berechtigungen waren so vergeben, dass auch nur der Ersteller in das Verzeichnis schreiben konnte. Somit war die Ursache gefunden!
2. Fazit: Sobald ein System-User die genannten Drush tmp-Verzeichnisse erstellt hat, können diese nicht mehr von anderen Benutzern bearbeitet werden. Also ein Berechtigungsproblem.
Die Lösung:
... ist nicht ganz so schön aber wirkungsvoll (insb. da es sich ohnehin nur um ein Testsystem handelt):
Ich habe die Verzeichnisse "tmp/drush" & "tmp/drush-env" mit dem ursprünglichen Benutzer nun (identisch zum /tmp-Verzeichnis selbst) mit den Rechten "0777" versehen, sodass die einzelnen User darunter ihre eigenen (geschützten) Verzeichnisse erstellen können.
Noch schöner wäre eine zukünftige Drush Lösung, die ein Fallback per drushrc.php - Wert manuell zulässt, sodass der zu verwendende Pfad in der Konfiguration überschrieben werden kann.
Die Lösung hat euch geholfen?
Habt ihr Anmerkungen oder eine bessere Lösung? Dann hinterlasst doch bitte einen Kommentar!
Vielen Dank!