There seems to be a bug in update/app/code/Magento/Update/CronReadinessCheck.php
The following code can be used as a replacement for CronReadinessCheck.php that gives proper logging output
<?php
/**
* Copyright © 2016 Magento. All rights reserved.
* See COPYING.txt for license details.
*/
namespace Magento\Update;
/**
* This class is used by Updater cron script to check if it can be run properly
*/
class CronReadinessCheck
{
/**
* Basename to Updater status file
*/
const CRON_JOB_STATUS_FILE = '.update_cronjob_status';
const UPDATE_CRON_LOG_FILE = 'var/log/update.log';
/**#@+
* Keys used in status file
*/
const KEY_READINESS_CHECKS = 'readiness_checks';
const KEY_FILE_PERMISSIONS_VERIFIED = 'file_permissions_verified';
const KEY_ERROR = 'error';
const KEY_CURRENT_TIMESTAMP = 'current_timestamp';
const KEY_LAST_TIMESTAMP = 'last_timestamp';
/**#@-*/
/**
* Setup cron job status file name
*/
const SETUP_CRON_JOB_STATUS_FILE = '.setup_cronjob_status';
/**#@+
* Keys from .setup_cronjob_status file
*/
const KEY_FILE_PATHS = 'file_paths';
const KEY_LIST = 'list';
/**#@-*/
/**
* Run Cron job readiness check
*
* @return bool
*/
public function runReadinessCheck()
{
$resultJsonRawData = ['readiness_checks' => []];
$success = true;
$permissionInfo = $this->checkPermissionsRecursively();
$nonWritablePaths = $permissionInfo->getNonWritablePaths();
$nonReadablePaths = $permissionInfo->getNonReadablePaths();
if ($permissionInfo->containsPaths())
{
$error = '';
if (!empty($nonWritablePaths)) {
$error .= '<br/>Found non-writable path(s):<br/>' .
implode('<br/>', $nonWritablePaths);
}
if (!empty($nonReadablePaths)) {
$error .= '<br/>Found non-readable path(s):<br/>' .
implode('<br/>', $nonReadablePaths);
}
$resultJsonRawData[self::KEY_READINESS_CHECKS][self::KEY_ERROR] = $error;
$resultJsonRawData[self::KEY_READINESS_CHECKS][self::KEY_FILE_PERMISSIONS_VERIFIED] = false;
$success = false;
} else {
$resultJsonRawData[self::KEY_READINESS_CHECKS][self::KEY_FILE_PERMISSIONS_VERIFIED] = true;
}
if (file_exists(MAGENTO_BP . '/var/' . self::CRON_JOB_STATUS_FILE)) {
$jsonData = json_decode(file_get_contents(MAGENTO_BP . '/var/' . self::CRON_JOB_STATUS_FILE), true);
if (isset($jsonData[self::KEY_CURRENT_TIMESTAMP])) {
$resultJsonRawData[self::KEY_LAST_TIMESTAMP] = $jsonData[self::KEY_CURRENT_TIMESTAMP];
}
}
$resultJsonRawData[self::KEY_CURRENT_TIMESTAMP] = time();
$resultJson = json_encode($resultJsonRawData, JSON_PRETTY_PRINT | JSON_UNESCAPED_SLASHES);
file_put_contents(MAGENTO_BP . '/var/' . self::CRON_JOB_STATUS_FILE, $resultJson);
// If non-accessible paths are found, log an 'error' entry for the same in update.log
if ( !$success ) {
$outputString = 'Cron readiness check failure!' . PHP_EOL;
if (!empty($nonWritablePaths)) {
$outputString .= "Found following non-writable paths: \t" . implode(PHP_EOL . "\t", $nonWritablePaths);
}
if (!empty($nonReadablePaths)) {
$outputString .= "Found following non-readable paths: \t" . implode(PHP_EOL . "\t", $nonReadablePaths);
}
$updateLoggerFactory = new UpdateLoggerFactory();
$logger = $updateLoggerFactory->create();
$logger->log(\Psr\Log\LogLevel::ERROR, $outputString);
}
return $success;
}
/**
* Check file permissions recursively
*
* @return PermissionInfo
*/
private function checkPermissionsRecursively()
{
// For backward compatibility, initialize the list wth magento root directory.
$dirAndFileList[] = '';
// Get the list of magento specific directories and files
$setupCronJobStatusFilePath = MAGENTO_BP . '/var/' . self::SETUP_CRON_JOB_STATUS_FILE;
if (is_readable($setupCronJobStatusFilePath)) {
$fileContents = json_decode(file_get_contents($setupCronJobStatusFilePath), true);
if (isset($fileContents[self::KEY_FILE_PATHS][self::KEY_LIST])) {
$dirAndFileList = $fileContents[self::KEY_FILE_PATHS][self::KEY_LIST];
}
}
$nonWritablePaths = [];
$nonReadablePaths = [];
foreach ($dirAndFileList as $path) {
$path = MAGENTO_BP . '/' . $path;
if (is_dir($path)) {
try {
$filesystemIterator = new \RecursiveIteratorIterator(
new \RecursiveDirectoryIterator($path),
\RecursiveIteratorIterator::SELF_FIRST
);
$filesystemIterator = new ExcludeFilter(
$filesystemIterator,
[
MAGENTO_BP . '/update',
MAGENTO_BP . '/var/session',
'.git',
'.idea'
]
);
foreach ($filesystemIterator as $item) {
$path = $item->__toString();
if (!is_writable($path)) {
$nonWritablePaths[] = $path;
}
}
} catch (\UnexpectedValueException $e) {
$nonReadablePaths[] = $path;
}
} else {
if (!is_writable($path)) {
$nonWritablePaths[] = $path;
}
}
}
return new PermissionInfo($nonWritablePaths, $nonReadablePaths);
}
}