fix(config): ложное предупреждение про AWG, сироты section_interface, дубль cron

- has_outbound_section: туннельные секции (awg/warp/vpn/openvpn/masque/
  anytls/snell/mieru/sudoku) теперь считаются исходящей конфигурацией -
  одинокая AWG-секция больше не получает вводящее в заблуждение
  «No proxy outbound sections found» (жалобы пользователей #39/#42)
- новая миграция orphan_section_interface_cleanup: удаление секции
  маршрутизации раньше оставляло после себя дочерние section_interface,
  ссылающиеся на несуществующего родителя (у пользователя - запись на
  секцию '2' при живой только '1'); сироты удаляются через новую операцию
  delete_section; функция объявлена до массива MIGRATIONS - ucode не
  поднимает объявления
- strip_unmarked_tachyon_cron_lines: старые версии писали cron-строки без
  маркер-комментария, они переживали фильтрацию по маркерам, копились при
  обновлениях и crond запускал component_updates_if_due дважды за тик;
  немаркированные строки с нашими командами теперь вычищаются при каждом
  refresh и remove
This commit is contained in:
Dushnilin
2026-08-22 10:08:05 +03:00
parent c788c86184
commit 44016ec95b
4 changed files with 81 additions and 7 deletions
+41 -2
View File
@@ -710,6 +710,36 @@ function cron_refresh_plan(settings, sections, bin, list_marker, subscription_ma
print_cron_refresh_plan(cron_refresh_plan_rows(settings, sections, bin, list_marker, subscription_marker, component_marker));
}
// Older releases wrote tachyon cron jobs WITHOUT the marker comment; those
// lines survive marker-based filtering, stack up across upgrades and make
// crond run the same job twice per tick. Drop unmarked lines that invoke a
// tachyon-owned cron command via our binary.
function strip_unmarked_tachyon_cron_lines(data, bin, markers) {
data = as_string(data);
if (data == "")
return "";
let escaped_bin = replace(as_string(bin), /([^0-9A-Za-z_])/g, "\\$1");
let pattern = "^[^#\\n]*" + escaped_bin + "[ \\t]+(list_update|subscription_update|component_updates_if_due)([ \\t]|$)";
let lines = split(data, "\n");
let has_trailing_newline = substr(data, length(data) - 1) == "\n";
let result = "";
for (let i = 0; i < length(lines); i++) {
let line = as_string(lines[i]);
if (i == length(lines) - 1 && has_trailing_newline && line == "")
continue;
if (line_contains_any_marker(line, markers))
continue;
if (match(line, pattern) != null)
continue;
result += line + "\n";
}
return result;
}
function cron_refresh_apply_result(settings, sections, existing_crontab, bin, list_marker, subscription_marker, component_marker) {
let plan = cron_refresh_plan_rows(settings, sections, bin, list_marker, subscription_marker, component_marker);
let filtered_crontab = filter_cron_markers_text(existing_crontab, [ list_marker, subscription_marker, component_marker ]);
@@ -754,7 +784,9 @@ function cron_refresh_apply_result(settings, sections, existing_crontab, bin, li
return {
status: int(plan.status || 0),
crontab: filtered_crontab + (int(plan.status || 0) == 0 ? cron_jobs : ""),
crontab: strip_unmarked_tachyon_cron_lines(
filtered_crontab, bin, [ list_marker, subscription_marker, component_marker ]
) + (int(plan.status || 0) == 0 ? cron_jobs : ""),
logs
};
}
@@ -774,6 +806,11 @@ function write_crontab_text(text) {
return ok;
}
// Older releases wrote tachyon cron jobs WITHOUT the marker comment; those
// lines survive marker-based filtering, stack up across upgrades and make
// crond run the same job twice per tick. Drop unmarked lines that invoke a
// tachyon-owned cron command via our binary.
function log_cron_apply_result(result) {
for (let item in array_or_empty(object_or_empty(result).logs))
log_message(item.message, item.level);
@@ -781,8 +818,10 @@ function log_cron_apply_result(result) {
function remove_cron_jobs(list_marker, subscription_marker, component_marker) {
let crontab = command_output_from_args([ "crontab", "-l" ]);
let markers = [ list_marker, subscription_marker, component_marker ];
let result = {
crontab: filter_cron_markers_text(crontab, [ list_marker, subscription_marker, component_marker ]),
crontab: strip_unmarked_tachyon_cron_lines(
filter_cron_markers_text(crontab, markers), BIN_PATH, markers),
logs: [ { level: "info", message: "The cron job removed" } ]
};