685224ccb2
Bug descubierto al ejecutar el reset real: los guards y los kills usaban 'pgrep -af [c]hromium | grep -F <udd>'. Como la ruta del user-data-dir contiene la cadena 'chromium' (~/.config/chromium-cdp), el propio proceso grep/ugrep —cuyo cmdline incluye <udd>— era capturado por pgrep, dando un falso positivo perpetuo: el guard creía siempre que había un chromium abierto y delete/restore abortaban con exit 2, y el lazo de cierre nunca convergía. Fix en delete_chrome_profile, restore_chrome_bookmarks, create_chrome_profile y el pipeline reset_chrome_profiles: enumerar por PID con 'pgrep -x chromium' (comm exactamente 'chromium', nunca grep/pgrep/bash) y leer /proc/PID/cmdline para comprobar el udd. Validado: reset destructivo real de los 4 perfiles completó OK, cada perfil quedó con solo uBlock + web_proxy y los bookmarks restaurados.
173 lines
7.2 KiB
Bash
173 lines
7.2 KiB
Bash
#!/usr/bin/env bash
|
|
# restore_chrome_bookmarks — restaura archivos Bookmarks de un backup generado por
|
|
# backup_chrome_bookmarks hacia los perfiles destino en user-data-dir.
|
|
# Copia byte a byte con cp -p (nunca parsea ni reserializa el JSON).
|
|
|
|
set -euo pipefail
|
|
|
|
restore_chrome_bookmarks() {
|
|
# ── defaults ──────────────────────────────────────────────────────────────
|
|
local _user_data_dir="${HOME}/.config/chromium"
|
|
local _backup_dir=""
|
|
local _profiles=()
|
|
local _dry_run=0
|
|
|
|
# ── parse args ────────────────────────────────────────────────────────────
|
|
_usage() {
|
|
cat >&2 <<'EOF'
|
|
Usage: restore_chrome_bookmarks --backup-dir <ts-dir>
|
|
[--user-data-dir <dir>] [--profile <name>]... [--dry-run]
|
|
|
|
--user-data-dir Raíz de perfiles destino. Default: ~/.config/chromium
|
|
--backup-dir Directorio de backup con timestamp generado por
|
|
backup_chrome_bookmarks. Debe contener subdirectorios
|
|
<profile>/Bookmarks. OBLIGATORIO.
|
|
--profile <name> Perfil a restaurar (repetible). Si no se pasa ninguno
|
|
se restauran TODOS los perfiles presentes en backup-dir.
|
|
--dry-run Muestra qué se copiaría sin tocar nada.
|
|
|
|
Exit codes:
|
|
0 éxito (o dry-run completado)
|
|
1 error de argumento o validación
|
|
2 chromium está corriendo (solo en modo real)
|
|
EOF
|
|
return 1
|
|
}
|
|
|
|
while [[ $# -gt 0 ]]; do
|
|
case "$1" in
|
|
--user-data-dir) _user_data_dir="$2"; shift 2 ;;
|
|
--backup-dir) _backup_dir="$2"; shift 2 ;;
|
|
--profile) _profiles+=("$2"); shift 2 ;;
|
|
--dry-run) _dry_run=1; shift ;;
|
|
-h|--help) _usage; return 0 ;;
|
|
*) echo "restore_chrome_bookmarks: argumento desconocido: $1" >&2; return 1 ;;
|
|
esac
|
|
done
|
|
|
|
# ── validaciones ──────────────────────────────────────────────────────────
|
|
if [[ -z "$_backup_dir" ]]; then
|
|
echo "restore_chrome_bookmarks: --backup-dir es obligatorio" >&2
|
|
return 1
|
|
fi
|
|
|
|
if [[ ! -d "$_backup_dir" ]]; then
|
|
echo "restore_chrome_bookmarks: backup-dir no encontrado: ${_backup_dir}" >&2
|
|
return 1
|
|
fi
|
|
|
|
if [[ ! -d "$_user_data_dir" ]]; then
|
|
echo "restore_chrome_bookmarks: user-data-dir no encontrado: ${_user_data_dir}" >&2
|
|
return 1
|
|
fi
|
|
|
|
# ── guard: ningún chromium debe tener ESTE user-data-dir abierto (excepto en dry-run) ──
|
|
# Por-udd, no global. Comprobamos por PID con comm=chromium (pgrep -x) y leemos su cmdline,
|
|
# para NO auto-matchear el propio `grep`/`pgrep`: el path del udd contiene "chromium"
|
|
# (~/.config/chromium-cdp), así que un `pgrep -af '[c]hromium' | grep <udd>` se detecta a sí mismo.
|
|
if [[ $_dry_run -eq 0 ]]; then
|
|
local _p _busy=0
|
|
for _p in $(pgrep -x chromium 2>/dev/null); do
|
|
if tr '\0' ' ' < "/proc/$_p/cmdline" 2>/dev/null | grep -qF -- "$_user_data_dir"; then
|
|
_busy=1; break
|
|
fi
|
|
done
|
|
if [[ $_busy -eq 1 ]]; then
|
|
echo "restore_chrome_bookmarks: hay un chromium con este user-data-dir abierto — ciérralo antes de restaurar:" >&2
|
|
echo " pkill -TERM chromium" >&2
|
|
echo "(Chromium reescribe Bookmarks desde memoria al cerrar y desharía la restauración)" >&2
|
|
return 2
|
|
fi
|
|
fi
|
|
|
|
# ── determinar perfiles a restaurar ───────────────────────────────────────
|
|
local _target_profiles=()
|
|
|
|
if [[ ${#_profiles[@]} -gt 0 ]]; then
|
|
# Perfiles explícitos: verificar que existen en el backup
|
|
local _p
|
|
for _p in "${_profiles[@]}"; do
|
|
if [[ ! -f "${_backup_dir}/${_p}/Bookmarks" ]]; then
|
|
echo "restore_chrome_bookmarks: backup no contiene perfil '${_p}': ${_backup_dir}/${_p}/Bookmarks" >&2
|
|
return 1
|
|
fi
|
|
_target_profiles+=("$_p")
|
|
done
|
|
else
|
|
# Autodescubrir todos los perfiles en el backup
|
|
local _profile_path
|
|
while IFS= read -r -d '' _profile_path; do
|
|
local _pname
|
|
_pname="$(basename "$(dirname "$_profile_path")")"
|
|
_target_profiles+=("$_pname")
|
|
done < <(find "$_backup_dir" -mindepth 2 -maxdepth 2 -name "Bookmarks" -print0 | sort -z)
|
|
|
|
if [[ ${#_target_profiles[@]} -eq 0 ]]; then
|
|
echo "restore_chrome_bookmarks: no se encontraron archivos Bookmarks en: ${_backup_dir}" >&2
|
|
return 1
|
|
fi
|
|
fi
|
|
|
|
# ── restaurar cada perfil ─────────────────────────────────────────────────
|
|
local _restored_json=""
|
|
local _first=1
|
|
|
|
local _prof
|
|
for _prof in "${_target_profiles[@]}"; do
|
|
local _src="${_backup_dir}/${_prof}/Bookmarks"
|
|
local _dst_dir="${_user_data_dir}/${_prof}"
|
|
local _dst="${_dst_dir}/Bookmarks"
|
|
local _dst_bak="${_dst_dir}/Bookmarks.bak"
|
|
|
|
# Tamaño del archivo fuente para el JSON de salida
|
|
local _bytes=0
|
|
if [[ -f "$_src" ]]; then
|
|
_bytes="$(wc -c < "$_src")"
|
|
# Eliminar espacios que wc puede añadir en algunas plataformas
|
|
_bytes="${_bytes// /}"
|
|
fi
|
|
|
|
if [[ $_dry_run -eq 1 ]]; then
|
|
echo "=== restore_chrome_bookmarks DRY-RUN ===" >&2
|
|
echo " Perfil : ${_prof}" >&2
|
|
echo " src : ${_src}" >&2
|
|
echo " dst : ${_dst}" >&2
|
|
echo " bytes : ${_bytes}" >&2
|
|
if [[ -f "$_dst_bak" ]]; then
|
|
echo " .bak : borraría ${_dst_bak}" >&2
|
|
fi
|
|
else
|
|
# Crear directorio destino si no existe
|
|
mkdir -p "$_dst_dir"
|
|
|
|
# Copiar byte a byte preservando timestamps (NUNCA reserializar)
|
|
cp -p "$_src" "$_dst"
|
|
|
|
# Borrar Bookmarks.bak residual si existe
|
|
if [[ -f "$_dst_bak" ]]; then
|
|
rm -f "$_dst_bak"
|
|
fi
|
|
fi
|
|
|
|
# Construir fragmento JSON para este perfil
|
|
local _entry
|
|
_entry="$(printf '{"profile":"%s","dst":"%s","bytes":%s}' \
|
|
"$_prof" "$_dst" "$_bytes")"
|
|
|
|
if [[ $_first -eq 1 ]]; then
|
|
_restored_json="${_entry}"
|
|
_first=0
|
|
else
|
|
_restored_json+=",$_entry"
|
|
fi
|
|
done
|
|
|
|
# ── emitir resultado JSON ─────────────────────────────────────────────────
|
|
printf '{"restored":[%s]}\n' "$_restored_json"
|
|
}
|
|
|
|
# ── auto-ejecución ────────────────────────────────────────────────────────────
|
|
if [[ "${BASH_SOURCE[0]}" == "${0}" ]]; then
|
|
restore_chrome_bookmarks "$@"
|
|
fi
|