1C-Bitrix 25.700.0
Загрузка...
Поиск...
Не найдено
backup.php
См. документацию.
1<?php
2
8
9if (ini_get('short_open_tag') == 0 && strtoupper(ini_get('short_open_tag')) != 'ON')
10{
11 die("Error: short_open_tag parameter must be turned on in php.ini\n");
12}
13
14error_reporting(E_ALL & ~E_NOTICE & ~E_DEPRECATED & ~E_WARNING);
15define('START_TIME', microtime(1));
16define('BX_FORCE_DISABLE_SEPARATED_SESSION_MODE', true);
17define('CLI', defined('BX_CRONTAB') && BX_CRONTAB === true || !$_SERVER['DOCUMENT_ROOT']);
18
19if (!defined('NOT_CHECK_PERMISSIONS'))
20{
21 define('NOT_CHECK_PERMISSIONS', true);
22}
23
24$NS = []; // NewState
25
26if (CLI && defined('BX_CRONTAB')) // start from cron_events.php
27{
28 IncludeModuleLangFile($_SERVER['DOCUMENT_ROOT'] . '/bitrix/modules/main/admin/dump.php');
29
30 if (IntOption('dump_auto_enable') != 1)
31 {
32 return;
33 }
34
35 $l = COption::GetOptionInt('main', 'last_backup_start_time', 0);
36 if (time() - $l < IntOption('dump_auto_interval') * 86400)
37 {
38 return;
39 }
40
41 $min_left = IntOption('dump_auto_time') - date('H') * 60 - date("i");
42 if ($min_left > 0 || $min_left < -60)
43 {
44 return;
45 }
46
47 define('LOCK_FILE', $_SERVER['DOCUMENT_ROOT'] . '/bitrix/backup/auto_lock');
48
49 if (!file_exists($_SERVER['DOCUMENT_ROOT'] . '/bitrix/backup'))
50 {
51 mkdir($_SERVER['DOCUMENT_ROOT'] . '/bitrix/backup');
52 }
53
54 if (file_exists(LOCK_FILE))
55 {
56 if (!($time = file_get_contents(LOCK_FILE)))
57 {
58 RaiseErrorAndDie('Can\'t read file: ' . LOCK_FILE, 1);
59 }
60
61 if ($time + 86400 > time())
62 {
63 return;
64 }
65 else
66 {
67 ShowBackupStatus('Warning! Last backup has failed');
69 "SEVERITY" => "WARNING",
70 "AUDIT_TYPE_ID" => "BACKUP_ERROR",
71 "MODULE_ID" => "main",
72 "ITEM_ID" => LOCK_FILE,
73 "DESCRIPTION" => GetMessage('AUTO_LOCK_EXISTS_ERR', ['#DATETIME#' => ConvertTimeStamp($time)]),
74 ]);
75
76 foreach (GetModuleEvents("main", "OnAutoBackupUnknownError", true) as $arEvent)
77 {
78 ExecuteModuleEventEx($arEvent, [['TIME' => $time]]);
79 }
80
81 unlink(LOCK_FILE) || RaiseErrorAndDie('Can\'t delete file: ' . LOCK_FILE, 2);
82 }
83 }
84
85 if (!file_put_contents(LOCK_FILE, time()))
86 {
87 RaiseErrorAndDie('Can\'t create file: ' . LOCK_FILE, 3);
88 }
89
90 COption::SetOptionInt('main', 'last_backup_start_time', time());
91}
92else
93{
94 define('NO_AGENT_CHECK', true);
95 define("STATISTIC_SKIP_ACTIVITY_CHECK", true);
96 if (!$_SERVER['DOCUMENT_ROOT'])
97 {
98 $DOCUMENT_ROOT = $_SERVER['DOCUMENT_ROOT'] = realpath(__DIR__ . '/../../../../');
99 }
100 require($_SERVER['DOCUMENT_ROOT'] . '/bitrix/modules/main/include/prolog_before.php');
101 IncludeModuleLangFile($_SERVER['DOCUMENT_ROOT'] . '/bitrix/modules/main/admin/dump.php');
102}
103if (!defined('DOCUMENT_ROOT'))
104{
105 define('DOCUMENT_ROOT', rtrim(str_replace('\\', '/', $_SERVER['DOCUMENT_ROOT']), '/'));
106}
107require_once($_SERVER["DOCUMENT_ROOT"] . "/bitrix/modules/main/classes/general/backup.php");
108
109$public = $USER?->IsAdmin();
110if ($public) // backup from public
111{
112 $NS =& $_SESSION['BX_DUMP_STATE'];
113 if (isset($_REQUEST['start']) && $_REQUEST['start'] == 'Y')
114 {
115 $NS = [];
116 }
117}
118elseif (!CLI) // hit from bitrixcloud service
119{
120 if ((!$backup_secret_key = CPasswordStorage::Get('backup_secret_key')) || $backup_secret_key != $_REQUEST['secret_key'])
121 {
122 RaiseErrorAndDie('Secret key is incorrect', 10);
123 }
124 elseif (isset($_REQUEST['check_auth']) && $_REQUEST['check_auth'])
125 {
126 echo 'SUCCESS';
127 exit(0);
128 }
129 if (IntOption('dump_auto_enable') != 2)
130 {
131 RaiseErrorAndDie('Backup is disabled', 4);
132 }
133
134 session_write_close();
135 ini_set("session.use_strict_mode", "0");
136 session_id(md5($backup_secret_key));
137 session_start();
138 $NS =& $_SESSION['BX_DUMP_STATE'];
139
140 if ($NS['TIMESTAMP'] && ($i = IntOption('dump_max_exec_time_sleep')) > 0)
141 {
142 if (time() - $NS['TIMESTAMP'] < $i)
143 {
144 sleep(3);
145 echo "NEXT\n" . GetProgressPercent($NS);
146 exit(0);
147 }
148 }
149}
150
151if (!file_exists(DOCUMENT_ROOT . '/bitrix/backup'))
152{
153 mkdir(DOCUMENT_ROOT . '/bitrix/backup');
154}
155
156if (!file_exists(DOCUMENT_ROOT . "/bitrix/backup/index.php"))
157{
158 $f = fopen(DOCUMENT_ROOT . "/bitrix/backup/index.php", "w");
159 fwrite($f, "<head><meta http-equiv=\"REFRESH\" content=\"0;URL=/bitrix/admin/index.php\"></head>");
160 fclose($f);
161}
162
163while (ob_end_flush())
164{
165 ;
166}
167
168@set_time_limit(0);
169
170$bGzip = function_exists('gzcompress');
171$bBitrixCloud = function_exists('openssl_encrypt') && CModule::IncludeModule('bitrixcloud') && CModule::IncludeModule('clouds');
172
173if ($public)
174{
175 $arParams = [
176 'dump_archive_size_limit' => 100 * 1024 * 1024,
177 'dump_use_compression' => $bGzip,
178 'dump_integrity_check' => 1,
179 'dump_delete_old' => 0,
180 'dump_site_id' => [],
181
182 'dump_base' => 1,
183 'dump_base_skip_stat' => 0,
184 'dump_base_skip_search' => 0,
185 'dump_base_skip_log' => 0,
186
187 'dump_file_public' => 1,
188 'dump_file_kernel' => 1,
189 'dump_do_clouds' => 0,
190 'skip_mask' => 0,
191 'skip_mask_array' => [],
192 'dump_max_file_size' => 0,
193 ];
194}
195else
196{
197 $arParams = [
198 'dump_archive_size_limit' => IntOption('dump_archive_size_limit'),
199 'dump_use_compression' => $bGzip && IntOption('dump_use_compression'),
200 'dump_integrity_check' => IntOption('dump_integrity_check'),
201
202 'dump_delete_old' => IntOption('dump_delete_old'),
203 'dump_old_time' => IntOption('dump_old_time'),
204 'dump_old_cnt' => IntOption('dump_old_cnt'),
205 'dump_old_size' => IntOption('dump_old_size'),
206
207 'dump_site_id' => is_array($ar = unserialize(COption::GetOptionString("main", "dump_site_id" . "_auto"), ['allowed_classes' => false])) ? $ar : [],
208 ];
209
211 'dump_base' => IntOption('dump_base', 1),
212 'dump_base_skip_stat' => IntOption('dump_base_skip_stat'),
213 'dump_base_skip_search' => IntOption('dump_base_skip_search'),
214 'dump_base_skip_log' => IntOption('dump_base_skip_log'),
215
216 'dump_file_public' => IntOption('dump_file_public', 1),
217 'dump_file_kernel' => IntOption('dump_file_kernel', 1),
218 'dump_do_clouds' => IntOption('dump_do_clouds', 1),
219 'skip_mask' => IntOption('skip_mask'),
220 'skip_mask_array' => is_array($ar = unserialize(COption::GetOptionString("main", "skip_mask_array_auto"), ['allowed_classes' => false])) ? $ar : [],
221 'dump_max_file_size' => IntOption('dump_max_file_size'),
222 ];
223
225}
226
227$skip_mask_array = $arParams['skip_mask_array'];
228
229if ($DB->type != 'MYSQL')
230{
231 $arParams['dump_base'] = 0;
232}
233
234if (!$NS['step'])
235{
236 $NS = ['step' => 1, 'step_cnt' => 0];
237 $NS['START_TIME'] = START_TIME;
238 if ($public)
239 {
240 $dump_bucket_id = 0;
241 }
242 else
243 {
244 $NS['dump_encrypt_key'] = CPasswordStorage::Get('dump_temporary_cache');
245 $dump_bucket_id = IntOption('dump_bucket_id');
246 }
247
248 if ($dump_bucket_id == -1)
249 {
250 if (!$bBitrixCloud || !$NS['dump_encrypt_key'])
251 {
252 $dump_bucket_id = 0;
253 ShowBackupStatus('BitrixCloud is not available');
254 }
255 }
256 $NS['BUCKET_ID'] = $dump_bucket_id;
257
258 if ($dump_bucket_id == -1)
259 {
260 $arc_name = DOCUMENT_ROOT . BX_ROOT . "/backup/" . date('Ymd_His_') . rand(11111111, 99999999);
261 }
262 elseif (($arc_name = $argv[1]) && !is_dir($arc_name))
263 {
264 $arc_name = str_replace(['.tar', '.gz', '.enc'], '', $arc_name);
265 }
266 else
267 {
268 $prefix = str_replace('/', '', COption::GetOptionString("main", "server_name", ""));
269 $arc_name = CBackup::GetArcName(preg_match('#^[a-z0-9.\-]+$#i', $prefix) ? substr($prefix, 0, 20) . '_' : '');
270 }
271
272 $NS['arc_name'] = $arc_name . ($NS['dump_encrypt_key'] ? ".enc" : ".tar") . ($arParams['dump_use_compression'] ? ".gz" : '');
273 $NS['dump_name'] = $arc_name . '.sql';
274
275 if (!empty($arParams['dump_site_id']))
276 {
277 $NS['site_path_list'] = [];
278 $res = CSite::GetList('sort', 'asc', ['ACTIVE' => 'Y']);
279 while ($f = $res->Fetch())
280 {
281 $root = rtrim(str_replace('\\', '/', $f['ABS_DOC_ROOT']), '/');
282 if (is_dir($root) && in_array($f['ID'], $arParams['dump_site_id']))
283 {
284 $NS['site_path_list'][$f['ID']] = $root;
285 }
286 }
287 }
288 else
289 {
290 $NS['site_path_list'] = ['s1' => DOCUMENT_ROOT];
291 }
292
293 if (!$public)
294 {
295 foreach (GetModuleEvents("main", "OnAutoBackupStart", true) as $arEvent)
296 {
297 ExecuteModuleEventEx($arEvent, [$NS]);
298 }
299 }
300
301 ShowBackupStatus('Backup started to file: ' . $NS['arc_name']);
302 if ($arParams['dump_base'])
303 {
304 $NS['step_cnt'] = 2;
305 }
306 if ($arParams['dump_do_clouds'] && ($arDumpClouds = CBackup::GetBucketList()))
307 {
308 $NS['step_cnt']++;
309 }
310 if (($arParams['dump_file_public'] || $arParams['dump_file_kernel']))
311 {
312 $NS['step_cnt']++;
313 }
314 if ($arParams['dump_integrity_check'])
315 {
316 $NS['step_cnt']++;
317 }
318 if ($NS['BUCKET_ID'])
319 {
320 $NS['step_cnt']++;
321 }
322 if ($arParams['dump_delete_old'] > 1)
323 {
324 $NS['step_cnt']++;
325 }
326 $NS['step_finished'] = 0;
327}
328
329$NS['step_done'] = 0;
330$after_file = str_replace('.sql', '_after_connect.sql', preg_replace('#\.[0-9]+$#', '', $NS['dump_name']));
331
332if ($NS['step'] <= 2)
333{
334 // dump database
335 if ($arParams['dump_base'])
336 {
337 if ($NS['step'] == 1)
338 {
339 ShowBackupStatus('Dumping database');
340 if (!CBackup::MakeDump($NS['dump_name'], $NS['dump_state']))
341 {
342 RaiseErrorAndDie(GetMessage('DUMP_NO_PERMS'), 100, $NS['dump_name']);
343 }
344
345 $TotalTables = $NS['dump_state']['TableCount'];
346 $FinishedTables = $TotalTables - count($NS['dump_state']['TABLES']);
347 $NS['step_done'] = $FinishedTables / $TotalTables;
348
349 if (!$NS['dump_state']['end'])
350 {
351 CheckPoint();
352 }
353
354 $rs = $DB->Query('SHOW VARIABLES LIKE "character_set_results"');
355 if (($f = $rs->Fetch()) && array_key_exists('Value', $f))
356 {
357 file_put_contents($after_file, "SET NAMES '" . $f['Value'] . "';\n");
358 }
359
360 $rs = $DB->Query('SHOW VARIABLES LIKE "collation_database"');
361 if (($f = $rs->Fetch()) && array_key_exists('Value', $f))
362 {
363 file_put_contents($after_file, "ALTER DATABASE `<DATABASE>` COLLATE " . $f['Value'] . ";\n", 8);
364 }
365
366 $NS['step'] = 2;
367 $NS['step_finished']++;
368 clearstatcache();
369
370 $next_part = $NS['dump_name'];
371 $NS['dump_size'] = filesize($next_part);
372 while (file_exists($next_part = CBackup::getNextName($next_part)))
373 {
374 $NS['dump_size'] += filesize($next_part);
375 }
376 }
377
378 ShowBackupStatus('Archiving database dump');
379 $tar = new CTar;
380 $tar->EncryptKey = $NS['dump_encrypt_key'];
381 $tar->ArchiveSizeLimit = $arParams['dump_archive_size_limit'];
382 $tar->gzip = $arParams['dump_use_compression'];
383 $tar->path = DOCUMENT_ROOT;
384 $tar->ReadBlockCurrent = intval($NS['ReadBlockCurrent']);
385 $tar->ReadFileSize = intval($NS['ReadFileSize']);
386
387 if (!$tar->openWrite($NS["arc_name"]))
388 {
389 RaiseErrorAndDie(GetMessage('DUMP_NO_PERMS'), 200, $NS['arc_name']);
390 }
391
392 if (!$tar->ReadBlockCurrent)
393 {
394 if (file_exists($f = DOCUMENT_ROOT . BX_ROOT . '/.config.php')) // legacy SaaS support
395 {
396 $tar->addFile($f);
397 }
398
399 if (file_exists($after_file))
400 {
401 $tar->addFile($after_file);
402 unlink($after_file);
403 }
404 }
405
406 $Block = $tar->Block;
407 while (haveTime())
408 {
409 $r = $tar->addFile($NS['dump_name']);
410 if ($r === false)
411 {
412 RaiseErrorAndDie(implode('<br>', $tar->err), 210, $NS['arc_name'], true);
413 }
414 if ($tar->ReadBlockCurrent == 0)
415 {
416 unlink($NS["dump_name"]);
417 if (file_exists($next_part = CBackup::getNextName($NS['dump_name'])))
418 {
419 $NS['dump_name'] = $next_part;
420 }
421 else // finish
422 {
423 $NS['arc_size'] = 0;
424 $name = $NS["arc_name"];
425 while (file_exists($name))
426 {
427 $size = filesize($name);
428 $NS['arc_size'] += $size;
429 $name = $tar->getNextName($name);
430 }
431 $NS['step_finished']++;
432
433 break;
434 }
435 }
436 }
437 $tar->close();
438
439 $NS["data_size"] += 512 * ($tar->Block - $Block);
440 $NS["ReadBlockCurrent"] = $tar->ReadBlockCurrent;
441 $NS["ReadFileSize"] = $tar->ReadFileSize;
442 $NS['step_done'] = $NS['data_size'] / $NS['dump_size'];
443
444 CheckPoint();
445 }
446 $NS['step'] = 3;
447}
448
449if ($NS['step'] == 3)
450{
451 $NS['step_done'] = 0;
452 // Download cloud files
453 if ($arParams['dump_do_clouds'] && ($arDumpClouds = CBackup::GetBucketList()))
454 {
455 ShowBackupStatus('Downloading cloud files');
456 foreach ($arDumpClouds as $arBucket)
457 {
458 $id = $arBucket['ID'];
459 if ($NS['bucket_finished_' . $id])
460 {
461 continue;
462 }
463
464 $obCloud = new CloudDownload($arBucket['ID']);
465 $obCloud->last_bucket_path = $NS['last_bucket_path'];
466 if ($res = $obCloud->Scan(''))
467 {
468 $NS['bucket_finished_' . $id] = true;
469 }
470 else
471 {
472 $NS['last_bucket_path'] = $obCloud->path;
473 break;
474 }
475 }
476
477 CheckPoint();
478 $NS['step_finished']++;
479 }
480 $NS['step'] = 4;
481}
482
483$DB->Disconnect();
484
485if ($NS['step'] == 4)
486{
487 // Tar files
488 $NS['step_done'] = 0;
489 if ($arParams['dump_file_public'] || $arParams['dump_file_kernel'])
490 {
491 ShowBackupStatus('Archiving files');
492
493 $DirScan = new CDirRealScan;
494 $DirScan->startPath = $NS['startPath'];
495
496 $tar = new CTar;
497 $tar->EncryptKey = $NS['dump_encrypt_key'];
498 $tar->ArchiveSizeLimit = $arParams['dump_archive_size_limit'];
499 $tar->gzip = $arParams['dump_use_compression'];
500 $tar->ReadBlockCurrent = intval($NS['ReadBlockCurrent']);
501 $tar->ReadFileSize = intval($NS['ReadFileSize']);
502
503 foreach ($NS['site_path_list'] as $SITE_ID => $DOCUMENT_ROOT_SITE)
504 {
505 $DOCUMENT_ROOT_SITE = rtrim($DOCUMENT_ROOT_SITE, '/');
506
507 $tar->path = $DOCUMENT_ROOT_SITE;
508
509 if (!$tar->openWrite($NS["arc_name"]))
510 {
511 RaiseErrorAndDie(GetMessage('DUMP_NO_PERMS'), 400, $NS['arc_name'], true);
512 }
513
514 CBackup::$DOCUMENT_ROOT_SITE = $DOCUMENT_ROOT_SITE;
515 CBackup::$REAL_DOCUMENT_ROOT_SITE = realpath($DOCUMENT_ROOT_SITE);
516
517 if ($NS['multisite'])
518 {
519 $tar->prefix = 'bitrix/backup/sites/' . $SITE_ID . '/';
520 $DirScan->arSkip[$DOCUMENT_ROOT_SITE . '/bitrix'] = true;
521 $DirScan->arSkip[$DOCUMENT_ROOT_SITE . '/upload'] = true;
522 if (is_link($DOCUMENT_ROOT_SITE . '/local'))
523 {
524 // if it's a link, we need it only the first time
525 $DirScan->arSkip[$DOCUMENT_ROOT_SITE . '/local'] = true;
526 }
527 }
528
529 $Block = $tar->Block;
530
531 $r = $DirScan->Scan($DOCUMENT_ROOT_SITE);
532 $tar->close();
533
534 if (!isset($NS["data_size"]))
535 {
536 $NS["data_size"] = 0;
537 }
538 $NS["data_size"] += 512 * ($tar->Block - $Block);
539
540 if ($r === false)
541 {
542 RaiseErrorAndDie(implode('<br>', array_merge($tar->err, $DirScan->err)), 410, $tar->file, true);
543 }
544
545 $NS["ReadBlockCurrent"] = $tar->ReadBlockCurrent;
546 $NS["ReadFileSize"] = $tar->ReadFileSize;
547 $NS["startPath"] = $DirScan->nextPath;
548
549 if (!isset($NS["cnt"]))
550 {
551 $NS["cnt"] = 0;
552 }
553 $NS["cnt"] += $DirScan->FileCount;
554
555 $last_files_count = IntOption('last_files_count');
556 if (!$last_files_count)
557 {
558 $last_files_count = 200000;
559 }
560 $NS['step_done'] = $NS['cnt'] / $last_files_count;
561 if ($NS['step_done'] > 1)
562 {
563 $NS['step_done'] = 1;
564 }
565
566 if ($r !== 'BREAK') // finish scan
567 {
568 array_shift($NS['site_path_list']);
569 $NS['multisite'] = true;
570 unset($NS['startPath']);
571 }
572
573 CheckPoint();
574 }
575
576 $NS['arc_size'] = 0;
577 $name = $NS["arc_name"];
578 $tar = new CTar();
579 while (file_exists($name))
580 {
581 $size = filesize($name);
582 $NS['arc_size'] += $size;
583 $name = $tar->getNextName($name);
584 }
585 DeleteDirFilesEx(BX_ROOT . '/backup/clouds');
586 if ($arParams['dump_file_public'] && $arParams['dump_file_kernel'])
587 {
588 COption::SetOptionInt("main", "last_files_count", $NS['cnt']);
589 }
590 $NS['step_finished']++;
591 }
592 $NS['step'] = 5;
593}
594
595if ($NS['step'] == 5)
596{
597 // Integrity check
598 $NS['step_done'] = 0;
599 if ($arParams['dump_integrity_check'])
600 {
601 ShowBackupStatus('Checking archive integrity');
602 $tar = new CTarCheck;
603 $tar->EncryptKey = $NS['dump_encrypt_key'];
604
605 if (!$tar->openRead($NS["arc_name"]))
606 {
607 RaiseErrorAndDie(GetMessage('DUMP_NO_PERMS_READ') . '<br>' . implode('<br>', $tar->err), 510, $NS['arc_name']);
608 }
609 else
610 {
611 if (($Block = intval($NS['Block'] ?? 0)) && !$tar->SkipTo($Block))
612 {
613 RaiseErrorAndDie(implode('<br>', $tar->err), 520, $tar->file, true);
614 }
615 while (($r = $tar->extractFile()) && haveTime())
616 {
617 ;
618 }
619 $NS["Block"] = $tar->Block;
620 $NS['step_done'] = $NS['Block'] * 512 / $NS['data_size'];
621 if ($r === false)
622 {
623 RaiseErrorAndDie(implode('<br>', $tar->err), 530, $tar->file, true);
624 }
625 }
626 $tar->close();
627
628 CheckPoint();
629 $NS['step_finished']++;
630 }
631 $NS['step'] = 6;
632}
633
634$DB->DoConnect();
635
636if ($NS['step'] == 6)
637{
638 // Send to the cloud
639 $NS['step_done'] = 0;
640 if ($NS['BUCKET_ID'])
641 {
642 ShowBackupStatus('Sending backup to the cloud');
643 if (!CModule::IncludeModule('clouds'))
644 {
645 RaiseErrorAndDie(GetMessage("MAIN_DUMP_NO_CLOUDS_MODULE"), 600, $NS['arc_name']);
646 }
647
648 $tar = new CTar();
649 while (CheckPoint())
650 {
651 $file_size = filesize($NS["arc_name"]);
652 $file_name = $NS['BUCKET_ID'] == -1 ? basename($NS['arc_name']) : substr($NS['arc_name'], strlen(DOCUMENT_ROOT));
653 $obUpload = new CCloudStorageUpload($file_name);
654
655 if ($NS['BUCKET_ID'] == -1)
656 {
657 if (!$bBitrixCloud)
658 {
659 RaiseErrorAndDie(getMessage('DUMP_BXCLOUD_NA'), 610);
660 }
661
662 $obBucket = null;
663 if (!$NS['obBucket'])
664 {
665 try
666 {
668 $q = $backup->getQuota();
669 if ($q && $NS['arc_size'] > $q)
670 {
671 RaiseErrorAndDie(GetMessage('DUMP_ERR_BIG_BACKUP', ['#ARC_SIZE#' => $NS['arc_size'], '#QUOTA#' => $q]), 620);
672 }
673
674 $obBucket = $backup->getBucketToWriteFile(CTar::getCheckword($NS['dump_encrypt_key']), basename($NS['arc_name']));
675 $NS['obBucket'] = serialize($obBucket);
676 }
677 catch (Exception $e)
678 {
679 unset($NS['obBucket']);
680 RaiseErrorAndDie($e->getMessage(), 630);
681 }
682 }
683 else
684 {
685 $obBucket = unserialize(
686 $NS['obBucket'],
687 ['allowed_classes' => ['CBitrixCloudBackupBucket']]
688 );
689 }
690
691 $obBucket->Init();
692 $obBucket->GetService()->setPublic(false);
693
694 $bucket_id = $obBucket;
695 }
696 else
697 {
698 $obBucket = null;
699 $bucket_id = $NS['BUCKET_ID'];
700 }
701
702 if (!$obUpload->isStarted())
703 {
704 if (is_object($obBucket))
705 {
706 $obBucket->setCheckWordHeader();
707 }
708
709 if (!$obUpload->Start($bucket_id, $file_size))
710 {
711 if ($e = $APPLICATION->GetException())
712 {
713 $strError = $e->GetString();
714 }
715 else
716 {
717 $strError = GetMessage('MAIN_DUMP_INT_CLOUD_ERR');
718 }
719 RaiseErrorAndDie($strError, 640, $NS['arc_name']);
720 }
721
722 if (is_object($obBucket))
723 {
724 $obBucket->unsetCheckWordHeader();
725 }
726 }
727
728 if (!$fp = fopen($NS['arc_name'], 'rb'))
729 {
730 RaiseErrorAndDie(GetMessage("MAIN_DUMP_ERR_OPEN_FILE") . ' ' . $NS['arc_name'], 650, $NS['arc_name']);
731 }
732
733 fseek($fp, $obUpload->getPos());
734 while ($obUpload->getPos() < $file_size && haveTime())
735 {
736 $part = fread($fp, $obUpload->getPartSize());
737 $fails = 0;
738 $res = false;
739 while ($obUpload->hasRetries())
740 {
741 if ($res = $obUpload->Next($part, $obBucket))
742 {
743 break;
744 }
745 elseif (++$fails >= 10)
746 {
747 $e = $APPLICATION->GetException();
748 $strError = $e ? '. ' . $e->GetString() : '';
749 RaiseErrorAndDie('Internal Error: could not init upload for ' . $fails . ' times' . $strError, 660, $NS['arc_name']);
750 }
751 }
752 $NS['step_done'] = $obUpload->getPos() / $NS['arc_size'];
753
754 if (!$res)
755 {
756 $obUpload->Delete();
757 $e = $APPLICATION->GetException();
758 $strError = $e ? '. ' . $e->GetString() : '';
759 RaiseErrorAndDie(GetMessage('MAIN_DUMP_ERR_FILE_SEND') . ' ' . basename($NS['arc_name']) . $strError, 670, $NS['arc_name']);
760 }
761 }
762 fclose($fp);
763
764 CheckPoint();
765
766 if ($obUpload->Finish($obBucket))
767 {
768 if ($NS['BUCKET_ID'] != -1)
769 {
770 $oBucket = new CCloudStorageBucket($NS['BUCKET_ID']);
771 $oBucket->IncFileCounter($file_size);
772 }
773
774 if (file_exists($arc_name = $tar->getNextName($NS['arc_name'])))
775 {
776 unset($NS['obBucket']);
777 $NS['arc_name'] = $arc_name;
778 }
779 else
780 {
781 if ($bBitrixCloud)
782 {
783 $ob = new CBitrixCloudBackup;
784 $ob->clearOptions();
785 }
786
787 if ($arParams['dump_delete_old'] == 1)
788 {
789 $name = CTar::getFirstName($NS['arc_name']);
790 while (file_exists($name))
791 {
792 $size = filesize($name);
793 if (unlink($name) && COption::GetOptionInt('main', 'disk_space', 0) > 0)
794 {
795 CDiskQuota::updateDiskQuota("file", $size, "del");
796 }
797 $name = $tar->getNextName($name);
798 }
799 }
800 break;
801 }
802 }
803 else
804 {
805 $obUpload->Delete();
806 $e = $APPLICATION->GetException();
807 $strError = $e ? '. ' . $e->GetString() : '';
808 RaiseErrorAndDie(GetMessage('MAIN_DUMP_ERR_FILE_SEND') . basename($NS['arc_name']) . $strError, 680, $NS['arc_name']);
809 }
810 }
811 $NS['step_finished']++;
812 }
813 $NS['step'] = 7;
814}
815
816if ($NS['step'] == 7)
817{
818 // Delete old backups
819 $NS['step_done'] = 0;
820 if ($arParams['dump_delete_old'] > 1)
821 {
822 ShowBackupStatus('Deleting old backups');
823 $arFiles = [];
824 $arParts = [];
825
826 $TotalSize = $NS['arc_size'];
827
828 if (is_dir($p = DOCUMENT_ROOT . BX_ROOT . '/backup'))
829 {
830 if ($dir = opendir($p))
831 {
832 $arc_name = CTar::getFirstName(basename($NS['arc_name']));
833 while (($item = readdir($dir)) !== false)
834 {
835 $f = $p . '/' . $item;
836 if (!is_file($f))
837 {
838 continue;
839 }
840
841 if (!preg_match('#\.(sql|tar|gz|enc|[0-9]+)$#', $item))
842 {
843 continue;
844 }
845
846 $name = CTar::getFirstName($item);
847 if ($name == $arc_name)
848 {
849 continue;
850 }
851
852 $s = filesize($f);
853 $m = filemtime($f);
854
855 $arFiles[$name] = $m;
856 $arParts[$name][] = $item;
857 $TotalSize += $s;
858 }
859 closedir($dir);
860 }
861 }
862 asort($arFiles);
863 $cnt = count($arFiles) + 1;
864
865 foreach ($arFiles as $name => $m)
866 {
867 switch ($arParams['dump_delete_old'])
868 {
869 case 2: // time
870 if ($m >= time() - 86400 * $arParams['dump_old_time'])
871 {
872 break 2;
873 }
874 break;
875 case 4: // cnt
876 if ($cnt <= $arParams['dump_old_cnt'])
877 {
878 break 2;
879 }
880 break;
881 case 8: // size
882 if ($TotalSize / 1024 / 1024 / 1024 <= $arParams['dump_old_size'])
883 {
884 break 2;
885 }
886 break;
887 default:
888 break;
889 }
890
891 $cnt--;
892 foreach ($arParts[$name] as $item)
893 {
894 $f = $p . '/' . $item;
895 $size = filesize($f);
896 $TotalSize -= $size;
897 if (!unlink($f))
898 {
899 RaiseErrorAndDie('Could not delete file: ' . $f, 700, $NS['arc_name']);
900 }
901 if (COption::GetOptionInt('main', 'disk_space', 0) > 0)
902 {
903 CDiskQuota::updateDiskQuota("file", $size, "del");
904 }
905 }
906 }
907 $NS['step_finished']++;
908 }
909 $NS['step'] = 8;
910}
911
912if (COption::GetOptionInt('main', 'disk_space', 0) > 0)
913{
914 $name = $NS["arc_name"];
915 $tar = new CTar();
916 while (file_exists($name))
917 {
918 $size = filesize($name);
919 CDiskQuota::updateDiskQuota("file", $size, "add");
920 $name = $tar->getNextName($name);
921 }
922}
923
924$info = "Finished.\n\nData size: " . round($NS['data_size'] / 1024 / 1024, 2) . " M\nArchive size: " . round($NS['arc_size'] / 1024 / 1024, 2) . " M\nTime: " . round(time() - $NS['START_TIME'], 2) . " sec\n";
927 "SEVERITY" => "WARNING",
928 "AUDIT_TYPE_ID" => "BACKUP_SUCCESS",
929 "MODULE_ID" => "main",
930 "ITEM_ID" => $NS['arc_name'],
931 "DESCRIPTION" => $info,
932]);
933
934foreach (GetModuleEvents("main", "OnAutoBackupSuccess", true) as $arEvent)
935{
936 ExecuteModuleEventEx($arEvent, [$NS]);
937}
938
939$NS = [];
940if (defined('LOCK_FILE'))
941{
942 unlink(LOCK_FILE) || RaiseErrorAndDie('Can\'t delete file: ' . LOCK_FILE, 1000);
943}
944if (!CLI)
945{
946 echo 'FINISH';
947}
948COption::SetOptionInt('main', 'last_backup_end_time', time());
949
950function IntOption($name, $def = 0)
951{
952 global $arParams;
953 if (isset($arParams[$name]))
954 {
955 return $arParams[$name];
956 }
957
958 static $CACHE;
959 $name .= '_auto';
960
961 if (!isset($CACHE[$name]))
962 {
963 $CACHE[$name] = COption::GetOptionInt("main", $name, $def);
964 }
965 return $CACHE[$name];
966}
967
969{
970 if (!CLI && !$_REQUEST['show_status'])
971 {
972 return;
973 }
974 global $NS;
975 echo round(microtime(1) - $NS['START_TIME'], 2) . ' sec ' . $str . "\n";
976}
977
978function haveTime()
979{
980 static $timeout;
981 if (!$timeout)
982 {
983 $timeout = IntOption('dump_max_exec_time', 30);
984 if ($timeout < 5)
985 {
986 $timeout = 5;
987 }
988 }
989 if (!CLI && time() - START_TIME > $timeout)
990 {
991 return false;
992 }
993 return true;
994}
995
996function RaiseErrorAndDie($strError, $errCode = 0, $ITEM_ID = '', $delete = false)
997{
998 global $DB, $NS;
999
1000 if ($delete)
1001 {
1002 $arc_name = CTar::getFirstName(basename($NS['arc_name']));
1003
1004 if ($dir = opendir($path = DOCUMENT_ROOT . '/bitrix/backup'))
1005 {
1006 while ($item = readdir($dir))
1007 {
1008 if (is_dir($path . '/' . $item))
1009 {
1010 continue;
1011 }
1012 if (CTar::getFirstName($item) == $arc_name)
1013 {
1014 $delete = unlink($path . '/' . $item) && $delete;
1015 }
1016 }
1017 closedir($dir);
1018 }
1019 else
1020 {
1021 $delete = false;
1022 }
1023
1024 $strError .= "\n" . ($delete ? 'The backup was incorrect and it was deleted' : 'The backup was incorrect but there was an error deleting it');
1025 }
1026
1027 $NS0 = $NS;
1028 $NS = [];
1029 session_write_close();
1030
1031 if (CLI)
1032 {
1033 echo 'Error [' . $errCode . ']: ' . str_replace('<br>', "\n", $strError) . "\n";
1034 }
1035 else
1036 {
1037 echo "ERROR_" . $errCode . "\n" . htmlspecialcharsbx($strError) . "\n";
1038 }
1039
1040 if (is_object($DB))
1041 {
1042 $DB->DoConnect();
1043
1045 "SEVERITY" => "WARNING",
1046 "AUDIT_TYPE_ID" => "BACKUP_ERROR",
1047 "MODULE_ID" => "main",
1048 "ITEM_ID" => $ITEM_ID,
1049 "DESCRIPTION" => "[" . $errCode . "] " . $strError,
1050 ]);
1051
1052 foreach (GetModuleEvents("main", "OnAutoBackupError", true) as $arEvent)
1053 {
1054 ExecuteModuleEventEx($arEvent, [array_merge($NS0, ['ERROR' => $strError, 'ERROR_CODE' => $errCode, 'ITEM_ID' => $ITEM_ID])]);
1055 }
1056
1057 $link = '/bitrix/admin/event_log.php?set_filter=Y&find_type=audit_type_id&find_audit_type[]=BACKUP_ERROR';
1058 $ar = [
1059 "MESSAGE" => 'The last automatic backup has failed. Please check your <a href="' . $link . '">system log<a>',
1060 "TAG" => "BACKUP",
1061 "MODULE_ID" => "MAIN",
1062 'NOTIFY_TYPE' => CAdminNotify::TYPE_ERROR,
1063 'ENABLE_CLOSE' => 'Y',
1064 ];
1065 foreach (['ru', 'ua', 'en', 'de'] as $lang)
1066 {
1067 \Bitrix\Main\Localization\Loc::loadLanguageFile($_SERVER['DOCUMENT_ROOT'] . '/bitrix/modules/main/admin/dump.php', $lang);
1068 $ar["LANG"][$lang] = \Bitrix\Main\Localization\Loc::getMessage('DUMP_ERR_AUTO', ['#MESSAGE#' => $strError, '#LINK#' => $link], $lang);
1069 }
1071 }
1072 die();
1073}
1074
1075function CheckPoint()
1076{
1077 if (haveTime())
1078 {
1079 return true;
1080 }
1081
1082 global $NS;
1083 $NS['WORK_TIME'] = microtime(1) - START_TIME;
1084 $NS['TIMESTAMP'] = time();
1085
1086 session_write_close();
1087 echo "NEXT\n" . GetProgressPercent($NS);
1088 exit(0);
1089}
1090
1092{
1093 if ($NS['step_done'] > 1)
1094 {
1095 $NS['step_done'] = 1;
1096 }
1097 $res = round(100 * ($NS['step_finished'] + $NS['step_done']) / $NS['step_cnt']);
1098 if ($res > 99)
1099 {
1100 $res = 99;
1101 }
1102 return $res;
1103}
$arParams
Определения access_dialog.php:21
$path
Определения access_edit.php:21
const BX_CRONTAB
Определения bootstrap.php:12
const BX_ROOT
Определения bx_root.php:3
global $APPLICATION
Определения include.php:80
static loadLanguageFile($file, $language=null, $normalize=true)
Определения loc.php:225
static getMessage($code, $replace=null, $language=null)
Определения loc.php:30
const TYPE_ERROR
Определения admin_notify.php:8
static Add($arFields)
Определения admin_notify.php:22
static SetOptionInt($module_id, $name, $value="", $desc="", $site="")
Определения option.php:54
static GetList($by="sort", $order="asc", $arFilter=[])
Определения site.php:605
static $DOCUMENT_ROOT_SITE
Определения backup.php:17
static MakeDump($strDumpFile, &$arState)
Определения backup.php:238
static $REAL_DOCUMENT_ROOT_SITE
Определения backup.php:18
static GetArcName($prefix='')
Определения backup.php:217
static GetBucketList($arFilter=array())
Определения backup.php:42
static getNextName($file)
Определения backup.php:526
Определения backup.php:4
clearOptions()
Определения backup.php:216
static getInstance()
Определения backup.php:19
Определения backup.php:663
static Add($arFields)
Определения event_log.php:44
static Get($strName)
Определения backup.php:817
Определения backup.php:1948
Определения backup.php:851
static getFirstName($file)
Определения backup.php:1616
static getCheckword($key)
Определения backup.php:1611
Определения backup.php:1960
$str
Определения commerceml2.php:63
$f
Определения component_props.php:52
$res
Определения filter_act.php:7
$_REQUEST["admin_mnu_menu_id"]
Определения get_menu.php:8
$p
Определения group_list_element_edit.php:23
$strError
Определения options_user_settings.php:4
$DOCUMENT_ROOT
Определения cron_frame.php:10
$_SERVER["DOCUMENT_ROOT"]
Определения cron_frame.php:9
global $DB
Определения cron_frame.php:29
global $USER
Определения csv_new_run.php:40
if(!defined('SITE_ID')) $lang
Определения include.php:91
$l
Определения options.php:783
GetProgressPercent($NS)
Определения backup.php:1091
RaiseErrorAndDie($strError, $errCode=0, $ITEM_ID='', $delete=false)
Определения backup.php:996
ShowBackupStatus($str)
Определения backup.php:968
$bGzip
Определения backup.php:170
$after_file
Определения backup.php:330
IntOption($name, $def=0)
Определения backup.php:950
if($NS['step']==6) if( $NS[ 'step']==7) if(COption::GetOptionInt('main', 'disk_space', 0) > 0) $info
Определения backup.php:924
$public
Определения backup.php:109
$bBitrixCloud
Определения backup.php:171
$arExpertBackupDefaultParams
Определения backup.php:210
$skip_mask_array
Определения backup.php:227
CheckPoint()
Определения backup.php:1075
const START_TIME
Определения backup.php:15
const CLI
Определения backup.php:17
if(!defined('NOT_CHECK_PERMISSIONS')) $NS
Определения backup.php:24
haveTime()
Определения backup.php:978
ExecuteModuleEventEx($arEvent, $arParams=[])
Определения tools.php:5214
htmlspecialcharsbx($string, $flags=ENT_COMPAT, $doubleEncode=true)
Определения tools.php:2701
GetModuleEvents($MODULE_ID, $MESSAGE_ID, $bReturnArray=false)
Определения tools.php:5177
IncludeModuleLangFile($filepath, $lang=false, $bReturnArray=false)
Определения tools.php:3778
DeleteDirFilesEx($path, $root=null)
Определения tools.php:2823
GetMessage($name, $aReplace=null)
Определения tools.php:3397
$name
Определения menu_edit.php:35
$time
Определения payment.php:61
$arFiles
Определения options.php:60
if( $daysToExpire >=0 &&$daysToExpire< 60 elseif)( $daysToExpire< 0)
Определения prolog_main_admin.php:393
$ar
Определения options.php:199
$dir
Определения quickway.php:303
die
Определения quickway.php:367
$i
Определения factura.php:643
</p ></td >< td valign=top style='border-top:none;border-left:none;border-bottom:solid windowtext 1.0pt;border-right:solid windowtext 1.0pt;padding:0cm 2.0pt 0cm 2.0pt;height:9.0pt'>< p class=Normal align=center style='margin:0cm;margin-bottom:.0001pt;text-align:center;line-height:normal'>< a name=ТекстовоеПоле54 ></a ><?=($taxRate > count( $arTaxList) > 0) ? $taxRate."%"
Определения waybill.php:936
$rs
Определения action.php:82
foreach($arTemplatesList as $templ) if(mb_strpos($templ["NAME"] $def
Определения template_copy.php:264
$SITE_ID
Определения yandex_run.php:607