1#!@PERL_PATH@ 2 3# Copyright (c) 2000, 2017, Oracle and/or its affiliates. All rights reserved. 4# 5# This program is free software; you can redistribute it and/or modify 6# it under the terms of the GNU General Public License, version 2.0, 7# as published by the Free Software Foundation. 8# 9# This program is also distributed with certain software (including 10# but not limited to OpenSSL) that is licensed under separate terms, 11# as designated in a particular file or component or in included license 12# documentation. The authors of MySQL hereby grant you an additional 13# permission to link the program and your derivative works with the 14# separately licensed software that they have included with MySQL. 15# 16# This program is distributed in the hope that it will be useful, 17# but WITHOUT ANY WARRANTY; without even the implied warranty of 18# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 19# GNU General Public License, version 2.0, for more details. 20# 21# You should have received a copy of the GNU Library General Public 22# License along with this library; if not, write to the Free 23# Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, 24# MA 02110-1301, USA 25 26use Getopt::Long; 27use POSIX qw(strftime getcwd); 28use File::Path qw(mkpath); 29 30$|=1; 31$VER="2.16"; 32 33my @defaults_options; # Leading --no-defaults, --defaults-file, etc. 34 35$opt_example = 0; 36$opt_help = 0; 37$opt_log = undef(); 38$opt_mysqladmin = "@bindir@/mysqladmin"; 39$opt_mysqld = "@libexecdir@/mysqld"; 40$opt_no_log = 0; 41$opt_password = undef(); 42$opt_tcp_ip = 0; 43$opt_user = "root"; 44$opt_version = 0; 45$opt_silent = 0; 46$opt_verbose = 0; 47 48my $my_print_defaults_exists= 1; 49my $logdir= undef(); 50 51my ($mysqld, $mysqladmin, $groupids, $homedir, $my_progname); 52 53$homedir = $ENV{HOME}; 54$my_progname = $0; 55$my_progname =~ s/.*[\/]//; 56 57 58if (defined($ENV{UMASK})) { 59 my $UMASK = $ENV{UMASK}; 60 my $m; 61 my $fmode = "0640"; 62 63 if(($UMASK =~ m/[^0246]/) || ($UMASK =~ m/^[^0]/) || (length($UMASK) != 4)) { 64 printf("UMASK must be a 3-digit mode with an additional leading 0 to indicate octal.\n"); 65 printf("The first digit will be corrected to 6, the others may be 0, 2, 4, or 6.\n"); } 66 else { 67 $fmode= substr $UMASK, 2, 2; 68 $fmode= "06${fmode}"; } 69 70 if($fmode != $UMASK) { 71 printf("UMASK corrected from $UMASK to $fmode ...\n"); } 72 73 $fmode= oct($fmode); 74 75 umask($fmode); 76} 77 78 79main(); 80 81#### 82#### main sub routine 83#### 84 85sub main 86{ 87 my $flag_exit= 0; 88 89 if (!defined(my_which(my_print_defaults))) 90 { 91 # We can't throw out yet, since --version, --help, or --example may 92 # have been given 93 print "WARNING: my_print_defaults command not found.\n"; 94 print "Please make sure you have this command available and\n"; 95 print "in your path. The command is available from the latest\n"; 96 print "MySQL distribution.\n"; 97 $my_print_defaults_exists= 0; 98 } 99 100 # Remove leading defaults options from @ARGV 101 while (@ARGV > 0) 102 { 103 last unless $ARGV[0] =~ 104 /^--(?:no-defaults$|(?:defaults-file|defaults-extra-file)=)/; 105 push @defaults_options, (shift @ARGV); 106 } 107 108 foreach (@defaults_options) 109 { 110 $_ = quote_shell_word($_); 111 } 112 113 # Add [mysqld_multi] options to front of @ARGV, ready for GetOptions() 114 unshift @ARGV, defaults_for_group('mysqld_multi'); 115 116 # We've already handled --no-defaults, --defaults-file, etc. 117 if (!GetOptions("help", "example", "version", "mysqld=s", "mysqladmin=s", 118 "user=s", "password=s", "log=s", "no-log", 119 "tcp-ip", "silent", "verbose")) 120 { 121 $flag_exit= 1; 122 } 123 usage() if ($opt_help); 124 125 if ($opt_verbose && $opt_silent) 126 { 127 print "Both --verbose and --silent have been given. Some of the warnings "; 128 print "will be disabled\nand some will be enabled.\n\n"; 129 } 130 131 init_log() if (!defined($opt_log)); 132 $groupids = $ARGV[1]; 133 if ($opt_version) 134 { 135 print "$my_progname version $VER by Jani Tolonen\n"; 136 exit(0); 137 } 138 example() if ($opt_example); 139 if ($flag_exit) 140 { 141 print "Error with an option, see $my_progname --help for more info.\n"; 142 exit(1); 143 } 144 if (!defined(my_which(my_print_defaults))) 145 { 146 print "ABORT: Can't find command 'my_print_defaults'.\n"; 147 print "This command is available from the latest MySQL\n"; 148 print "distribution. Please make sure you have the command\n"; 149 print "in your PATH.\n"; 150 exit(1); 151 } 152 usage() if (!defined($ARGV[0]) || 153 (!($ARGV[0] =~ m/^start$/i) && 154 !($ARGV[0] =~ m/^stop$/i) && 155 !($ARGV[0] =~ m/^reload$/i) && 156 !($ARGV[0] =~ m/^report$/i))); 157 158 if (!$opt_no_log) 159 { 160 w2log("$my_progname log file version $VER; run: ", 161 "$opt_log", 1, 0); 162 } 163 else 164 { 165 print "$my_progname log file version $VER; run: "; 166 print strftime "%a %b %e %H:%M:%S %Y", localtime; 167 print "\n"; 168 } 169 if (($ARGV[0] =~ m/^start$/i) || ($ARGV[0] =~ m/^reload$/i)) 170 { 171 if (!defined(($mysqld= my_which($opt_mysqld))) && $opt_verbose) 172 { 173 print "WARNING: Couldn't find the default mysqld binary.\n"; 174 print "Tried: $opt_mysqld\n"; 175 print "This is OK, if you are using option \"mysqld=...\" in "; 176 print "groups [mysqldN] separately for each.\n\n"; 177 } 178 if ($ARGV[0] =~ m/^start$/i) { 179 start_mysqlds(); 180 } elsif ($ARGV[0] =~ m/^reload$/i) { 181 reload_mysqlds(); 182 } 183 } 184 else 185 { 186 if (!defined(($mysqladmin= my_which($opt_mysqladmin))) && $opt_verbose) 187 { 188 print "WARNING: Couldn't find the default mysqladmin binary.\n"; 189 print "Tried: $opt_mysqladmin\n"; 190 print "This is OK, if you are using option \"mysqladmin=...\" in "; 191 print "groups [mysqldN] separately for each.\n\n"; 192 } 193 if ($ARGV[0] =~ m/^report$/i) 194 { 195 report_mysqlds(); 196 } 197 else 198 { 199 stop_mysqlds(); 200 } 201 } 202} 203 204# 205# Quote word for shell 206# 207 208sub quote_shell_word 209{ 210 my ($option)= @_; 211 212 $option =~ s!([^\w=./-])!\\$1!g; 213 return $option; 214} 215 216sub defaults_for_group 217{ 218 my ($group) = @_; 219 220 return () unless $my_print_defaults_exists; 221 222 my $com= join ' ', 'my_print_defaults', @defaults_options, $group; 223 my @defaults = `$com`; 224 chomp @defaults; 225 return @defaults; 226} 227 228#### 229#### Init log file. Check for appropriate place for log file, in the following 230#### order: my_print_defaults mysqld datadir, @datadir@ 231#### 232 233sub init_log 234{ 235 foreach my $opt (defaults_for_group('mysqld')) 236 { 237 if ($opt =~ m/^--datadir=(.*)/ && -d "$1" && -w "$1") 238 { 239 $logdir= $1; 240 } 241 } 242 if (!defined($logdir)) 243 { 244 $logdir= "@datadir@" if (-d "@datadir@" && -w "@datadir@"); 245 } 246 if (!defined($logdir)) 247 { 248 # Log file was not specified and we could not log to a standard place, 249 # so log file be disabled for now. 250 if (!$opt_silent) 251 { 252 print "WARNING: Log file disabled. Maybe directory or file isn't writable?\n"; 253 } 254 $opt_no_log= 1; 255 } 256 else 257 { 258 $opt_log= "$logdir/mysqld_multi.log"; 259 } 260} 261 262#### 263#### Report living and not running MySQL servers 264#### 265 266sub report_mysqlds 267{ 268 my (@groups, $com, $i, @options, $pec); 269 270 print "Reporting MySQL (Percona Server) servers\n"; 271 if (!$opt_no_log) 272 { 273 w2log("\nReporting MySQL (Percona Server) servers","$opt_log",0,0); 274 } 275 @groups = &find_groups($groupids); 276 for ($i = 0; defined($groups[$i]); $i++) 277 { 278 $com= get_mysqladmin_options($i, @groups); 279 $com.= " ping >> /dev/null 2>&1"; 280 system($com); 281 $pec = $? >> 8; 282 if ($pec) 283 { 284 print "MySQL (Percona Server) from group: $groups[$i] is not running\n"; 285 if (!$opt_no_log) 286 { 287 w2log("MySQL (Percona Server) from group: $groups[$i] is not running", 288 "$opt_log", 0, 0); 289 } 290 } 291 else 292 { 293 print "MySQL (Percona Server) from group: $groups[$i] is running\n"; 294 if (!$opt_no_log) 295 { 296 w2log("MySQL (Percona Server) from group: $groups[$i] is running", 297 "$opt_log", 0, 0); 298 } 299 } 300 } 301 if (!$i) 302 { 303 print "No groups to be reported (check your GNRs)\n"; 304 if (!$opt_no_log) 305 { 306 w2log("No groups to be reported (check your GNRs)", "$opt_log", 0, 0); 307 } 308 } 309} 310 311#### 312#### start multiple servers 313#### 314 315sub start_mysqlds() 316{ 317 my (@groups, $com, $tmp, $i, @options, $j, $mysqld_found, $info_sent); 318 319 if (!$opt_no_log) 320 { 321 w2log("\nStarting MySQL (Percona Server) servers\n","$opt_log",0,0); 322 } 323 else 324 { 325 print "\nStarting MySQL (Percona Server) servers\n"; 326 } 327 @groups = &find_groups($groupids); 328 for ($i = 0; defined($groups[$i]); $i++) 329 { 330 @options = defaults_for_group($groups[$i]); 331 332 $basedir_found= 0; # The default 333 $mysqld_found= 1; # The default 334 $mysqld_found= 0 if (!length($mysqld)); 335 $com= "$mysqld"; 336 for ($j = 0, $tmp= ""; defined($options[$j]); $j++) 337 { 338 if ("--datadir=" eq substr($options[$j], 0, 10)) { 339 $datadir = $options[$j]; 340 $datadir =~ s/\-\-datadir\=//; 341 eval { mkpath($datadir) }; 342 if ($@) { 343 print "FATAL ERROR: Cannot create data directory $datadir: $!\n"; 344 exit(1); 345 } 346 if (! -d $datadir."/mysql") { 347 if (-w $datadir) { 348 print "\n\nInstalling new database in $datadir\n\n"; 349 $install_cmd="@bindir@/mysql_install_db "; 350 $install_cmd.="--user=mysql "; 351 $install_cmd.="--datadir=$datadir"; 352 system($install_cmd); 353 } else { 354 print "\n"; 355 print "FATAL ERROR: Tried to create mysqld under group [$groups[$i]],\n"; 356 print "but the data directory is not writable.\n"; 357 print "data directory used: $datadir\n"; 358 exit(1); 359 } 360 } 361 362 if (! -d $datadir."/mysql") { 363 print "\n"; 364 print "FATAL ERROR: Tried to start mysqld under group [$groups[$i]],\n"; 365 print "but no data directory was found or could be created.\n"; 366 print "data directory used: $datadir\n"; 367 exit(1); 368 } 369 } 370 371 if ("--mysqladmin=" eq substr($options[$j], 0, 13)) 372 { 373 # catch this and ignore 374 } 375 elsif ("--mysqld=" eq substr($options[$j], 0, 9)) 376 { 377 $options[$j]=~ s/\-\-mysqld\=//; 378 $com= $options[$j]; 379 $mysqld_found= 1; 380 } 381 elsif ("--basedir=" eq substr($options[$j], 0, 10)) 382 { 383 $basedir= $options[$j]; 384 $basedir =~ s/^--basedir=//; 385 $basedir_found= 1; 386 $options[$j]= quote_shell_word($options[$j]); 387 $tmp.= " $options[$j]"; 388 } 389 else 390 { 391 $options[$j]= quote_shell_word($options[$j]); 392 $tmp.= " $options[$j]"; 393 } 394 } 395 if ($opt_verbose && $com =~ m/\/(safe_mysqld|mysqld_safe)$/ && !$info_sent) 396 { 397 print "WARNING: $1 is being used to start mysqld. In this case you "; 398 print "may need to pass\n\"ledir=...\" under groups [mysqldN] to "; 399 print "$1 in order to find the actual mysqld binary.\n"; 400 print "ledir (library executable directory) should be the path to the "; 401 print "wanted mysqld binary.\n\n"; 402 $info_sent= 1; 403 } 404 $com.= $tmp; 405 $com.= " >> $opt_log 2>&1" if (!$opt_no_log); 406 $com.= " &"; 407 if (!$mysqld_found) 408 { 409 print "\n"; 410 print "FATAL ERROR: Tried to start mysqld under group [$groups[$i]], "; 411 print "but no mysqld binary was found.\n"; 412 print "Please add \"mysqld=...\" in group [mysqld_multi], or add it to "; 413 print "group [$groups[$i]] separately.\n"; 414 exit(1); 415 } 416 if ($basedir_found) 417 { 418 $curdir=getcwd(); 419 chdir($basedir) or die "Can't change to datadir $basedir"; 420 } 421 system($com); 422 if ($basedir_found) 423 { 424 chdir($curdir) or die "Can't change back to original dir $curdir"; 425 } 426 } 427 if (!$i && !$opt_no_log) 428 { 429 w2log("No MySQL (Percona Server) servers to be started (check your GNRs)", 430 "$opt_log", 0, 0); 431 } 432} 433 434#### 435#### reload multiple servers 436#### 437 438sub reload_mysqlds() 439{ 440 my (@groups, $com, $tmp, $i, @options, $j); 441 442 if (!$opt_no_log) 443 { 444 w2log("\nReloading MySQL servers\n","$opt_log",0,0); 445 } 446 else 447 { 448 print "\nReloading MySQL servers\n"; 449 } 450 @groups = &find_groups($groupids); 451 for ($i = 0; defined($groups[$i]); $i++) 452 { 453 $mysqld_server = $mysqld; 454 @options = defaults_for_group($groups[$i]); 455 456 for ($j = 0, $tmp= ""; defined($options[$j]); $j++) 457 { 458 if ("--mysqladmin=" eq substr($options[$j], 0, 13)) 459 { 460 # catch this and ignore 461 } 462 elsif ("--mysqld=" eq substr($options[$j], 0, 9)) 463 { 464 $options[$j] =~ s/\-\-mysqld\=//; 465 $mysqld_server = $options[$j]; 466 } 467 elsif ("--pid-file=" eq substr($options[$j], 0, 11)) 468 { 469 $options[$j] =~ s/\-\-pid-file\=//; 470 $pid_file = $options[$j]; 471 } 472 } 473 $com = "killproc -p $pid_file -HUP $mysqld_server"; 474 system($com); 475 476 $com = "touch $pid_file"; 477 system($com); 478 } 479 if (!$i && !$opt_no_log) 480 { 481 w2log("No MySQL servers to be reloaded (check your GNRs)", 482 "$opt_log", 0, 0); 483 } 484} 485 486### 487#### stop multiple servers 488#### 489 490sub stop_mysqlds() 491{ 492 my (@groups, $com, $i, @options); 493 494 if (!$opt_no_log) 495 { 496 w2log("\nStopping MySQL (Percona Server) servers\n","$opt_log",0,0); 497 } 498 else 499 { 500 print "\nStopping MySQL (Percona Server) servers\n"; 501 } 502 @groups = &find_groups($groupids); 503 for ($i = 0; defined($groups[$i]); $i++) 504 { 505 $com= get_mysqladmin_options($i, @groups); 506 $com.= " shutdown"; 507 $com.= " >> $opt_log 2>&1" if (!$opt_no_log); 508 $com.= " &"; 509 system($com); 510 } 511 if (!$i && !$opt_no_log) 512 { 513 w2log("No MySQL (Percona Server) servers to be stopped (check your GNRs)", 514 "$opt_log", 0, 0); 515 } 516} 517 518#### 519#### Sub function for mysqladmin option parsing 520#### 521 522sub get_mysqladmin_options 523{ 524 my ($i, @groups)= @_; 525 my ($mysqladmin_found, $com, $tmp, $j); 526 527 @options = defaults_for_group($groups[$i]); 528 529 $mysqladmin_found= 1; # The default 530 $mysqladmin_found= 0 if (!length($mysqladmin)); 531 $com = "$mysqladmin"; 532 $tmp = " -u $opt_user"; 533 if (defined($opt_password)) { 534 my $pw= $opt_password; 535 # Protect single quotes in password 536 $pw =~ s/'/'"'"'/g; 537 $tmp.= " -p'$pw'"; 538 } 539 $tmp.= $opt_tcp_ip ? " -h 127.0.0.1" : ""; 540 for ($j = 0; defined($options[$j]); $j++) 541 { 542 if ("--mysqladmin=" eq substr($options[$j], 0, 13)) 543 { 544 $options[$j]=~ s/\-\-mysqladmin\=//; 545 $com= $options[$j]; 546 $mysqladmin_found= 1; 547 } 548 elsif ((($options[$j] =~ m/^(\-\-socket\=)(.*)$/) && !$opt_tcp_ip) || 549 ($options[$j] =~ m/^(\-\-port\=)(.*)$/)) 550 { 551 $tmp.= " $options[$j]"; 552 } 553 } 554 if (!$mysqladmin_found) 555 { 556 print "\n"; 557 print "FATAL ERROR: Tried to use mysqladmin in group [$groups[$i]], "; 558 print "but no mysqladmin binary was found.\n"; 559 print "Please add \"mysqladmin=...\" in group [mysqld_multi], or "; 560 print "in group [$groups[$i]].\n"; 561 exit(1); 562 } 563 $com.= $tmp; 564 return $com; 565} 566 567# Return a list of option files which can be opened. Similar, but not 568# identical, to behavior of my_search_option_files() 569sub list_defaults_files 570{ 571 my %opt; 572 foreach (@defaults_options) 573 { 574 return () if /^--no-defaults$/; 575 $opt{$1} = $2 if /^--defaults-(extra-file|file)=(.*)$/; 576 } 577 578 return ($opt{file}) if exists $opt{file}; 579 580 my %seen; # Don't list the same file more than once 581 return grep { defined $_ and not $seen{$_}++ and -f $_ and -r $_ } 582 ('/etc/my.cnf', 583 '/etc/mysql/my.cnf', 584 '@sysconfdir@/my.cnf', 585 ($ENV{MYSQL_HOME} ? "$ENV{MYSQL_HOME}/my.cnf" : undef), 586 $opt{'extra-file'}, 587 ($ENV{HOME} ? "$ENV{HOME}/.my.cnf" : undef)); 588} 589 590 591# Takes a specification of GNRs (see --help), and returns a list of matching 592# groups which actually are mentioned in a relevant config file 593sub find_groups 594{ 595 my ($raw_gids) = @_; 596 597 my %gids; 598 my @groups; 599 600 if (defined($raw_gids)) 601 { 602 # Make a hash of the wanted group ids 603 foreach my $raw_gid (split ',', $raw_gids) 604 { 605 # Match 123 or 123-456 606 my ($start, $end) = ($raw_gid =~ /^\s*(\d+)(?:\s*-\s*(\d+))?\s*$/); 607 $end = $start if not defined $end; 608 if (not defined $start or $end < $start or $start < 0) 609 { 610 print "ABORT: Bad GNR: $raw_gid; see $my_progname --help\n"; 611 exit(1); 612 } 613 614 foreach my $i ($start .. $end) 615 { 616 # Use $i + 0 to normalize numbers (002 + 0 -> 2) 617 $gids{$i + 0}= 1; 618 } 619 } 620 } 621 622 my @defaults_files = list_defaults_files(); 623 #warn "@{[sort keys %gids]} -> @defaults_files\n"; 624 foreach my $file (@defaults_files) 625 { 626 next unless open CONF, "< $file"; 627 628 while (<CONF>) 629 { 630 if (/^\s*\[\s*(mysqld)(\d+)\s*\]\s*$/) 631 { 632 #warn "Found a group: $1$2\n"; 633 # Use $2 + 0 to normalize numbers (002 + 0 -> 2) 634 if (not defined($raw_gids) or $gids{$2 + 0}) 635 { 636 push @groups, "$1$2"; 637 } 638 } 639 } 640 641 close CONF; 642 } 643 return @groups; 644} 645 646#### 647#### w2log: Write to a logfile. 648#### 1.arg: append to the log file (given string, or from a file. if a file, 649#### file will be read from $opt_logdir) 650#### 2.arg: logfile -name (w2log assumes that the logfile is in $opt_logdir). 651#### 3.arg. 0 | 1, if true, print current date to the logfile. 3. arg will 652#### be ignored, if 1. arg is a file. 653#### 4.arg. 0 | 1, if true, first argument is a file, else a string 654#### 655 656sub w2log 657{ 658 my ($msg, $file, $date_flag, $is_file)= @_; 659 my (@data); 660 661 open (LOGFILE, ">>$opt_log") 662 or die "FATAL: w2log: Couldn't open log file: $opt_log\n"; 663 664 if ($is_file) 665 { 666 open (FROMFILE, "<$msg") && (@data=<FROMFILE>) && 667 close(FROMFILE) 668 or die "FATAL: w2log: Couldn't open file: $msg\n"; 669 foreach my $line (@data) 670 { 671 print LOGFILE "$line"; 672 } 673 } 674 else 675 { 676 print LOGFILE "$msg"; 677 print LOGFILE strftime "%a %b %e %H:%M:%S %Y", localtime if ($date_flag); 678 print LOGFILE "\n"; 679 } 680 close (LOGFILE); 681 return; 682} 683 684#### 685#### my_which is used, because we can't assume that every system has the 686#### which -command. my_which can take only one argument at a time. 687#### Return values: requested system command with the first found path, 688#### or undefined, if not found. 689#### 690 691sub my_which 692{ 693 my ($command) = @_; 694 my (@paths, $path); 695 696 # If the argument is not 'my_print_defaults' then it would be of the format 697 # <absolute_path>/<program> 698 return $command if ($command ne 'my_print_defaults' && -f $command && 699 -x $command); 700 701 @paths = split(':', $ENV{'PATH'}); 702 foreach $path (@paths) 703 { 704 $path .= "/$command"; 705 return $path if (-f $path && -x $path); 706 } 707 return undef(); 708} 709 710 711#### 712#### example 713#### 714 715sub example 716{ 717 print <<EOF; 718# This is an example of a my.cnf file for $my_progname. 719# Usually this file is located in home dir ~/.my.cnf or /etc/my.cnf 720# 721# SOME IMPORTANT NOTES FOLLOW: 722# 723# 1.COMMON USER 724# 725# Make sure that the MySQL user, who is stopping the mysqld services, has 726# the same password to all MySQL servers being accessed by $my_progname. 727# This user needs to have the 'Shutdown_priv' -privilege, but for security 728# reasons should have no other privileges. It is advised that you create a 729# common 'multi_admin' user for all MySQL servers being controlled by 730# $my_progname. Here is an example how to do it: 731# 732# GRANT SHUTDOWN ON *.* TO multi_admin\@localhost IDENTIFIED BY 'password' 733# 734# You will need to apply the above to all MySQL servers that are being 735# controlled by $my_progname. 'multi_admin' will shutdown the servers 736# using 'mysqladmin' -binary, when '$my_progname stop' is being called. 737# 738# 2.PID-FILE 739# 740# If you are using mysqld_safe to start mysqld, make sure that every 741# MySQL server has a separate pid-file. In order to use mysqld_safe 742# via $my_progname, you need to use two options: 743# 744# mysqld=/path/to/mysqld_safe 745# ledir=/path/to/mysqld-binary/ 746# 747# ledir (library executable directory), is an option that only mysqld_safe 748# accepts, so you will get an error if you try to pass it to mysqld directly. 749# For this reason you might want to use the above options within [mysqld#] 750# group directly. 751# 752# 3.DATA DIRECTORY 753# 754# It is NOT advised to run many MySQL servers within the same data directory. 755# You can do so, but please make sure to understand and deal with the 756# underlying caveats. In short they are: 757# - Speed penalty 758# - Risk of table/data corruption 759# - Data synchronising problems between the running servers 760# - Heavily media (disk) bound 761# - Relies on the system (external) file locking 762# - Is not applicable with all table types. (Such as InnoDB) 763# Trying so will end up with undesirable results. 764# 765# 4.TCP/IP Port 766# 767# Every server requires one and it must be unique. 768# 769# 5.[mysqld#] Groups 770# 771# In the example below the first and the fifth mysqld group was 772# intentionally left out. You may have 'gaps' in the config file. This 773# gives you more flexibility. 774# 775# 6.MySQL Server User 776# 777# You can pass the user=... option inside [mysqld#] groups. This 778# can be very handy in some cases, but then you need to run $my_progname 779# as UNIX root. 780# 781# 7.A Start-up Manage Script for $my_progname 782# 783# In the recent MySQL distributions you can find a file called 784# mysqld_multi.server.sh. It is a wrapper for $my_progname. This can 785# be used to start and stop multiple servers during boot and shutdown. 786# 787# You can place the file in /etc/init.d/mysqld_multi.server.sh and 788# make the needed symbolic links to it from various run levels 789# (as per Linux/Unix standard). You may even replace the 790# /etc/init.d/mysql.server script with it. 791# 792# Before using, you must create a my.cnf file either in @sysconfdir@/my.cnf 793# or /root/.my.cnf and add the [mysqld_multi] and [mysqld#] groups. 794# 795# The script can be found from support-files/mysqld_multi.server.sh 796# in MySQL distribution. (Verify the script before using) 797# 798 799[mysqld_multi] 800mysqld = @bindir@/mysqld_safe 801mysqladmin = @bindir@/mysqladmin 802user = multi_admin 803password = my_password 804 805[mysqld2] 806socket = /tmp/mysql.sock2 807port = 3307 808pid-file = @localstatedir@2/hostname.pid2 809datadir = @localstatedir@2 810language = @datadir@/mysql/english 811user = unix_user1 812 813[mysqld3] 814mysqld = /path/to/mysqld_safe 815ledir = /path/to/mysqld-binary/ 816mysqladmin = /path/to/mysqladmin 817socket = /tmp/mysql.sock3 818port = 3308 819pid-file = @localstatedir@3/hostname.pid3 820datadir = @localstatedir@3 821language = @datadir@/mysql/swedish 822user = unix_user2 823 824[mysqld4] 825socket = /tmp/mysql.sock4 826port = 3309 827pid-file = @localstatedir@4/hostname.pid4 828datadir = @localstatedir@4 829language = @datadir@/mysql/estonia 830user = unix_user3 831 832[mysqld6] 833socket = /tmp/mysql.sock6 834port = 3311 835pid-file = @localstatedir@6/hostname.pid6 836datadir = @localstatedir@6 837language = @datadir@/mysql/japanese 838user = unix_user4 839EOF 840 exit(0); 841} 842 843#### 844#### usage 845#### 846 847sub usage 848{ 849 print <<EOF; 850$my_progname version $VER by Jani Tolonen 851 852Description: 853$my_progname can be used to start, reload, or stop any number of separate 854mysqld processes running in different TCP/IP ports and UNIX sockets. 855 856$my_progname can read group [mysqld_multi] from my.cnf file. You may 857want to put options mysqld=... and mysqladmin=... there. Since 858version 2.10 these options can also be given under groups [mysqld#], 859which gives more control over different versions. One can have the 860default mysqld and mysqladmin under group [mysqld_multi], but this is 861not mandatory. Please note that if mysqld or mysqladmin is missing 862from both [mysqld_multi] and [mysqld#], a group that is tried to be 863used, $my_progname will abort with an error. 864 865$my_progname will search for groups named [mysqld#] from my.cnf (or 866the given --defaults-extra-file=...), where '#' can be any positive 867integer starting from 1. These groups should be the same as the regular 868[mysqld] group, but with those port, socket and any other options 869that are to be used with each separate mysqld process. The number 870in the group name has another function; it can be used for starting, 871reloading, stopping, or reporting any specific mysqld server. 872 873Usage: $my_progname [OPTIONS] {start|reload|stop|report} [GNR,GNR,GNR...] 874or $my_progname [OPTIONS] {start|reload|stop|report} [GNR-GNR,GNR,GNR-GNR,...] 875 876The GNR means the group number. You can start, reload, stop or report any GNR, 877or several of them at the same time. (See --example) The GNRs list can 878be comma separated or a dash combined. The latter means that all the 879GNRs between GNR1-GNR2 will be affected. Without GNR argument all the 880groups found will either be started, reloaded, stopped, or reported. Note that 881syntax for specifying GNRs must appear without spaces. 882 883Options: 884 885These options must be given before any others: 886--no-defaults Do not read any defaults file 887--defaults-file=... Read only this configuration file, do not read the 888 standard system-wide and user-specific files 889--defaults-extra-file=... Read this configuration file in addition to the 890 standard system-wide and user-specific files 891Using: @{[join ' ', @defaults_options]} 892 893--example Give an example of a config file with extra information. 894--help Print this help and exit. 895--log=... Log file. Full path to and the name for the log file. NOTE: 896 If the file exists, everything will be appended. 897 Using: $opt_log 898--mysqladmin=... mysqladmin binary to be used for a server shutdown. 899 Since version 2.10 this can be given within groups [mysqld#] 900 Using: $mysqladmin 901--mysqld=... mysqld binary to be used. Note that you can give mysqld_safe 902 to this option also. The options are passed to mysqld. Just 903 make sure you have mysqld in your PATH or fix mysqld_safe. 904 Using: $mysqld 905 Please note: Since mysqld_multi version 2.3 you can also 906 give this option inside groups [mysqld#] in ~/.my.cnf, 907 where '#' stands for an integer (number) of the group in 908 question. This will be recognised as a special option and 909 will not be passed to the mysqld. This will allow one to 910 start different mysqld versions with mysqld_multi. 911--no-log Print to stdout instead of the log file. By default the log 912 file is turned on. 913--password=... Password for mysqladmin user. 914--silent Disable warnings. 915--tcp-ip Connect to the MySQL server(s) via the TCP/IP port instead 916 of the UNIX socket. This affects stopping and reporting. 917 If a socket file is missing, the server may still be 918 running, but can be accessed only via the TCP/IP port. 919 By default connecting is done via the UNIX socket. 920--user=... mysqladmin user. Using: $opt_user 921--verbose Be more verbose. 922--version Print the version number and exit. 923EOF 924 exit(0); 925} 926