php fopen() 在同一进程中使用 Symfony/Component/Process class 创建的文件没有这样的文件或目录

php fopen() No such file or directory for file created in same process using Symfony/Component/Process class

我正在尝试制作 mysqldump 备份并将该备份上传到 aws s3。一切都在单独工作,但是当在一个脚本中尝试两者时,即使 file_exists 无法读取该文件,fopen 也找不到该文件。 请有人帮忙 这是代码

function db_backup($db)
{
    date_default_timezone_set("Asia/Kolkata");
    $DBUSER = env('DB_USERNAME');
    $DBPASSWD = env('DB_PASSWORD');
    $today = date('YmdHis');
    $output_file = "{$db}_{$today}.sql.gz";
    if (!is_dir(storage_path('backups'))) mkdir(storage_path('backups'));
    $path = escapeshellarg(storage_path("backups/{$output_file}"));
    $process = new Process(
        sprintf(
            'mysqldump --routines=true --compact --comments=false -u%s -p%s %s |gzip > %s',
            escapeshellarg($DBUSER),
            escapeshellarg($DBPASSWD),
            $db,
            $path
        )
    );
    try {
        $process->run();
        if ($process->isSuccessful()) {
            if (file_exists($path)) {
                //$aws = resolve(S3Service::class);
                //$aws->upload($path, $output_file);
                Log::info("Daily Backup Successs {$path}");
            } else {
                echo "File Not Found: {$path} \n";
            }
        }
    } catch (ProcessFailedException $err) {
        Log::error('Daily Backup Failed', (array) $err);
    }
}

总是找不到文件,但备份成功。

Symfony 的 Process() 构造函数接受一个数组,而不是一个字符串。这里有一些 useful examples in the documentation 概述了正确的用法。

幸运的是,有一个静态助手 Process::fromShellCommandline(),您可以使用它从字符串命令创建新的 Process 对象。

然后您可以将代码修改为类似于:

$process = Process::fromShellCommandline(sprintf(
'mysqldump --routines=true --compact --comments=false -u%s -p%s %s |gzip > %s',            escapeshellarg($DBUSER),
    escapeshellarg($DBPASSWD),
    $db,
    $path
));

您没有收到任何错误的原因可能是您的错误报告。为了证明这个工作我不得不修改你的脚本和 运行 命令 'echo "%s:%s %s" | gzip > %s', 而不是 ymmv.

只需从文件路径中删除 escapeshellarg() 函数即可解决问题。 由于该函数 fopen 无法读取该路径。

function db_backup($db)
{
date_default_timezone_set("Asia/Kolkata");
$DBUSER = env('DB_USERNAME');
$DBPASSWD = env('DB_PASSWORD');
$today = date('YmdHis');
$output_file = "{$db}_{$today}.sql.gz";
if (!is_dir(storage_path('backups'))) mkdir(storage_path('backups'));
$path = storage_path("backups/{$output_file}");
$process = new Process(
    sprintf(
        'mysqldump --routines=true --compact --comments=false -u%s -p%s %s |gzip > %s',
        escapeshellarg($DBUSER),
        escapeshellarg($DBPASSWD),
        $db,
        $path
    )
);
try {
    $process->run();
    if ($process->isSuccessful()) {
        if (file_exists($path)) {
            //$aws = resolve(S3Service::class);
            //$aws->upload($path, $output_file);
            Log::info("Daily Backup Successs {$path}");
        } else {
            echo "File Not Found: {$path} \n";
        }
    }
} catch (ProcessFailedException $err) {
    Log::error('Daily Backup Failed', (array) $err);
}
}