summaryrefslogtreecommitdiff
path: root/scripts/mysqld_safe.sh
diff options
context:
space:
mode:
Diffstat (limited to 'scripts/mysqld_safe.sh')
-rw-r--r--scripts/mysqld_safe.sh361
1 files changed, 256 insertions, 105 deletions
diff --git a/scripts/mysqld_safe.sh b/scripts/mysqld_safe.sh
index e6b015e7d16..99dcafbbf71 100644
--- a/scripts/mysqld_safe.sh
+++ b/scripts/mysqld_safe.sh
@@ -2,16 +2,28 @@
# Copyright Abandoned 1996 TCX DataKonsult AB & Monty Program KB & Detron HB
# This file is public domain and comes with NO WARRANTY of any kind
#
-# scripts to start the MySQL daemon and restart it if it dies unexpectedly
+# Script to start the MySQL daemon and restart it if it dies unexpectedly
#
# This should be executed in the MySQL base directory if you are using a
-# binary installation that has other paths than you are using.
+# binary installation that is not installed in its compile-time default
+# location
#
# mysql.server works by first doing a cd to the base directory and from there
# executing mysqld_safe
KILL_MYSQLD=1;
MYSQLD=
+niceness=0
+# Initial logging status: error log is not open, and not using syslog
+logging=init
+want_syslog=0
+syslog_tag=
+user=@MYSQLD_USER@
+pid_file=
+err_log=
+
+syslog_tag_mysqld=mysqld
+syslog_tag_mysqld_safe=mysqld_safe
trap '' 1 2 3 15 # we shouldn't let anyone kill us
@@ -31,7 +43,6 @@ Usage: $0 [OPTIONS]
--defaults-file=FILE Use the specified defaults file
--defaults-extra-file=FILE Also use defaults from the specified file
--ledir=DIRECTORY Look for mysqld in the specified directory
- --log-error=FILE Log errors to the specified log file
--open-files-limit=LIMIT Limit the number of open files
--core-file-size=LIMIT Limit core files to the specified size
--timezone=TZ Set the system timezone
@@ -39,6 +50,9 @@ Usage: $0 [OPTIONS]
--mysqld-version=VERSION Use "mysqld-VERSION" as mysqld
--nice=NICE Set the scheduling priority of mysqld
--skip-kill-mysqld Don't try to kill stray mysqld processes
+ --syslog Log messages to syslog with 'logger'
+ --skip-syslog Log messages to error log (default)
+ --syslog-tag=TAG Pass -t "mysqld-TAG" to 'logger'
All other options are passed to the mysqld program.
@@ -46,6 +60,84 @@ EOF
exit 1
}
+my_which ()
+{
+ save_ifs="${IFS-UNSET}"
+ IFS=:
+ for file
+ do
+ for dir in $PATH
+ do
+ if [ -f "$dir/$file" ]
+ then
+ echo "$dir/$file"
+ continue 2
+ fi
+ done
+ return 1 # Failure, didn't find file in path
+ done
+ if [ "$save_ifs" = UNSET ]
+ then
+ unset IFS
+ else
+ IFS="$save_ifs"
+ fi
+ return 0 # Success
+}
+
+log_generic () {
+ priority="$1"
+ shift
+
+ msg="`date +'%y%m%d %H:%M:%S'` mysqld_safe $*"
+ echo "$msg"
+ case $logging in
+ init) ;; # Just echo the message, don't save it anywhere
+ file) echo "$msg" >> "$err_log" ;;
+ syslog) logger -t "$syslog_tag_mysqld_safe" -p "$priority" "$*" ;;
+ *)
+ echo "Internal program error (non-fatal):" \
+ " unknown logging method '$logging'" >&2
+ ;;
+ esac
+}
+
+log_error () {
+ log_generic daemon.error "$@" >&2
+}
+
+log_notice () {
+ log_generic daemon.notice "$@"
+}
+
+eval_log_error () {
+ cmd="$1"
+ case $logging in
+ file) cmd="$cmd >> "`shell_quote_string "$err_log"`" 2>&1" ;;
+ syslog)
+ # mysqld often prefixes its messages with a timestamp, which is
+ # redundant when logging to syslog (which adds its own timestamp)
+ # However, we don't strip the timestamp with sed here, because
+ # sed buffers output (only GNU sed supports a -u (unbuffered) option)
+ # which means that messages may not get sent to syslog until the
+ # mysqld process quits.
+ cmd="$cmd 2>&1 | logger -t '$syslog_tag_mysqld' -p daemon.error"
+ ;;
+ *)
+ echo "Internal program error (non-fatal):" \
+ " unknown logging method '$logging'" >&2
+ ;;
+ esac
+
+ #echo "Running mysqld: [$cmd]"
+ eval "$cmd"
+}
+
+shell_quote_string() {
+ # This sed command makes sure that any special chars are quoted,
+ # so the arg gets passed exactly to the server.
+ echo "$1" | sed -e 's,\([^a-zA-Z0-9/_.=-]\),\\\1,g'
+}
parse_arguments() {
# We only need to pass arguments through to the server if we don't
@@ -59,47 +151,46 @@ parse_arguments() {
fi
for arg do
+ val=`echo "$arg" | sed -e "s;--[^=]*=;;"`
case "$arg" in
- --skip-kill-mysqld*)
- KILL_MYSQLD=0;
- ;;
# these get passed explicitly to mysqld
- --basedir=*) MY_BASEDIR_VERSION=`echo "$arg" | sed -e "s;--basedir=;;"` ;;
- --datadir=*) DATADIR=`echo "$arg" | sed -e "s;--datadir=;;"` ;;
- --pid-file=*) pid_file=`echo "$arg" | sed -e "s;--pid-file=;;"` ;;
- --user=*) user=`echo "$arg" | sed -e "s;--[^=]*=;;"` ; SET_USER=1 ;;
+ --basedir=*) MY_BASEDIR_VERSION="$val" ;;
+ --datadir=*) DATADIR="$val" ;;
+ --pid-file=*) pid_file="$val" ;;
+ --user=*) user="$val"; SET_USER=1 ;;
- # these two might have been set in a [mysqld_safe] section of my.cnf
+ # these might have been set in a [mysqld_safe] section of my.cnf
# they are added to mysqld command line to override settings from my.cnf
- --socket=*) mysql_unix_port=`echo "$arg" | sed -e "s;--socket=;;"` ;;
- --port=*) mysql_tcp_port=`echo "$arg" | sed -e "s;--port=;;"` ;;
+ --log-error=*) err_log="$val" ;;
+ --port=*) mysql_tcp_port="$val" ;;
+ --socket=*) mysql_unix_port="$val" ;;
# mysqld_safe-specific options - must be set in my.cnf ([mysqld_safe])!
- --ledir=*) ledir=`echo "$arg" | sed -e "s;--ledir=;;"` ;;
- --log-error=*) err_log=`echo "$arg" | sed -e "s;--log-error=;;"` ;;
- --open-files-limit=*) open_files=`echo "$arg" | sed -e "s;--open-files-limit=;;"` ;;
- --core-file-size=*) core_file_size=`echo "$arg" | sed -e "s;--core-file-size=;;"` ;;
- --timezone=*) TZ=`echo "$arg" | sed -e "s;--timezone=;;"` ; export TZ; ;;
- --mysqld=*) MYSQLD=`echo "$arg" | sed -e "s;--mysqld=;;"` ;;
+ --core-file-size=*) core_file_size="$val" ;;
+ --ledir=*) ledir="$val" ;;
+ --mysqld=*) MYSQLD="$val" ;;
--mysqld-version=*)
- tmp=`echo "$arg" | sed -e "s;--mysqld-version=;;"`
- if test -n "$tmp"
- then
- MYSQLD="mysqld-$tmp"
- else
- MYSQLD="mysqld"
- fi
- ;;
- --nice=*) niceness=`echo "$arg" | sed -e "s;--nice=;;"` ;;
- --help)
- usage
+ if test -n "$val"
+ then
+ MYSQLD="mysqld-$val"
+ else
+ MYSQLD="mysqld"
+ fi
;;
+ --nice=*) niceness="$val" ;;
+ --open-files-limit=*) open_files="$val" ;;
+ --skip-kill-mysqld*) KILL_MYSQLD=0 ;;
+ --syslog) want_syslog=1 ;;
+ --skip-syslog) want_syslog=0 ;;
+ --syslog-tag=*) syslog_tag="$val" ;;
+ --timezone=*) TZ="$val"; export TZ; ;;
+
+ --help) usage ;;
+
*)
if test -n "$pick_args"
then
- # This sed command makes sure that any special chars are quoted,
- # so the arg gets passed exactly to the server.
- args="$args "`echo "$arg" | sed -e 's,\([^a-zA-Z0-9_.-]\),\\\\\1,g'`
+ append_arg_to_args "$arg"
fi
;;
esac
@@ -118,8 +209,7 @@ then
MY_BASEDIR_VERSION=$MY_PWD # Where bin, share and data are
ledir=$MY_BASEDIR_VERSION/bin # Where mysqld is
# Check for the directories we would expect from a source install
-elif test -f ./share/mysql/english/errmsg.sys -a \
- -x ./libexec/mysqld
+elif test -f ./share/mysql/english/errmsg.sys -a -x ./libexec/mysqld
then
MY_BASEDIR_VERSION=$MY_PWD # Where libexec, share and var are
ledir=$MY_BASEDIR_VERSION/libexec # Where mysqld is
@@ -154,17 +244,17 @@ if test -z "$MYSQL_HOME"
then
if test -r "$MY_BASEDIR_VERSION/my.cnf" && test -r "$DATADIR/my.cnf"
then
- echo "WARNING: Found two instances of my.cnf -"
- echo "$MY_BASEDIR_VERSION/my.cnf and"
- echo "$DATADIR/my.cnf"
- echo "IGNORING $DATADIR/my.cnf"
- echo
+ log_error "WARNING: Found two instances of my.cnf -
+$MY_BASEDIR_VERSION/my.cnf and
+$DATADIR/my.cnf
+IGNORING $DATADIR/my.cnf"
+
MYSQL_HOME=$MY_BASEDIR_VERSION
elif test -r "$DATADIR/my.cnf"
then
- echo "WARNING: Found $DATADIR/my.cnf"
- echo "Datadir is deprecated place for my.cnf, please move it to $MY_BASEDIR_VERSION"
- echo
+ log_error "WARNING: Found $DATADIR/my.cnf
+The data directory is a deprecated location for my.cnf, please move it to
+$MY_BASEDIR_VERSION/my.cnf"
MYSQL_HOME=$DATADIR
else
MYSQL_HOME=$MY_BASEDIR_VERSION
@@ -172,12 +262,6 @@ then
fi
export MYSQL_HOME
-user=@MYSQLD_USER@
-niceness=0
-
-# these rely on $DATADIR by default, so we'll set them later on
-pid_file=
-err_log=
# Get first arguments from the my.cnf file, groups [mysqld] and [mysqld_safe]
# and then merge with the command line arguments
@@ -194,17 +278,103 @@ else
print_defaults="my_print_defaults"
fi
+append_arg_to_args () {
+ args="$args "`shell_quote_string "$1"`
+}
+
args=
+
SET_USER=2
parse_arguments `$print_defaults $defaults --loose-verbose mysqld server`
if test $SET_USER -eq 2
then
SET_USER=0
fi
+
parse_arguments `$print_defaults $defaults --loose-verbose mysqld_safe safe_mysqld`
parse_arguments PICK-ARGS-FROM-ARGV "$@"
-safe_mysql_unix_port=${mysql_unix_port:-${MYSQL_UNIX_PORT:-@MYSQL_UNIX_ADDR@}}
+# Determine what logging facility to use
+
+# Ensure that 'logger' exists, if it's requested
+if [ $want_syslog -eq 1 ]
+then
+ my_which logger > /dev/null 2>&1
+ if [ $? -ne 0 ]
+ then
+ log_error "--syslog requested, but no 'logger' program found. Please ensure that 'logger' is in your PATH, or do not specify the --syslog option to mysqld_safe."
+ exit 1
+ fi
+fi
+
+if [ -n "$err_log" -o $want_syslog -eq 0 ]
+then
+ if [ -n "$err_log" ]
+ then
+ # mysqld adds ".err" if there is no extension on the --log-error
+ # argument; must match that here, or mysqld_safe will write to a
+ # different log file than mysqld
+
+ # mysqld does not add ".err" to "--log-error=foo."; it considers a
+ # trailing "." as an extension
+ if expr "$err_log" : '.*\.[^/]*$' > /dev/null
+ then
+ :
+ else
+ err_log="$err_log".err
+ fi
+
+ case "$err_log" in
+ /* ) ;;
+ * ) err_log="$DATADIR/$err_log" ;;
+ esac
+ else
+ err_log=$DATADIR/`@HOSTNAME@`.err
+ fi
+
+ append_arg_to_args "--log-error=$err_log"
+
+ if [ $want_syslog -eq 1 ]
+ then
+ # User explicitly asked for syslog, so warn that it isn't used
+ log_error "Can't log to error log and syslog at the same time. Remove all --log-error configuration options for --syslog to take effect."
+ fi
+
+ # Log to err_log file
+ log_notice "Logging to '$err_log'."
+ logging=file
+else
+ if [ -n "$syslog_tag" ]
+ then
+ # Sanitize the syslog tag
+ syslog_tag=`echo "$syslog_tag" | sed -e 's/[^a-zA-Z0-9_-]/_/g'`
+ syslog_tag_mysqld_safe="${syslog_tag_mysqld_safe}-$syslog_tag"
+ syslog_tag_mysqld="${syslog_tag_mysqld}-$syslog_tag"
+ fi
+ log_notice "Logging to syslog."
+ logging=syslog
+fi
+
+USER_OPTION=""
+if test -w / -o "$USER" = "root"
+then
+ if test "$user" != "root" -o $SET_USER = 1
+ then
+ USER_OPTION="--user=$user"
+ fi
+ # Change the err log to the right user, if it is in use
+ if [ $want_syslog -eq 0 ]; then
+ touch $err_log
+ chown $user $err_log
+ fi
+ if test -n "$open_files"
+ then
+ ulimit -n $open_files
+ append_arg_to_args "--open-files-limit=$open_files"
+ fi
+fi
+
+safe_mysql_unix_port=${mysql_unix_port:-${MYSQL_UNIX_PORT:-@MYSQL_UNIX_ADDR@}}
# Make sure that directory for $safe_mysql_unix_port exists
mysql_unix_port_dir=`dirname $safe_mysql_unix_port`
if [ ! -d $mysql_unix_port_dir ]
@@ -214,25 +384,19 @@ then
chmod 755 $mysql_unix_port_dir
fi
-# Use the mysqld-max binary by default if the user doesn't specify a binary
+# If the user doesn't specify a binary, we assume name "mysqld"
if test -z "$MYSQLD"
then
- if test -x $ledir/mysqld-max
- then
- MYSQLD=mysqld-max
- else
- MYSQLD=mysqld
- fi
+ MYSQLD=mysqld
fi
if test ! -x $ledir/$MYSQLD
then
- echo "The file $ledir/$MYSQLD doesn't exist or is not executable"
- echo "Please do a cd to the mysql installation directory and restart"
- echo "this script from there as follows:"
- echo "./bin/mysqld_safe".
- echo "See http://dev.mysql.com/doc/mysql/en/mysqld-safe.html for more"
- echo "information"
+ log_error "The file $ledir/$MYSQLD
+does not exist or is not executable. Please cd to the mysql installation
+directory and restart this script from there as follows:
+./bin/mysqld_safe&
+See http://dev.mysql.com/doc/mysql/en/mysqld-safe.html for more information"
exit 1
fi
@@ -245,15 +409,15 @@ else
* ) pid_file="$DATADIR/$pid_file" ;;
esac
fi
-test -z "$err_log" && err_log=$DATADIR/`@HOSTNAME@`.err
+append_arg_to_args "--pid-file=$pid_file"
if test -n "$mysql_unix_port"
then
- args="--socket=$mysql_unix_port $args"
+ append_arg_to_args "--socket=$mysql_unix_port"
fi
if test -n "$mysql_tcp_port"
then
- args="--port=$mysql_tcp_port $args"
+ append_arg_to_args "--port=$mysql_tcp_port"
fi
if test $niceness -eq 0
@@ -271,7 +435,7 @@ fi
if nohup nice > /dev/null 2>&1
then
normal_niceness=`nice`
- nohup_niceness=`nohup nice`
+ nohup_niceness=`nohup nice 2>/dev/null`
numeric_nice_values=1
for val in $normal_niceness $nohup_niceness
@@ -308,22 +472,6 @@ else
fi
fi
-USER_OPTION=""
-if test -w / -o "$USER" = "root"
-then
- if test "$user" != "root" -o $SET_USER = 1
- then
- USER_OPTION="--user=$user"
- fi
- # If we are root, change the err log to the right user.
- touch $err_log; chown $user $err_log
- if test -n "$open_files"
- then
- ulimit -n $open_files
- args="--open-files-limit=$open_files $args"
- fi
-fi
-
# Try to set the core file size (even if we aren't root) because many systems
# don't specify a hard limit on core file size.
if test -n "$core_file_size"
@@ -341,18 +489,17 @@ then
then
if @FIND_PROC@
then # The pid contains a mysqld process
- echo "A mysqld process already exists"
- echo "A mysqld process already exists at " `date` >> $err_log
+ log_error "A mysqld process already exists"
exit 1
fi
fi
rm -f $pid_file
if test -f $pid_file
then
- echo "Fatal error: Can't remove the pid file: $pid_file"
- echo "Fatal error: Can't remove the pid file: $pid_file at " `date` >> $err_log
- echo "Please remove it manually and start $0 again"
- echo "mysqld daemon not started"
+ log_error "Fatal error: Can't remove the pid file:
+$pid_file
+Please remove it manually and start $0 again;
+mysqld daemon not started"
exit 1
fi
fi
@@ -369,27 +516,32 @@ fi
# $MY_BASEDIR_VERSION/bin/myisamchk --silent --force --fast --medium-check $DATADIR/*/*.MYI
# $MY_BASEDIR_VERSION/bin/isamchk --silent --force $DATADIR/*/*.ISM
-echo "Starting $MYSQLD daemon with databases from $DATADIR"
-
# Does this work on all systems?
#if type ulimit | grep "shell builtin" > /dev/null
#then
# ulimit -n 256 > /dev/null 2>&1 # Fix for BSD and FreeBSD systems
#fi
-echo "`date +'%y%m%d %H:%M:%S mysqld started'`" >> $err_log
+cmd="$NOHUP_NICENESS"
+
+for i in "$ledir/$MYSQLD" "$defaults" "--basedir=$MY_BASEDIR_VERSION" \
+ "--datadir=$DATADIR" "$USER_OPTION"
+do
+ cmd="$cmd "`shell_quote_string "$i"`
+done
+cmd="$cmd $args"
+# Avoid 'nohup: ignoring input' warning
+test -n "$NOHUP_NICENESS" && cmd="$cmd < /dev/null"
+
+log_notice "Starting $MYSQLD daemon with databases from $DATADIR"
while true
do
rm -f $safe_mysql_unix_port $pid_file # Some extra safety
- if test -z "$args"
- then
- $NOHUP_NICENESS $ledir/$MYSQLD $defaults --basedir=$MY_BASEDIR_VERSION --datadir=$DATADIR $USER_OPTION --pid-file=$pid_file @MYSQLD_DEFAULT_SWITCHES@ >> $err_log 2>&1
- else
- eval "$NOHUP_NICENESS $ledir/$MYSQLD $defaults --basedir=$MY_BASEDIR_VERSION --datadir=$DATADIR $USER_OPTION --pid-file=$pid_file @MYSQLD_DEFAULT_SWITCHES@ $args >> $err_log 2>&1"
- fi
+
+ eval_log_error "$cmd"
+
if test ! -f $pid_file # This is removed if normal shutdown
then
- echo "STOPPING server from pid file $pid_file"
break
fi
@@ -402,7 +554,7 @@ do
# kill -9 is used or the process won't react on the kill.
numofproces=`ps xaww | grep -v "grep" | grep "$ledir/$MYSQLD\>" | grep -c "pid-file=$pid_file"`
- echo -e "\nNumber of processes running now: $numofproces" | tee -a $err_log
+ log_notice "Number of processes running now: $numofproces"
I=1
while test "$I" -le "$numofproces"
do
@@ -415,16 +567,15 @@ do
# echo "TEST $I - $T **"
if kill -9 $T
then
- echo "$MYSQLD process hanging, pid $T - killed" | tee -a $err_log
- else
+ log_error "$MYSQLD process hanging, pid $T - killed"
+ else
break
fi
I=`expr $I + 1`
done
fi
- echo "`date +'%y%m%d %H:%M:%S'` mysqld restarted" | tee -a $err_log
+ log_notice "mysqld restarted"
done
-echo "`date +'%y%m%d %H:%M:%S'` mysqld ended" | tee -a $err_log
-echo "" | tee -a $err_log
+log_notice "mysqld from pid file $pid_file ended"