Skip to content

Commit 6d6d24d

Browse files
committed
feat(fnos-mount-manager): 添加 remount 命令功能
新增 remount 命令用于将被 FNOS 挂载到错误路径的磁盘重新挂回正确的业务名路径, 同时修复了 apply 命令中 tmpfiles 配置文件安装逻辑,并添加了完整的测试用例。
1 parent c1cb174 commit 6d6d24d

6 files changed

Lines changed: 374 additions & 3 deletions

File tree

linux/fnos/fnos-mount-manager/README.md

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -44,6 +44,9 @@ bash linux/fnos/fnos-mount-manager/fnos-mount-manager.sh apply --target /tmp/fst
4444

4545
# 执行统一修复
4646
bash linux/fnos/fnos-mount-manager/fnos-mount-manager.sh repair
47+
48+
# 把被 FNOS 挂到型号路径的磁盘重新挂回业务名路径
49+
bash linux/fnos/fnos-mount-manager/fnos-mount-manager.sh remount
4750
```
4851

4952
## 迁移说明

linux/fnos/fnos-mount-manager/build.sh

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,7 @@ MODULES=(
1818
"${SOURCE_DIR}/commands/check.sh"
1919
"${SOURCE_DIR}/commands/status.sh"
2020
"${SOURCE_DIR}/commands/repair.sh"
21+
"${SOURCE_DIR}/commands/remount.sh"
2122
"${SOURCE_DIR}/main.sh"
2223
)
2324

Lines changed: 98 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,98 @@
1+
# shellcheck shell=bash
2+
3+
if [[ -n "${FNOS_MOUNT_MANAGER_REMOUNT_LOADED:-}" ]]; then
4+
return 0
5+
fi
6+
FNOS_MOUNT_MANAGER_REMOUNT_LOADED=1
7+
8+
# 以更主动的方式把磁盘重新挂到受管挂载点:
9+
# 若设备已经被挂到错误路径,会先卸载错误目标,再按我们的挂载点重挂。
10+
fm_remount_disk() {
11+
local index="$1"
12+
local name="${FM_CONFIG_DISK_NAMES[${index}]}"
13+
local source="${FM_CONFIG_DISK_SOURCES[${index}]}"
14+
local mountpoint="${FM_CONFIG_DISK_MOUNTPOINTS[${index}]}"
15+
local device_path
16+
device_path="$(fm_source_to_device_path "${source}")"
17+
18+
local mounted_target=""
19+
mounted_target="$(fm_find_mount_target_for_device "${device_path}")"
20+
21+
if [[ "${mounted_target}" == "${mountpoint}" ]]; then
22+
fm_log "info" "${name} already mounted at ${mountpoint}"
23+
return 0
24+
fi
25+
26+
fm_run_privileged mkdir -p "${mountpoint}"
27+
28+
if [[ -n "${mounted_target}" ]]; then
29+
fm_log "warn" "${name} device is mounted at ${mounted_target}; remounting to ${mountpoint}"
30+
31+
if ! fm_run_privileged umount "${mounted_target}" >/dev/null 2>&1; then
32+
# FNOS 相关服务可能仍持有旧路径句柄,显式 remount 时退到 lazy umount。
33+
fm_run_privileged umount -l "${mounted_target}" >/dev/null 2>&1 || true
34+
fi
35+
36+
mounted_target="$(fm_find_mount_target_for_device "${device_path}")"
37+
if [[ -n "${mounted_target}" ]]; then
38+
fm_log "warn" "${name} device is still mounted at ${mounted_target}"
39+
return 1
40+
fi
41+
fi
42+
43+
if command -v systemctl >/dev/null 2>&1; then
44+
local mount_unit
45+
mount_unit="$(fm_unit_name_for_path "${mountpoint}" mount)"
46+
fm_run_privileged systemctl reset-failed "${mount_unit}" >/dev/null 2>&1 || true
47+
fm_run_privileged systemctl stop "${mount_unit}" >/dev/null 2>&1 || true
48+
49+
local automount_unit
50+
automount_unit="$(fm_unit_name_for_path "${mountpoint}" automount)"
51+
fm_run_privileged systemctl reset-failed "${automount_unit}" >/dev/null 2>&1 || true
52+
fm_run_privileged systemctl stop "${automount_unit}" >/dev/null 2>&1 || true
53+
fi
54+
55+
if fm_run_privileged mount "${mountpoint}" >/dev/null 2>&1; then
56+
fm_log "info" "Remounted ${name} to ${mountpoint}"
57+
return 0
58+
fi
59+
60+
fm_log "warn" "Remount failed for ${name}"
61+
return 1
62+
}
63+
64+
# 显式接管错误挂载并切回受管命名。
65+
fm_cmd_remount() {
66+
while [[ $# -gt 0 ]]; do
67+
case "$1" in
68+
--help | -h)
69+
cat <<'EOF'
70+
Usage: fnos-mount-manager remount
71+
72+
Force managed disks back onto the configured mountpoints.
73+
EOF
74+
return 0
75+
;;
76+
*)
77+
fm_die "Unknown remount option: $1"
78+
;;
79+
esac
80+
done
81+
82+
[[ -f "$(fm_local_config_path)" ]] || fm_die "Local config not found: $(fm_local_config_path)"
83+
fm_load_config "$(fm_local_config_path)"
84+
85+
local failures=0
86+
local i
87+
for (( i = 0; i < ${#FM_CONFIG_DISK_NAMES[@]}; i += 1 )); do
88+
if ! fm_remount_disk "${i}"; then
89+
failures=$(( failures + 1 ))
90+
fi
91+
done
92+
93+
if (( failures > 0 )); then
94+
fm_die "Remount completed with ${failures} failure(s)"
95+
fi
96+
97+
fm_log "info" "Remount completed successfully"
98+
}

linux/fnos/fnos-mount-manager/fnos-mount-manager.sh

Lines changed: 115 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -642,6 +642,7 @@ fm_prepare_mountpoints() {
642642
fm_cmd_apply() {
643643
local target="/etc/fstab"
644644
local tmpfiles_target="/etc/tmpfiles.d/fnos-mount-manager.conf"
645+
local install_tmpfiles="0"
645646

646647
while [[ $# -gt 0 ]]; do
647648
case "$1" in
@@ -651,6 +652,7 @@ fm_cmd_apply() {
651652
;;
652653
--tmpfiles-target)
653654
tmpfiles_target="$2"
655+
install_tmpfiles="1"
654656
shift 2
655657
;;
656658
--help | -h)
@@ -682,13 +684,14 @@ EOF
682684

683685
if [[ "${target}" == "/etc/fstab" ]]; then
684686
fm_prepare_mountpoints
687+
install_tmpfiles="1"
685688
fi
686689

687690
fm_install_file "${temp_output}" "${target}"
688691
rm -f "${temp_output}"
689692
fm_log "info" "Applied managed block to ${target}"
690693

691-
if [[ "${target}" == "/etc/fstab" ]]; then
694+
if [[ "${install_tmpfiles}" == "1" ]]; then
692695
fm_install_file "$(fm_local_tmpfiles_path)" "${tmpfiles_target}"
693696
fm_log "info" "Applied tmpfiles rules to ${tmpfiles_target}"
694697
fi
@@ -762,16 +765,18 @@ fm_check_rendered_file() {
762765
fi
763766

764767
local temp_render
768+
local temp_tmpfiles
765769
temp_render="$(mktemp)"
770+
temp_tmpfiles="$(mktemp)"
766771

767-
fm_generate_scope "${config_path}" "${temp_render}" "${source_label}"
772+
fm_generate_scope "${config_path}" "${temp_render}" "${temp_tmpfiles}" "${source_label}"
768773

769774
if ! cmp -s "${rendered_path}" "${temp_render}"; then
770775
fm_log "error" "Rendered file is stale: ${rendered_path}"
771776
error_count_ref=$(( error_count_ref + 1 ))
772777
fi
773778

774-
rm -f "${temp_render}"
779+
rm -f "${temp_render}" "${temp_tmpfiles}"
775780
}
776781

777782
# 检查已知的 shell 登录补挂载片段,避免把副作用留在非显式命令路径里。
@@ -1086,6 +1091,107 @@ EOF
10861091
}
10871092

10881093

1094+
# --- remount.sh ---
1095+
# shellcheck shell=bash
1096+
1097+
if [[ -n "${FNOS_MOUNT_MANAGER_REMOUNT_LOADED:-}" ]]; then
1098+
return 0
1099+
fi
1100+
FNOS_MOUNT_MANAGER_REMOUNT_LOADED=1
1101+
1102+
# 以更主动的方式把磁盘重新挂到受管挂载点:
1103+
# 若设备已经被挂到错误路径,会先卸载错误目标,再按我们的挂载点重挂。
1104+
fm_remount_disk() {
1105+
local index="$1"
1106+
local name="${FM_CONFIG_DISK_NAMES[${index}]}"
1107+
local source="${FM_CONFIG_DISK_SOURCES[${index}]}"
1108+
local mountpoint="${FM_CONFIG_DISK_MOUNTPOINTS[${index}]}"
1109+
local device_path
1110+
device_path="$(fm_source_to_device_path "${source}")"
1111+
1112+
local mounted_target=""
1113+
mounted_target="$(fm_find_mount_target_for_device "${device_path}")"
1114+
1115+
if [[ "${mounted_target}" == "${mountpoint}" ]]; then
1116+
fm_log "info" "${name} already mounted at ${mountpoint}"
1117+
return 0
1118+
fi
1119+
1120+
fm_run_privileged mkdir -p "${mountpoint}"
1121+
1122+
if [[ -n "${mounted_target}" ]]; then
1123+
fm_log "warn" "${name} device is mounted at ${mounted_target}; remounting to ${mountpoint}"
1124+
1125+
if ! fm_run_privileged umount "${mounted_target}" >/dev/null 2>&1; then
1126+
# FNOS 相关服务可能仍持有旧路径句柄,显式 remount 时退到 lazy umount。
1127+
fm_run_privileged umount -l "${mounted_target}" >/dev/null 2>&1 || true
1128+
fi
1129+
1130+
mounted_target="$(fm_find_mount_target_for_device "${device_path}")"
1131+
if [[ -n "${mounted_target}" ]]; then
1132+
fm_log "warn" "${name} device is still mounted at ${mounted_target}"
1133+
return 1
1134+
fi
1135+
fi
1136+
1137+
if command -v systemctl >/dev/null 2>&1; then
1138+
local mount_unit
1139+
mount_unit="$(fm_unit_name_for_path "${mountpoint}" mount)"
1140+
fm_run_privileged systemctl reset-failed "${mount_unit}" >/dev/null 2>&1 || true
1141+
fm_run_privileged systemctl stop "${mount_unit}" >/dev/null 2>&1 || true
1142+
1143+
local automount_unit
1144+
automount_unit="$(fm_unit_name_for_path "${mountpoint}" automount)"
1145+
fm_run_privileged systemctl reset-failed "${automount_unit}" >/dev/null 2>&1 || true
1146+
fm_run_privileged systemctl stop "${automount_unit}" >/dev/null 2>&1 || true
1147+
fi
1148+
1149+
if fm_run_privileged mount "${mountpoint}" >/dev/null 2>&1; then
1150+
fm_log "info" "Remounted ${name} to ${mountpoint}"
1151+
return 0
1152+
fi
1153+
1154+
fm_log "warn" "Remount failed for ${name}"
1155+
return 1
1156+
}
1157+
1158+
# 显式接管错误挂载并切回受管命名。
1159+
fm_cmd_remount() {
1160+
while [[ $# -gt 0 ]]; do
1161+
case "$1" in
1162+
--help | -h)
1163+
cat <<'EOF'
1164+
Usage: fnos-mount-manager remount
1165+
1166+
Force managed disks back onto the configured mountpoints.
1167+
EOF
1168+
return 0
1169+
;;
1170+
*)
1171+
fm_die "Unknown remount option: $1"
1172+
;;
1173+
esac
1174+
done
1175+
1176+
[[ -f "$(fm_local_config_path)" ]] || fm_die "Local config not found: $(fm_local_config_path)"
1177+
fm_load_config "$(fm_local_config_path)"
1178+
1179+
local failures=0
1180+
local i
1181+
for (( i = 0; i < ${#FM_CONFIG_DISK_NAMES[@]}; i += 1 )); do
1182+
if ! fm_remount_disk "${i}"; then
1183+
failures=$(( failures + 1 ))
1184+
fi
1185+
done
1186+
1187+
if (( failures > 0 )); then
1188+
fm_die "Remount completed with ${failures} failure(s)"
1189+
fi
1190+
1191+
fm_log "info" "Remount completed successfully"
1192+
}
1193+
1194+
10891195
# --- main.sh ---
10901196
#!/usr/bin/env bash
10911197
set -Eeuo pipefail
@@ -1107,6 +1213,8 @@ if [[ -z "${FNOS_MANAGER_STANDALONE:-}" ]]; then
11071213
source "${SCRIPT_DIR}/commands/status.sh"
11081214
# shellcheck source=linux/fnos/fnos-mount-manager/commands/repair.sh
11091215
source "${SCRIPT_DIR}/commands/repair.sh"
1216+
# shellcheck source=linux/fnos/fnos-mount-manager/commands/remount.sh
1217+
source "${SCRIPT_DIR}/commands/remount.sh"
11101218
fi
11111219

11121220
# 输出统一帮助信息,说明配置路径和常用命令。
@@ -1120,6 +1228,7 @@ Commands:
11201228
check Validate config drift and known conflicts
11211229
status Show current disk and unit status
11221230
repair Attempt a unified mount repair
1231+
remount Move disks back onto the managed mountpoints
11231232
help Show this help
11241233
EOF
11251234
}
@@ -1147,6 +1256,9 @@ fm_main() {
11471256
repair)
11481257
fm_cmd_repair "$@"
11491258
;;
1259+
remount)
1260+
fm_cmd_remount "$@"
1261+
;;
11501262
help | --help | -h)
11511263
fm_show_help
11521264
;;

linux/fnos/fnos-mount-manager/main.sh

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,8 @@ if [[ -z "${FNOS_MANAGER_STANDALONE:-}" ]]; then
1818
source "${SCRIPT_DIR}/commands/status.sh"
1919
# shellcheck source=linux/fnos/fnos-mount-manager/commands/repair.sh
2020
source "${SCRIPT_DIR}/commands/repair.sh"
21+
# shellcheck source=linux/fnos/fnos-mount-manager/commands/remount.sh
22+
source "${SCRIPT_DIR}/commands/remount.sh"
2123
fi
2224

2325
# 输出统一帮助信息,说明配置路径和常用命令。
@@ -31,6 +33,7 @@ Commands:
3133
check Validate config drift and known conflicts
3234
status Show current disk and unit status
3335
repair Attempt a unified mount repair
36+
remount Move disks back onto the managed mountpoints
3437
help Show this help
3538
EOF
3639
}
@@ -58,6 +61,9 @@ fm_main() {
5861
repair)
5962
fm_cmd_repair "$@"
6063
;;
64+
remount)
65+
fm_cmd_remount "$@"
66+
;;
6167
help | --help | -h)
6268
fm_show_help
6369
;;

0 commit comments

Comments
 (0)