From b828c516941a6aead60198a7b79def8cb62bfd4f Mon Sep 17 00:00:00 2001 From: Cole Arendt Date: Sun, 11 Nov 2018 22:38:30 -0500 Subject: [PATCH 1/8] add option for multiple share directories --- nfsd.sh | 126 +++++++++++++++++++++++++++++++------------------------- 1 file changed, 70 insertions(+), 56 deletions(-) diff --git a/nfsd.sh b/nfsd.sh index b352df7..a126016 100755 --- a/nfsd.sh +++ b/nfsd.sh @@ -19,63 +19,77 @@ stop() exit } -# 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" - /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/exportsThese -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 +# How much do we need these checks? +## 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 + +# Build opts string +opts=`echo "${READ_ONLY} ${SYNC} ${FSID} ${SUBTREE_CHECK} ${ROOT_SQUASH}" | tr -s ' ' | tr ' ' ','` + +# Get mounts +mounts="${@}" + +for mnt in "${mounts[@]}"; do + src=$(echo $mnt | awk -F':' '{ print $1 }') + mkdir -p $src + echo "$src ${PERMITTED}($opts)" >> /etc/exports +done + +## 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" +# /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 + # 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 with it occurs +# We expect this at times and don't want the script to be terminated if it occurs set -uo pipefail IFS=$'\n\t' @@ -116,7 +130,7 @@ while true; do /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): + # Check if NFS is now running by recording its PID (if it is not running $pid will be null): pid=`pidof rpc.mountd` # If $pid is null, startup failed; log the fact and sleep for 2s @@ -137,7 +151,7 @@ done while true; do - # Check if NFS is STILL running by recording it's PID (if it's not running $pid will be null): + # Check if NFS is STILL running by recording its PID (if it is 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 From 1b232f5d6e00af8e8bdd7649577e07c7d05c9771 Mon Sep 17 00:00:00 2001 From: Cole Arendt Date: Sun, 11 Nov 2018 22:51:01 -0500 Subject: [PATCH 2/8] add default parameters for backwards compatibility --- nfsd.sh | 82 +++++++++++++++++++++++++++++++++------------------------ 1 file changed, 48 insertions(+), 34 deletions(-) diff --git a/nfsd.sh b/nfsd.sh index a126016..eb4cc90 100755 --- a/nfsd.sh +++ b/nfsd.sh @@ -20,41 +20,55 @@ stop() } # How much do we need these checks? -## 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 +# 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." + PERMITTED=* +else + echo "The PERMITTED environment variable is set." + echo "The permitted clients are: ${PERMITTED}." +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." + SET_OPTS=rw +else + echo "The READ_ONLY environment variable is set." + echo "Clients will have read-only access." + SET_OPTS=ro +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." + SET_OPTS=${SET_OPTS},async +else + echo "The SYNC environment variable is set, using 'sync' mode". + echo "Writes will be immediately written to disk." + SET_OPTS=${SET_OPTS},sync +fi + +# if NFS_OPTS is not set +# then use legacy approach +if [ -z "${NFS_OPTS}" ]; then + # set default options from legacy approach + DEFAULT_OPTS=fsid=0,no_subtree_check,no_auth_nlm,insecure,no_root_squash + + # Build opts string + opts=`echo "${SET_OPTS} ${DEFAULT_OPTS}" | tr -s ' ' | tr ' ' ','` +else + + # Otherwise use NFS_OPTS directly + + # Build opts string + opts=`echo "${NFS_OPTS}" | tr -s ' ' | tr ' ' ','` +fi; + -# Build opts string -opts=`echo "${READ_ONLY} ${SYNC} ${FSID} ${SUBTREE_CHECK} ${ROOT_SQUASH}" | tr -s ' ' | tr ' ' ','` # Get mounts mounts="${@}" From eb931c625236ba02caea0137d6fa078aae3c7129 Mon Sep 17 00:00:00 2001 From: Cole Arendt Date: Sun, 11 Nov 2018 22:52:53 -0500 Subject: [PATCH 3/8] remove space-replacing magic for clarity --- nfsd.sh | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/nfsd.sh b/nfsd.sh index eb4cc90..45d5872 100755 --- a/nfsd.sh +++ b/nfsd.sh @@ -59,13 +59,13 @@ if [ -z "${NFS_OPTS}" ]; then DEFAULT_OPTS=fsid=0,no_subtree_check,no_auth_nlm,insecure,no_root_squash # Build opts string - opts=`echo "${SET_OPTS} ${DEFAULT_OPTS}" | tr -s ' ' | tr ' ' ','` + opts=${SET_OPTS},${DEFAULT_OPTS} else # Otherwise use NFS_OPTS directly # Build opts string - opts=`echo "${NFS_OPTS}" | tr -s ' ' | tr ' ' ','` + opts=${NFS_OPTS} fi; From 4ea2c34161d11688bbe2822c0314be846e99295e Mon Sep 17 00:00:00 2001 From: Cole Arendt Date: Sun, 11 Nov 2018 22:59:07 -0500 Subject: [PATCH 4/8] add SHARED_DIRECTORY for backwards compatibility --- nfsd.sh | 31 ++++++++----------------------- 1 file changed, 8 insertions(+), 23 deletions(-) diff --git a/nfsd.sh b/nfsd.sh index 45d5872..8336287 100755 --- a/nfsd.sh +++ b/nfsd.sh @@ -68,7 +68,14 @@ else opts=${NFS_OPTS} fi; - +# Check if the SHARED_DIRECTORY variable is empty +if [ -z "${SHARED_DIRECTORY}" ]; then + echo "The SHARED_DIRECTORY environment variable is unset or null, using new approach" +else + echo "SHARED_DIRECTORY is set. Please use CMD instead" + echo "Adding SHARED_DIRECTORY to CMD input" + mounts[${#mounts[@]}]=$SHARED_DIRECTORY +fi # Get mounts mounts="${@}" @@ -79,28 +86,6 @@ for mnt in "${mounts[@]}"; do echo "$src ${PERMITTED}($opts)" >> /etc/exports done -## 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" -# /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 - - # 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 if it occurs From cc722d148342b4fd9d1ed20757e075a7162e76ad Mon Sep 17 00:00:00 2001 From: Cole Arendt Date: Sun, 11 Nov 2018 23:17:12 -0500 Subject: [PATCH 5/8] remove dependency on template file --- Dockerfile | 1 - 1 file changed, 1 deletion(-) diff --git a/Dockerfile b/Dockerfile index 8d502e3..7d8ee12 100644 --- a/Dockerfile +++ b/Dockerfile @@ -10,7 +10,6 @@ RUN apk add --no-cache --update --verbose nfs-utils bash iproute2 && \ echo "rpc_pipefs /var/lib/nfs/rpc_pipefs rpc_pipefs defaults 0 0" >> /etc/fstab && \ echo "nfsd /proc/fs/nfsd nfsd defaults 0 0" >> /etc/fstab -COPY exports /etc/ COPY nfsd.sh /usr/bin/nfsd.sh COPY .bashrc /root/.bashrc From 0d8a103da00983ea29b3ad7c7391451e7eb2bd2c Mon Sep 17 00:00:00 2001 From: Cole Arendt Date: Sun, 11 Nov 2018 23:17:23 -0500 Subject: [PATCH 6/8] remove template file --- exports | 1 - 1 file changed, 1 deletion(-) delete mode 100644 exports diff --git a/exports b/exports deleted file mode 100644 index 65f29e0..0000000 --- a/exports +++ /dev/null @@ -1 +0,0 @@ -{{SHARED_DIRECTORY}} {{PERMITTED}}({{READ_ONLY}},fsid=0,{{SYNC}},no_subtree_check,no_auth_nlm,insecure,no_root_squash) From ac153948f93aed2ecaef47c33c338cd2cda7d8b4 Mon Sep 17 00:00:00 2001 From: Cole Arendt Date: Sun, 11 Nov 2018 23:17:39 -0500 Subject: [PATCH 7/8] fix array reference add comments add logging --- nfsd.sh | 10 ++++++---- 1 file changed, 6 insertions(+), 4 deletions(-) diff --git a/nfsd.sh b/nfsd.sh index 8336287..4ad8ab6 100755 --- a/nfsd.sh +++ b/nfsd.sh @@ -19,7 +19,9 @@ stop() exit } -# How much do we need these checks? +# Get mounts +mounts=( "${@}" ) + # Check if the PERMITTED variable is empty if [ -z "${PERMITTED}" ]; then echo "The PERMITTED environment variable is unset or null, defaulting to '*'." @@ -55,6 +57,7 @@ fi # if NFS_OPTS is not set # then use legacy approach if [ -z "${NFS_OPTS}" ]; then + echo "NFS_OPTS has not been defined. Adding default parameters" # set default options from legacy approach DEFAULT_OPTS=fsid=0,no_subtree_check,no_auth_nlm,insecure,no_root_squash @@ -63,6 +66,7 @@ if [ -z "${NFS_OPTS}" ]; then else # Otherwise use NFS_OPTS directly + echo "NFS_OPTS has been defined. Disregarding READ_ONLY,SYNC, and default parameters" # Build opts string opts=${NFS_OPTS} @@ -77,10 +81,8 @@ else mounts[${#mounts[@]}]=$SHARED_DIRECTORY fi -# Get mounts -mounts="${@}" - for mnt in "${mounts[@]}"; do + echo "Setting up exports for mount: $mnt" src=$(echo $mnt | awk -F':' '{ print $1 }') mkdir -p $src echo "$src ${PERMITTED}($opts)" >> /etc/exports From 0976737e24e652725ed69a9d3f670e27426f19d0 Mon Sep 17 00:00:00 2001 From: Cole Arendt Date: Mon, 12 Nov 2018 14:10:59 -0500 Subject: [PATCH 8/8] remove unnecessary logging --- nfsd.sh | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/nfsd.sh b/nfsd.sh index 4ad8ab6..a551499 100755 --- a/nfsd.sh +++ b/nfsd.sh @@ -73,9 +73,7 @@ else fi; # Check if the SHARED_DIRECTORY variable is empty -if [ -z "${SHARED_DIRECTORY}" ]; then - echo "The SHARED_DIRECTORY environment variable is unset or null, using new approach" -else +if [ ! -z "${SHARED_DIRECTORY}" ]; then echo "SHARED_DIRECTORY is set. Please use CMD instead" echo "Adding SHARED_DIRECTORY to CMD input" mounts[${#mounts[@]}]=$SHARED_DIRECTORY