123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295 |
- #!/usr/bin/env bash
- #===============================================================================
- # FILE: samba.sh
- #
- # USAGE: ./samba.sh
- #
- # DESCRIPTION: Entrypoint for samba docker container
- #
- # OPTIONS: ---
- # REQUIREMENTS: ---
- # BUGS: ---
- # NOTES: ---
- # AUTHOR: David Personette ([email protected]),
- # ORGANIZATION:
- # CREATED: 09/28/2014 12:11
- # REVISION: 1.0
- #===============================================================================
- set -o nounset # Treat unset variables as an error
- ### charmap: setup character mapping for file/directory names
- # Arguments:
- # chars) from:to character mappings separated by ','
- # Return: configured character mapings
- charmap() { local chars="$1" file=/etc/samba/smb.conf
- grep -q catia $file || sed -i '/TCP_NODELAY/a \
- \
- vfs objects = catia\
- catia:mappings =\
- ' $file
- sed -i '/catia:mappings/s| =.*| = '"$chars"'|' $file
- }
- ### generic: set a generic config option in a section
- # Arguments:
- # section) section of config file
- # option) raw option
- # Return: line added to smb.conf (replaces existing line with same key)
- generic() { local section="$1" key="$(sed 's| *=.*||' <<< $2)" \
- value="$(sed 's|[^=]*= *||' <<< $2)" file=/etc/samba/smb.conf
- if sed -n '/^\['"$section"'\]/,/^\[/p' $file | grep -qE '^;*\s*'"$key"; then
- sed -i '/^\['"$1"'\]/,/^\[/s|^;*\s*\('"$key"' = \).*| \1'"$value"'|' \
- "$file"
- else
- sed -i '/\['"$section"'\]/a \ '"$key = $value" "$file"
- fi
- }
- ### global: set a global config option
- # Arguments:
- # option) raw option
- # Return: line added to smb.conf (replaces existing line with same key)
- global() { local key="$(sed 's| *=.*||' <<< $1)" \
- value="$(sed 's|[^=]*= *||' <<< $1)" file=/etc/samba/smb.conf
- if sed -n '/^\[global\]/,/^\[/p' $file | grep -qE '^;*\s*'"$key"; then
- sed -i '/^\[global\]/,/^\[/s|^;*\s*\('"$key"' = \).*| \1'"$value"'|' \
- "$file"
- else
- sed -i '/\[global\]/a \ '"$key = $value" "$file"
- fi
- }
- ### include: add a samba config file include
- # Arguments:
- # file) file to import
- include() { local includefile="$1" file=/etc/samba/smb.conf
- sed -i "\\|include = $includefile|d" "$file"
- echo "include = $includefile" >> "$file"
- }
- ### import: import a smbpasswd file
- # Arguments:
- # file) file to import
- # Return: user(s) added to container
- import() { local file="$1" name id
- while read name id; do
- grep -q "^$name:" /etc/passwd || adduser -D -H -u "$id" "$name"
- done < <(cut -d: -f1,2 $file | sed 's/:/ /')
- pdbedit -i smbpasswd:$file
- }
- ### perms: fix ownership and permissions of share paths
- # Arguments:
- # none)
- # Return: result
- perms() { local i file=/etc/samba/smb.conf
- for i in $(awk -F ' = ' '/ path = / {print $2}' $file); do
- chown -Rh smbuser. $i
- find $i -type d ! -perm 775 -exec chmod 775 {} \;
- find $i -type f ! -perm 0664 -exec chmod 0664 {} \;
- done
- }
- export -f perms
- ### recycle: disable recycle bin
- # Arguments:
- # none)
- # Return: result
- recycle() { local file=/etc/samba/smb.conf
- sed -i '/recycle:/d; /vfs objects/s/ recycle / /' $file
- }
- ### share: Add share
- # Arguments:
- # share) share name
- # path) path to share
- # browsable) 'yes' or 'no'
- # readonly) 'yes' or 'no'
- # guest) 'yes' or 'no'
- # users) list of allowed users
- # admins) list of admin users
- # writelist) list of users that can write to a RO share
- # comment) description of share
- # Return: result
- share() { local share="$1" path="$2" browsable="${3:-yes}" ro="${4:-yes}" \
- guest="${5:-yes}" users="${6:-""}" admins="${7:-""}" \
- writelist="${8:-""}" comment="${9:-""}" file=/etc/samba/smb.conf
- sed -i "/\\[$share\\]/,/^\$/d" $file
- echo "[$share]" >>$file
- echo " path = $path" >>$file
- echo " browsable = $browsable" >>$file
- echo " read only = $ro" >>$file
- echo " guest ok = $guest" >>$file
- [[ ${VETO:-yes} == no ]] || {
- echo -n " veto files = /.apdisk/.DS_Store/.TemporaryItems/" >>$file
- echo -n ".Trashes/desktop.ini/ehthumbs.db/Network Trash Folder/" >>$file
- echo "Temporary Items/Thumbs.db/" >>$file
- echo " delete veto files = yes" >>$file
- }
- [[ ${users:-""} && ! ${users:-""} == all ]] &&
- echo " valid users = $(tr ',' ' ' <<< $users)" >>$file
- [[ ${admins:-""} && ! ${admins:-""} =~ none ]] &&
- echo " admin users = $(tr ',' ' ' <<< $admins)" >>$file
- [[ ${writelist:-""} && ! ${writelist:-""} =~ none ]] &&
- echo " write list = $(tr ',' ' ' <<< $writelist)" >>$file
- [[ ${comment:-""} && ! ${comment:-""} =~ none ]] &&
- echo " comment = $(tr ',' ' ' <<< $comment)" >>$file
- echo "" >>$file
- [[ -d $path ]] || mkdir -p $path
- }
- ### smb: disable SMB2 minimum
- # Arguments:
- # none)
- # Return: result
- smb() { local file=/etc/samba/smb.conf
- sed -i 's/\([^#]*min protocol *=\).*/\1 LANMAN1/' $file
- }
- ### user: add a user
- # Arguments:
- # name) for user
- # password) for user
- # id) for user
- # group) for user
- # gid) for group
- # Return: user added to container
- user() { local name="$1" passwd="$2" id="${3:-""}" group="${4:-""}" \
- gid="${5:-""}"
- [[ "$group" ]] && { grep -q "^$group:" /etc/group ||
- addgroup ${gid:+--gid $gid }"$group"; }
- grep -q "^$name:" /etc/passwd ||
- adduser -D -H ${group:+-G $group} ${id:+-u $id} "$name"
- echo -e "$passwd\n$passwd" | smbpasswd -s -a "$name"
- }
- ### workgroup: set the workgroup
- # Arguments:
- # workgroup) the name to set
- # Return: configure the correct workgroup
- workgroup() { local workgroup="$1" file=/etc/samba/smb.conf
- sed -i 's|^\( *workgroup = \).*|\1'"$workgroup"'|' $file
- }
- ### widelinks: allow access wide symbolic links
- # Arguments:
- # none)
- # Return: result
- widelinks() { local file=/etc/samba/smb.conf \
- replace='\1\n wide links = yes\n unix extensions = no'
- sed -i 's/\(follow symlinks = yes\)/'"$replace"'/' $file
- }
- ### usage: Help
- # Arguments:
- # none)
- # Return: Help text
- usage() { local RC="${1:-0}"
- echo "Usage: ${0##*/} [-opt] [command]
- Options (fields in '[]' are optional, '<>' are required):
- -h This help
- -c \"<from:to>\" setup character mapping for file/directory names
- required arg: \"<from:to>\" character mappings separated by ','
- -G \"<section;parameter>\" Provide generic section option for smb.conf
- required arg: \"<section>\" - IE: \"share\"
- required arg: \"<parameter>\" - IE: \"log level = 2\"
- -g \"<parameter>\" Provide global option for smb.conf
- required arg: \"<parameter>\" - IE: \"log level = 2\"
- -i \"<path>\" Import smbpassword
- required arg: \"<path>\" - full file path in container
- -n Start the 'nmbd' daemon to advertise the shares
- -p Set ownership and permissions on the shares
- -r Disable recycle bin for shares
- -S Disable SMB2 minimum version
- -s \"<name;/path>[;browse;readonly;guest;users;admins;writelist;comment]\"
- Configure a share
- required arg: \"<name>;</path>\"
- <name> is how it's called for clients
- <path> path to share
- NOTE: for the default value, just leave blank
- [browsable] default:'yes' or 'no'
- [readonly] default:'yes' or 'no'
- [guest] allowed default:'yes' or 'no'
- NOTE: for user lists below, usernames are separated by ','
- [users] allowed default:'all' or list of allowed users
- [admins] allowed default:'none' or list of admin users
- [writelist] list of users that can write to a RO share
- [comment] description of share
- -u \"<username;password>[;ID;group;GID]\" Add a user
- required arg: \"<username>;<passwd>\"
- <username> for user
- <password> for user
- [ID] for user
- [group] for user
- [GID] for group
- -w \"<workgroup>\" Configure the workgroup (domain) samba should use
- required arg: \"<workgroup>\"
- <workgroup> for samba
- -W Allow access wide symbolic links
- -I Add an include option at the end of the smb.conf
- required arg: \"<include file path>\"
- <include file path> in the container, e.g. a bind mount
- The 'command' (if provided and valid) will be run instead of samba
- " >&2
- exit $RC
- }
- [[ "${USERID:-""}" =~ ^[0-9]+$ ]] && usermod -u $USERID -o smbuser
- [[ "${GROUPID:-""}" =~ ^[0-9]+$ ]] && groupmod -g $GROUPID -o smb
- while getopts ":hc:G:g:i:nprs:Su:Ww:I:" opt; do
- case "$opt" in
- h) usage ;;
- c) charmap "$OPTARG" ;;
- G) eval generic $(sed 's/^/"/; s/$/"/; s/;/" "/g' <<< $OPTARG) ;;
- g) global "$OPTARG" ;;
- i) import "$OPTARG" ;;
- n) NMBD="true" ;;
- p) PERMISSIONS="true" ;;
- r) recycle ;;
- s) eval share $(sed 's/^/"/; s/$/"/; s/;/" "/g' <<< $OPTARG) ;;
- S) smb ;;
- u) eval user $(sed 's/^/"/; s/$/"/; s/;/" "/g' <<< $OPTARG) ;;
- w) workgroup "$OPTARG" ;;
- W) widelinks ;;
- I) include "$OPTARG" ;;
- "?") echo "Unknown option: -$OPTARG"; usage 1 ;;
- ":") echo "No argument value for option: -$OPTARG"; usage 2 ;;
- esac
- done
- shift $(( OPTIND - 1 ))
- [[ "${CHARMAP:-""}" ]] && charmap "$CHARMAP"
- while read i; do
- eval generic $(sed 's/^/"/; s/$/"/; s/;/" "/g' <<< $i)
- done < <(env | awk '/^GENERIC[0-9=_]/ {sub (/^[^=]*=/, "", $0); print}')
- while read i; do
- global "$i"
- done < <(env | awk '/^GLOBAL[0-9=_]/ {sub (/^[^=]*=/, "", $0); print}')
- [[ "${IMPORT:-""}" ]] && import "$IMPORT"
- [[ "${RECYCLE:-""}" ]] && recycle
- while read i; do
- eval share $(sed 's/^/"/; s/$/"/; s/;/" "/g' <<< $i)
- done < <(env | awk '/^SHARE[0-9=_]/ {sub (/^[^=]*=/, "", $0); print}')
- [[ "${SMB:-""}" ]] && smb
- while read i; do
- eval user $(sed 's/^/"/; s/$/"/; s/;/" "/g' <<< $i)
- done < <(env | awk '/^USER[0-9=_]/ {sub (/^[^=]*=/, "", $0); print}')
- [[ "${WORKGROUP:-""}" ]] && workgroup "$WORKGROUP"
- [[ "${WIDELINKS:-""}" ]] && widelinks
- [[ "${INCLUDE:-""}" ]] && include "$INCLUDE"
- [[ "${PERMISSIONS:-""}" ]] && perms &
- if [[ $# -ge 1 && -x $(which $1 2>&-) ]]; then
- exec "$@"
- elif [[ $# -ge 1 ]]; then
- echo "ERROR: command not found: $1"
- exit 13
- elif ps -ef | egrep -v grep | grep -q smbd; then
- echo "Service already running, please restart container to apply changes"
- else
- [[ ${NMBD:-""} ]] && ionice -c 3 nmbd -D
- exec ionice -c 3 smbd --foreground --no-process-group </dev/null
- fi
|