#!/bin/sh # ctdb event script for Samba . $CTDB_BASE/functions detect_init_style case $CTDB_INIT_STYLE in suse) CTDB_SERVICE_SMB=${CTDB_SERVICE_SMB:-smb} CTDB_SERVICE_NMB=${CTDB_SERVICE_NMB:-nmb} CTDB_SERVICE_WINBIND=${CTDB_SERVICE_WINBIND:-winbind} ;; debian) CTDB_SERVICE_SMB=${CTDB_SERVICE_SMB:-samba} CTDB_SERVICE_NMB=${CTDB_SERVICE_NMB:-""} CTDB_SERVICE_WINBIND=${CTDB_SERVICE_WINBIND:-winbind} ;; *) # should not happen, but for now use redhat style as default: CTDB_SERVICE_SMB=${CTDB_SERVICE_SMB:-smb} CTDB_SERVICE_NMB=${CTDB_SERVICE_NMB:-""} CTDB_SERVICE_WINBIND=${CTDB_SERVICE_WINBIND:-winbind} ;; esac service_name="samba" service_start="start_samba" service_stop="stop_samba" loadconfig [ "$CTDB_MANAGES_SAMBA" = "yes" ] || [ "$CTDB_MANAGES_WINBIND" = "yes" ] || exit 0 start_samba() { # create the state directory for samba /bin/mkdir -p $CTDB_BASE/state/samba # make sure samba is not already started [ "$CTDB_MANAGES_SAMBA" = "yes" ] && { service "$CTDB_SERVICE_SMB" stop > /dev/null 2>&1 service "$CTDB_SERVICE_NMB" stop > /dev/null 2>&1 killall -0 -q smbd && { sleep 1 # make absolutely sure samba is dead killall -q -9 smbd } killall -0 -q nmbd && { sleep 1 # make absolutely sure samba is dead killall -q -9 nmbd } } # restart the winbind service check_ctdb_manages_winbind [ "$CTDB_MANAGES_WINBIND" = "yes" ] && { service "$CTDB_SERVICE_WINBIND" stop > /dev/null 2>&1 killall -0 -q winbindd && { sleep 1 # make absolutely sure winbindd is dead killall -q -9 winbindd } service "$CTDB_SERVICE_WINBIND" start } # start Samba service. Start it reniced, as under very heavy load # the number of smbd processes will mean that it leaves few cycles for # anything else [ "$CTDB_MANAGES_SAMBA" = "yes" ] && { nice_service "$CTDB_SERVICE_NMB" start nice_service "$CTDB_SERVICE_SMB" start } } stop_samba() { # shutdown Samba when ctdb goes down [ "$CTDB_MANAGES_SAMBA" = "yes" ] && { service "$CTDB_SERVICE_SMB" stop service "$CTDB_SERVICE_NMB" stop } # stop the winbind service check_ctdb_manages_winbind [ "$CTDB_MANAGES_WINBIND" = "yes" ] && { service "$CTDB_SERVICE_WINBIND" stop } } # set default samba cleanup period - in minutes [ -z "$SAMBA_CLEANUP_PERIOD" ] && { SAMBA_CLEANUP_PERIOD=10 } # we keep a cached copy of smb.conf here smbconf_cache="$CTDB_BASE/state/samba/smb.conf.cache" ############################################# # update the smb.conf cache in the foreground testparm_foreground_update() { mkdir -p "$CTDB_BASE/state/samba" || exit 1 testparm -s 2> /dev/null | egrep -v 'registry.shares.=|include.=' > "$smbconf_cache" } ############################################# # update the smb.conf cache in the background testparm_background_update() { # if the cache doesn't exist, then update in the foreground [ -f $smbconf_cache ] || { testparm_foreground_update } # otherwise do a background update ( tmpfile="${smbconf_cache}.$$" testparm -s > $tmpfile 2> /dev/null & # remember the pid of the teamparm process pid="$!" # give it 10 seconds to run timeleft=10 while [ $timeleft -gt 0 ]; do timeleft=$(($timeleft - 1)) # see if the process still exists /bin/kill -0 $pid > /dev/null 2>&1 || { # it doesn't exist, grab its exit status wait $pid [ $? = 0 ] || { echo "50.samba: smb.conf background update exited with status $?" rm -f "${tmpfile}" exit 1 } # put the new smb.conf contents in the cache (atomic rename) # make sure we remove references to the registry while doing # this to ensure that running testparm on the cache does # not use the registry egrep -v 'registry.shares.=|include.=' < "$tmpfile" > "${tmpfile}.2" rm -f "$tmpfile" mv -f "${tmpfile}.2" "$smbconf_cache" || { echo "50.samba: failed to update background cache" rm -f "${tmpfile}.2" exit 1 } exit 0 } # keep waiting for testparm to finish sleep 1 done # it took more than 10 seconds - kill it off rm -f "${tmpfile}" /bin/kill -9 "$pid" > /dev/null 2>&1 echo "50.samba: timed out updating smbconf cache in background" exit 1 ) & } ################################################## # show the testparm output using a cached smb.conf # to avoid registry access testparm_cat() { [ -f $smbconf_cache ] || { testparm_foreground_update } testparm -s "$smbconf_cache" "$@" 2>/dev/null } # function to see if ctdb manages winbind check_ctdb_manages_winbind() { [ -z "$CTDB_MANAGES_WINBIND" ] && { secmode=`testparm_cat --parameter-name=security` case $secmode in ADS|DOMAIN) CTDB_MANAGES_WINBIND="yes"; ;; *) CTDB_MANAGES_WINBIND="no"; ;; esac } } list_samba_shares () { testparm_cat | sed -n -e 's@^[[:space:]]*path[[:space:]]*=[[:space:]]@@p' | sed -e 's/"//g' } ########################### # periodic cleanup function periodic_cleanup() { # running smbstatus scrubs any dead entries from the connections # and sessionid database # echo "Running periodic cleanup of samba databases" smbstatus -np > /dev/null 2>&1 & } case "$1" in startup) ctdb_service_start ;; shutdown) ctdb_service_stop ;; monitor) # Create a dummy file to track when we need to do periodic cleanup # of samba databases [ -f $CTDB_BASE/state/samba/periodic_cleanup ] || { touch $CTDB_BASE/state/samba/periodic_cleanup } [ `/usr/bin/find $CTDB_BASE/state/samba/periodic_cleanup -mmin +$SAMBA_CLEANUP_PERIOD | wc -l` -eq 1 ] && { # Cleanup the databases periodic_cleanup touch $CTDB_BASE/state/samba/periodic_cleanup } [ "$CTDB_MANAGES_SAMBA" = "yes" ] && { [ "$CTDB_SAMBA_SKIP_SHARE_CHECK" = "yes" ] || { testparm_background_update testparm_cat | egrep '^WARNING|^ERROR|^Unknown' && { testparm_foreground_update testparm_cat | egrep '^WARNING|^ERROR|^Unknown' && { echo "ERROR: testparm shows smb.conf is not clean" exit 1 } } list_samba_shares | ctdb_check_directories_probe || { testparm_foreground_update list_samba_shares | ctdb_check_directories } || exit $? } smb_ports="$CTDB_SAMBA_CHECK_PORTS" [ -z "$smb_ports" ] && { smb_ports=`testparm_cat --parameter-name="smb ports"` } ctdb_check_tcp_ports $smb_ports || exit $? } # check winbind is OK check_ctdb_manages_winbind [ "$CTDB_MANAGES_WINBIND" = "yes" ] && { ctdb_check_command "winbind" "wbinfo -p" } ;; *) ctdb_standard_event_handler "$@" ;; esac exit 0