generated from jric11/baseProject
ChatGPT's update to harden software and run db updates.
This commit is contained in:
@@ -8,21 +8,22 @@ $base=new Base();$settings=$base->getSettings();$db=$base->connect();
|
||||
$engines=$db->query("SELECT ENGINE FROM information_schema.TABLES WHERE TABLE_SCHEMA=DATABASE() AND TABLE_TYPE='BASE TABLE'")->fetchAll(PDO::FETCH_COLUMN);
|
||||
if(array_filter($engines,static fn($v)=>$v!=='InnoDB'))throw new RuntimeException('Nontransactional tables require a maintenance-window locked backup.');
|
||||
$file=$directory.DIRECTORY_SEPARATOR.'hcr-'.gmdate('Ymd-His').'-'.bin2hex(random_bytes(3)).'.sql';
|
||||
$partial=$file.'.partial';$handle=fopen($partial,'x');if(!$handle)throw new RuntimeException('Cannot create protected backup output.');fclose($handle);chmod($partial,0600);
|
||||
$config=tempnam($directory,'hcr-connection-');chmod($config,0600);
|
||||
$partial=$file.'.partial';$config=null;
|
||||
$quote=static fn($value)=>'"'.str_replace(["\\",'"',"\r","\n"],["\\\\",'\\"','\\r','\\n'],(string)$value).'"';
|
||||
$options="[client]\nhost=".$quote($settings->DatabaseServer)."\nport=".(int)($settings->DatabasePort??3306)."\nuser=".$quote($settings->DatabaseUser)."\npassword=".$quote($settings->DatabasePassword)."\n";
|
||||
$ca=getenv('HCR_DB_TLS_CA');if($ca)$options.='ssl-ca='.$quote($ca)."\nssl-verify-server-cert\n";
|
||||
try{
|
||||
$handle=fopen($partial,'x');if(!$handle)throw new RuntimeException('Cannot create protected backup output.');fclose($handle);chmod($partial,0600);
|
||||
$config=tempnam($directory,'hcr-connection-');if($config===false)throw new RuntimeException('Cannot create protected connection configuration.');chmod($config,0600);
|
||||
file_put_contents($config,$options);
|
||||
$command=[getenv('HCR_DUMP_BINARY')?:'mariadb-dump','--defaults-extra-file='.$config,'--single-transaction','--quick','--routines','--events','--triggers','--hex-blob','--databases',(string)$settings->DatabaseName,'--result-file='.$partial];
|
||||
$process=proc_open($command,[0=>['pipe','r'],1=>['pipe','w'],2=>['pipe','w']],$pipes);
|
||||
if(!is_resource($process))throw new RuntimeException('Backup process could not start.');
|
||||
fclose($pipes[0]);$out=stream_get_contents($pipes[1]);$error=stream_get_contents($pipes[2]);fclose($pipes[1]);fclose($pipes[2]);
|
||||
if(proc_close($process)!==0){error_log('Backup process failed: '.$error);throw new RuntimeException('Backup failed; inspect the protected backup error log.');}
|
||||
if(!is_file($partial)||filesize($partial)<100||!str_contains(file_get_contents($partial),'Dump completed on'))throw new RuntimeException('Backup completion could not be confirmed.');
|
||||
if(!BackupValidation::complete($partial))throw new RuntimeException('Backup completion could not be confirmed.');
|
||||
if(!rename($partial,$file))throw new RuntimeException('Cannot finalize completed backup.');
|
||||
chmod($file,0600);
|
||||
$metadata=['created_utc'=>gmdate(DATE_ATOM),'bytes'=>filesize($file),'sha256'=>hash_file('sha256',$file)];file_put_contents($file.'.json',json_encode($metadata,JSON_PRETTY_PRINT));chmod($file.'.json',0600);
|
||||
echo json_encode(['backup'=>$file]+$metadata),"\n";
|
||||
}finally{if(is_file($config))unlink($config);if(is_file($partial))unlink($partial);}
|
||||
}finally{if(is_string($config)&&is_file($config))unlink($config);if(is_file($partial))unlink($partial);}
|
||||
|
||||
Reference in New Issue
Block a user