-
Notifications
You must be signed in to change notification settings - Fork 190
/
nfsd.sh
executable file
·159 lines (133 loc) · 5.42 KB
/
nfsd.sh
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
149
150
151
152
153
154
155
156
157
158
159
#!/bin/bash
# Make sure we react to these signals by running stop() when we see them - for clean shutdown
# And then exiting
trap "stop; exit 0;" SIGTERM SIGINT
stop()
{
# We're here because we've seen SIGTERM, likely via a Docker stop command or similar
# Let's shutdown cleanly
echo "SIGTERM caught, terminating NFS process(es)..."
/usr/sbin/exportfs -uav
/usr/sbin/rpc.nfsd 0
pid1=`pidof rpc.nfsd`
pid2=`pidof rpc.mountd`
# For IPv6 bug:
pid3=`pidof rpcbind`
kill -TERM $pid1 $pid2 $pid3 > /dev/null 2>&1
echo "Terminated."
exit
}
rm /etc/exports
# Check if the SHARED_DIRECTORY variable is empty
if [ -z "${SHARED_DIRECTORY}" ]; then
echo "The SHARED_DIRECTORY environment variable is unset or null, exiting..."
exit 1
else
echo "Writing SHARED_DIRECTORY to /etc/exports file"
echo "{{SHARED_DIRECTORY}} {{PERMITTED}}({{READ_ONLY}},fsid=0,{{SYNC}},no_subtree_check,no_auth_nlm,insecure,no_root_squash)" >> /etc/exports
/bin/sed -i "s@{{SHARED_DIRECTORY}}@${SHARED_DIRECTORY}@g" /etc/exports
fi
# This is here to demonsrate how multiple directories can be shared. You
# would need a block like this for each extra share.
# Any additional shares MUST be subdirectories of the root directory specified
# by SHARED_DIRECTORY.
# Check if the SHARED_DIRECTORY_2 variable is empty
if [ ! -z "${SHARED_DIRECTORY_2}" ]; then
echo "Writing SHARED_DIRECTORY_2 to /etc/exports file"
echo "{{SHARED_DIRECTORY_2}} {{PERMITTED}}({{READ_ONLY}},{{SYNC}},no_subtree_check,no_auth_nlm,insecure,no_root_squash)" >> /etc/exports
/bin/sed -i "s@{{SHARED_DIRECTORY_2}}@${SHARED_DIRECTORY_2}@g" /etc/exports
fi
# Check if the PERMITTED variable is empty
if [ -z "${PERMITTED}" ]; then
echo "The PERMITTED environment variable is unset or null, defaulting to '*'."
echo "This means any client can mount."
/bin/sed -i "s/{{PERMITTED}}/*/g" /etc/exports
else
echo "The PERMITTED environment variable is set."
echo "The permitted clients are: ${PERMITTED}."
/bin/sed -i "s/{{PERMITTED}}/"${PERMITTED}"/g" /etc/exports
fi
# Check if the READ_ONLY variable is set (rather than a null string) using parameter expansion
if [ -z ${READ_ONLY+y} ]; then
echo "The READ_ONLY environment variable is unset or null, defaulting to 'rw'."
echo "Clients have read/write access."
/bin/sed -i "s/{{READ_ONLY}}/rw/g" /etc/exports
else
echo "The READ_ONLY environment variable is set."
echo "Clients will have read-only access."
/bin/sed -i "s/{{READ_ONLY}}/ro/g" /etc/exports
fi
# Check if the SYNC variable is set (rather than a null string) using parameter expansion
if [ -z "${SYNC+y}" ]; then
echo "The SYNC environment variable is unset or null, defaulting to 'async' mode".
echo "Writes will not be immediately written to disk."
/bin/sed -i "s/{{SYNC}}/async/g" /etc/exports
else
echo "The SYNC environment variable is set, using 'sync' mode".
echo "Writes will be immediately written to disk."
/bin/sed -i "s/{{SYNC}}/sync/g" /etc/exports
fi
# Partially set 'unofficial Bash Strict Mode' as described here: http://redsymbol.net/articles/unofficial-bash-strict-mode/
# We don't set -e because the pidof command returns an exit code of 1 when the specified process is not found
# We expect this at times and don't want the script to be terminated when it occurs
set -uo pipefail
IFS=$'\n\t'
# This loop runs till until we've started up successfully
while true; do
# Check if NFS is running by recording it's PID (if it's not running $pid will be null):
pid=`pidof rpc.mountd`
# If $pid is null, do this to start or restart NFS:
while [ -z "$pid" ]; do
echo "Displaying /etc/exports contents:"
cat /etc/exports
echo ""
# Normally only required if v3 will be used
# But currently enabled to overcome an NFS bug around opening an IPv6 socket
echo "Starting rpcbind..."
/sbin/rpcbind -w
echo "Displaying rpcbind status..."
/sbin/rpcinfo
# Only required if v3 will be used
# /usr/sbin/rpc.idmapd
# /usr/sbin/rpc.gssd -v
# /usr/sbin/rpc.statd
echo "Starting NFS in the background..."
/usr/sbin/rpc.nfsd --debug 8 --no-udp --no-nfs-version 2 --no-nfs-version 3
echo "Exporting File System..."
if /usr/sbin/exportfs -rv; then
/usr/sbin/exportfs
else
echo "Export validation failed, exiting..."
exit 1
fi
echo "Starting Mountd in the background..."These
/usr/sbin/rpc.mountd --debug all --no-udp --no-nfs-version 2 --no-nfs-version 3
# --exports-file /etc/exports
# Check if NFS is now running by recording it's PID (if it's not running $pid will be null):
pid=`pidof rpc.mountd`
# If $pid is null, startup failed; log the fact and sleep for 2s
# We'll then automatically loop through and try again
if [ -z "$pid" ]; then
echo "Startup of NFS failed, sleeping for 2s, then retrying..."
sleep 2
fi
done
# Break this outer loop once we've started up successfully
# Otherwise, we'll silently restart and Docker won't know
echo "Startup successful."
break
done
while true; do
# Check if NFS is STILL running by recording it's PID (if it's not running $pid will be null):
pid=`pidof rpc.mountd`
# If it is not, lets kill our PID1 process (this script) by breaking out of this while loop:
# This ensures Docker observes the failure and handles it as necessary
if [ -z "$pid" ]; then
echo "NFS has failed, exiting, so Docker can restart the container..."
break
fi
# If it is, give the CPU a rest
sleep 1
done
sleep 1
exit 1