-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathpersistent-sshfs
executable file
·148 lines (119 loc) · 4.45 KB
/
persistent-sshfs
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
#!/bin/bash
# Check if a file path is provided as an argument
if [ "$#" -ne 1 ]; then
echo "Usage: $0 <mountpoints_file>"
exit 1
fi
mountpoints_file="$1"
# Check if the file exists
if [ ! -f "$mountpoints_file" ]; then
echo "File not found: $mountpoints_file"
exit 1
fi
# Initialize an empty mounts array
declare -a mounts=()
# Read mount points from the file and add them to the mounts array
while IFS= read -r line; do
mounts+=("$line")
done <"$mountpoints_file"
# Define log levels
LOG_LEVEL_DEBUG="DEBUG"
LOG_LEVEL_INFO="INFO"
LOG_LEVEL_ERROR="ERROR"
# Default log level
LOG_LEVEL_DEFAULT="$LOG_LEVEL_INFO"
# Get the log level from the environment variable or use default
LOG_LEVEL="${LOG_LEVEL:-$LOG_LEVEL_DEFAULT}"
# Convert log levels to integers for comparison
log_level_to_int() {
case "$1" in
"$LOG_LEVEL_DEBUG") echo 3 ;;
"$LOG_LEVEL_INFO") echo 2 ;;
"$LOG_LEVEL_ERROR") echo 1 ;;
*) echo 0 ;;
esac
}
LOG_LEVEL_INT=$(log_level_to_int "$LOG_LEVEL")
log() {
local level="$1"
local message="$2"
local level_int
level_int="$(log_level_to_int "$level")"
if [ "$level_int" -le "$LOG_LEVEL_INT" ]; then
echo "$(date '+%Y-%m-%d %H:%M:%S') [$level] $message"
fi
}
log "$LOG_LEVEL_INFO" "Starting with mount points from $mountpoints_file and LOG_LEVEL=$LOG_LEVEL"
# Array to keep track of background process PIDs
declare -a pids=()
# Clean up function to unmount all mount points and kill background processes
cleanup() {
log "$LOG_LEVEL_INFO" "Cleanup: unmounting all SSHFS mounts and exiting..."
# Kill background processes
for pid in "${pids[@]}"; do
if kill -0 "$pid" 2>/dev/null; then
log "$LOG_LEVEL_INFO" "Stopping background process $pid"
kill "$pid"
fi
done
# Unmount all SSHFS mounts
for mount_info in "${mounts[@]}"; do
IFS=':' read -r -a array <<<"$mount_info"
mount_point="${array[0]}"
if mount | grep -q "on $mount_point type fuse.sshfs"; then
fusermount -u "$mount_point" && log "$LOG_LEVEL_INFO" "Unmounted $mount_point"
fi
done
}
# Check SSH key-based authentication
check_ssh_key_auth() {
local userhost="$1"
local port="$2"
# Attempt to execute a non-interactive command (`exit`) on the remote server using the specified port
while ! ssh -o BatchMode=yes -o PasswordAuthentication=no -p "$port" "$userhost" exit; do
log "$LOG_LEVEL_ERROR" "SSH key-based authentication to $userhost on port $port failed or requires a password, retrying in 10 seconds..."
sleep 10
done
log "$LOG_LEVEL_INFO" "SSH key-based authentication to $userhost on port $port successful."
}
# Trap SIGINT and SIGTERM
trap cleanup SIGINT SIGTERM
# Iterate over each mount point and handle in the background
for mount in "${mounts[@]}"; do
# Parse the mount string to extract variables
IFS=':' read -r mountpoint userhost port remotedir <<<"$(echo "$mount" | sed -E 's/(.*):(.*@.*):([0-9]+):(.*)/\1:\2:\3:\4/')"
log "$LOG_LEVEL_INFO" "Processing mount: $mountpoint"
# Ensure the local directory exists
if [ ! -d "$mountpoint" ]; then
log "$LOG_LEVEL_INFO" "$mountpoint does not exist, creating..."
mkdir -p "$mountpoint"
fi
# Launch a background process for each mount
(
# Check SSH key-based authentication using userhost and port
check_ssh_key_auth "$userhost" "$port"
# Attempt to mount, keep retrying if it fails
while true; do
if mount | grep -q "on $mountpoint type fuse.sshfs"; then
log "$LOG_LEVEL_DEBUG" "$mountpoint is already mounted."
break # Exit the loop if the mount is successful
else
log "$LOG_LEVEL_INFO" "Attempting to mount $mountpoint..."
if sshfs -o reconnect -o port="$port" "$userhost:$remotedir" "$mountpoint"; then
log "$LOG_LEVEL_INFO" "$mountpoint mounted successfully."
break # Exit the loop if the mount is successful
else
log "$LOG_LEVEL_ERROR" "Failed to mount $mountpoint on port $port, retrying in 10 seconds..."
fi
fi
sleep 10
done
) &
# Store the PID of the background process
pids+=("$!")
done
# Wait for all background processes to complete
for pid in "${pids[@]}"; do
log "$LOG_LEVEL_DEBUG" "Waiting for background process $pid to complete..."
wait "$pid"
done