1#!@PERL_PATH@ 2 3# Copyright (c) 2000, 2021, Oracle and/or its affiliates. 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 servers\n"; 271 if (!$opt_no_log) 272 { 273 w2log("\nReporting MySQL 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 server from group: $groups[$i] is not running\n"; 285 if (!$opt_no_log) 286 { 287 w2log("MySQL server from group: $groups[$i] is not running", 288 "$opt_log", 0, 0); 289 } 290 } 291 else 292 { 293 print "MySQL server from group: $groups[$i] is running\n"; 294 if (!$opt_no_log) 295 { 296 w2log("MySQL 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 servers\n","$opt_log",0,0); 322 } 323 else 324 { 325 print "\nStarting MySQL 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@/mysqld "; 350 $install_cmd.="--initialize "; 351 $install_cmd.="--user=mysql "; 352 $install_cmd.="--datadir=$datadir"; 353 system($install_cmd); 354 } else { 355 print "\n"; 356 print "FATAL ERROR: Tried to create mysqld under group [$groups[$i]],\n"; 357 print "but the data directory is not writable.\n"; 358 print "data directory used: $datadir\n"; 359 exit(1); 360 } 361 } 362 363 if (! -d $datadir."/mysql") { 364 print "\n"; 365 print "FATAL ERROR: Tried to start mysqld under group [$groups[$i]],\n"; 366 print "but no data directory was found or could be created.\n"; 367 print "data directory used: $datadir\n"; 368 exit(1); 369 } 370 } 371 372 if ("--mysqladmin=" eq substr($options[$j], 0, 13)) 373 { 374 # catch this and ignore 375 } 376 elsif ("--mysqld=" eq substr($options[$j], 0, 9)) 377 { 378 $options[$j]=~ s/\-\-mysqld\=//; 379 $com= $options[$j]; 380 $mysqld_found= 1; 381 } 382 elsif ("--basedir=" eq substr($options[$j], 0, 10)) 383 { 384 $basedir= $options[$j]; 385 $basedir =~ s/^--basedir=//; 386 $basedir_found= 1; 387 $options[$j]= quote_shell_word($options[$j]); 388 $tmp.= " $options[$j]"; 389 } 390 else 391 { 392 $options[$j]= quote_shell_word($options[$j]); 393 $tmp.= " $options[$j]"; 394 } 395 } 396 if ($opt_verbose && $com =~ m/\/(safe_mysqld|mysqld_safe)$/ && !$info_sent) 397 { 398 print "WARNING: $1 is being used to start mysqld. In this case you "; 399 print "may need to pass\n\"ledir=...\" under groups [mysqldN] to "; 400 print "$1 in order to find the actual mysqld binary.\n"; 401 print "ledir (library executable directory) should be the path to the "; 402 print "wanted mysqld binary.\n\n"; 403 $info_sent= 1; 404 } 405 $com.= $tmp; 406 $com.= " >> $opt_log 2>&1" if (!$opt_no_log); 407 $com.= " &"; 408 if (!$mysqld_found) 409 { 410 print "\n"; 411 print "FATAL ERROR: Tried to start mysqld under group [$groups[$i]], "; 412 print "but no mysqld binary was found.\n"; 413 print "Please add \"mysqld=...\" in group [mysqld_multi], or add it to "; 414 print "group [$groups[$i]] separately.\n"; 415 exit(1); 416 } 417 if ($basedir_found) 418 { 419 $curdir=getcwd(); 420 chdir($basedir) or die "Can't change to datadir $basedir"; 421 } 422 system($com); 423 if ($basedir_found) 424 { 425 chdir($curdir) or die "Can't change back to original dir $curdir"; 426 } 427 } 428 if (!$i && !$opt_no_log) 429 { 430 w2log("No MySQL servers to be started (check your GNRs)", 431 "$opt_log", 0, 0); 432 } 433} 434 435#### 436#### reload multiple servers 437#### 438 439sub reload_mysqlds() 440{ 441 my (@groups, $com, $tmp, $i, @options, $j); 442 443 if (!$opt_no_log) 444 { 445 w2log("\nReloading MySQL servers\n","$opt_log",0,0); 446 } 447 else 448 { 449 print "\nReloading MySQL servers\n"; 450 } 451 @groups = &find_groups($groupids); 452 for ($i = 0; defined($groups[$i]); $i++) 453 { 454 $mysqld_server = $mysqld; 455 @options = defaults_for_group($groups[$i]); 456 457 for ($j = 0, $tmp= ""; defined($options[$j]); $j++) 458 { 459 if ("--mysqladmin=" eq substr($options[$j], 0, 13)) 460 { 461 # catch this and ignore 462 } 463 elsif ("--mysqld=" eq substr($options[$j], 0, 9)) 464 { 465 $options[$j] =~ s/\-\-mysqld\=//; 466 $mysqld_server = $options[$j]; 467 } 468 elsif ("--pid-file=" eq substr($options[$j], 0, 11)) 469 { 470 $options[$j] =~ s/\-\-pid-file\=//; 471 $pid_file = $options[$j]; 472 } 473 } 474 $com = "killproc -p $pid_file -HUP $mysqld_server"; 475 system($com); 476 477 $com = "touch $pid_file"; 478 system($com); 479 } 480 if (!$i && !$opt_no_log) 481 { 482 w2log("No MySQL servers to be reloaded (check your GNRs)", 483 "$opt_log", 0, 0); 484 } 485} 486 487### 488#### stop multiple servers 489#### 490 491sub stop_mysqlds() 492{ 493 my (@groups, $com, $i, @options); 494 495 if (!$opt_no_log) 496 { 497 w2log("\nStopping MySQL servers\n","$opt_log",0,0); 498 } 499 else 500 { 501 print "\nStopping MySQL servers\n"; 502 } 503 @groups = &find_groups($groupids); 504 for ($i = 0; defined($groups[$i]); $i++) 505 { 506 $com= get_mysqladmin_options($i, @groups); 507 $com.= " shutdown"; 508 $com.= " >> $opt_log 2>&1" if (!$opt_no_log); 509 $com.= " &"; 510 system($com); 511 } 512 if (!$i && !$opt_no_log) 513 { 514 w2log("No MySQL servers to be stopped (check your GNRs)", 515 "$opt_log", 0, 0); 516 } 517} 518 519#### 520#### Sub function for mysqladmin option parsing 521#### 522 523sub get_mysqladmin_options 524{ 525 my ($i, @groups)= @_; 526 my ($mysqladmin_found, $com, $tmp, $j); 527 528 @options = defaults_for_group($groups[$i]); 529 530 $mysqladmin_found= 1; # The default 531 $mysqladmin_found= 0 if (!length($mysqladmin)); 532 $com = "$mysqladmin"; 533 $tmp = " -u $opt_user"; 534 if (defined($opt_password)) { 535 my $pw= $opt_password; 536 # Protect single quotes in password 537 $pw =~ s/'/'"'"'/g; 538 $tmp.= " -p'$pw'"; 539 } 540 $tmp.= $opt_tcp_ip ? " -h 127.0.0.1" : ""; 541 for ($j = 0; defined($options[$j]); $j++) 542 { 543 if ("--mysqladmin=" eq substr($options[$j], 0, 13)) 544 { 545 $options[$j]=~ s/\-\-mysqladmin\=//; 546 $com= $options[$j]; 547 $mysqladmin_found= 1; 548 } 549 elsif ((($options[$j] =~ m/^(\-\-socket\=)(.*)$/) && !$opt_tcp_ip) || 550 ($options[$j] =~ m/^(\-\-port\=)(.*)$/)) 551 { 552 $tmp.= " $options[$j]"; 553 } 554 } 555 if (!$mysqladmin_found) 556 { 557 print "\n"; 558 print "FATAL ERROR: Tried to use mysqladmin in group [$groups[$i]], "; 559 print "but no mysqladmin binary was found.\n"; 560 print "Please add \"mysqladmin=...\" in group [mysqld_multi], or "; 561 print "in group [$groups[$i]].\n"; 562 exit(1); 563 } 564 $com.= $tmp; 565 return $com; 566} 567 568# Return a list of option files which can be opened. Similar, but not 569# identical, to behavior of my_search_option_files() 570sub list_defaults_files 571{ 572 my %opt; 573 foreach (@defaults_options) 574 { 575 return () if /^--no-defaults$/; 576 $opt{$1} = $2 if /^--defaults-(extra-file|file)=(.*)$/; 577 } 578 579 return ($opt{file}) if exists $opt{file}; 580 581 my %seen; # Don't list the same file more than once 582 return grep { defined $_ and not $seen{$_}++ and -f $_ and -r $_ } 583 ('/etc/my.cnf', 584 '/etc/mysql/my.cnf', 585 '@sysconfdir@/my.cnf', 586 ($ENV{MYSQL_HOME} ? "$ENV{MYSQL_HOME}/my.cnf" : undef), 587 $opt{'extra-file'}, 588 ($ENV{HOME} ? "$ENV{HOME}/.my.cnf" : undef)); 589} 590 591 592# Takes a specification of GNRs (see --help), and returns a list of matching 593# groups which actually are mentioned in a relevant config file 594sub find_groups 595{ 596 my ($raw_gids) = @_; 597 598 my %gids; 599 my @groups; 600 601 if (defined($raw_gids)) 602 { 603 # Make a hash of the wanted group ids 604 foreach my $raw_gid (split ',', $raw_gids) 605 { 606 # Match 123 or 123-456 607 my ($start, $end) = ($raw_gid =~ /^\s*(\d+)(?:\s*-\s*(\d+))?\s*$/); 608 $end = $start if not defined $end; 609 if (not defined $start or $end < $start or $start < 0) 610 { 611 print "ABORT: Bad GNR: $raw_gid; see $my_progname --help\n"; 612 exit(1); 613 } 614 615 foreach my $i ($start .. $end) 616 { 617 # Use $i + 0 to normalize numbers (002 + 0 -> 2) 618 $gids{$i + 0}= 1; 619 } 620 } 621 } 622 623 my @defaults_files = list_defaults_files(); 624 #warn "@{[sort keys %gids]} -> @defaults_files\n"; 625 foreach my $file (@defaults_files) 626 { 627 next unless open CONF, "< $file"; 628 629 while (<CONF>) 630 { 631 if (/^\s*\[\s*(mysqld)(\d+)\s*\]\s*$/) 632 { 633 #warn "Found a group: $1$2\n"; 634 # Use $2 + 0 to normalize numbers (002 + 0 -> 2) 635 if (not defined($raw_gids) or $gids{$2 + 0}) 636 { 637 push @groups, "$1$2"; 638 } 639 } 640 } 641 642 close CONF; 643 } 644 return @groups; 645} 646 647#### 648#### w2log: Write to a logfile. 649#### 1.arg: append to the log file (given string, or from a file. if a file, 650#### file will be read from $opt_logdir) 651#### 2.arg: logfile -name (w2log assumes that the logfile is in $opt_logdir). 652#### 3.arg. 0 | 1, if true, print current date to the logfile. 3. arg will 653#### be ignored, if 1. arg is a file. 654#### 4.arg. 0 | 1, if true, first argument is a file, else a string 655#### 656 657sub w2log 658{ 659 my ($msg, $file, $date_flag, $is_file)= @_; 660 my (@data); 661 662 open (LOGFILE, ">>$opt_log") 663 or die "FATAL: w2log: Couldn't open log file: $opt_log\n"; 664 665 if ($is_file) 666 { 667 open (FROMFILE, "<$msg") && (@data=<FROMFILE>) && 668 close(FROMFILE) 669 or die "FATAL: w2log: Couldn't open file: $msg\n"; 670 foreach my $line (@data) 671 { 672 print LOGFILE "$line"; 673 } 674 } 675 else 676 { 677 print LOGFILE "$msg"; 678 print LOGFILE strftime "%a %b %e %H:%M:%S %Y", localtime if ($date_flag); 679 print LOGFILE "\n"; 680 } 681 close (LOGFILE); 682 return; 683} 684 685#### 686#### my_which is used, because we can't assume that every system has the 687#### which -command. my_which can take only one argument at a time. 688#### Return values: requested system command with the first found path, 689#### or undefined, if not found. 690#### 691 692sub my_which 693{ 694 my ($command) = @_; 695 my (@paths, $path); 696 697 # If the argument is not 'my_print_defaults' then it would be of the format 698 # <absolute_path>/<program> 699 return $command if ($command ne 'my_print_defaults' && -f $command && 700 -x $command); 701 702 @paths = split(':', $ENV{'PATH'}); 703 foreach $path (@paths) 704 { 705 $path .= "/$command"; 706 return $path if (-f $path && -x $path); 707 } 708 return undef(); 709} 710 711 712#### 713#### example 714#### 715 716sub example 717{ 718 print <<EOF; 719# This is an example of a my.cnf file for $my_progname. 720# Usually this file is located in home dir ~/.my.cnf or /etc/my.cnf 721# 722# SOME IMPORTANT NOTES FOLLOW: 723# 724# 1.COMMON USER 725# 726# Make sure that the MySQL user, who is stopping the mysqld services, has 727# the same password to all MySQL servers being accessed by $my_progname. 728# This user needs to have the 'Shutdown_priv' -privilege, but for security 729# reasons should have no other privileges. It is advised that you create a 730# common 'multi_admin' user for all MySQL servers being controlled by 731# $my_progname. Here is an example how to do it: 732# 733# GRANT SHUTDOWN ON *.* TO multi_admin\@localhost IDENTIFIED BY 'password' 734# 735# You will need to apply the above to all MySQL servers that are being 736# controlled by $my_progname. 'multi_admin' will shutdown the servers 737# using 'mysqladmin' -binary, when '$my_progname stop' is being called. 738# 739# 2.PID-FILE 740# 741# If you are using mysqld_safe to start mysqld, make sure that every 742# MySQL server has a separate pid-file. In order to use mysqld_safe 743# via $my_progname, you need to use two options: 744# 745# mysqld=/path/to/mysqld_safe 746# ledir=/path/to/mysqld-binary/ 747# 748# ledir (library executable directory), is an option that only mysqld_safe 749# accepts, so you will get an error if you try to pass it to mysqld directly. 750# For this reason you might want to use the above options within [mysqld#] 751# group directly. 752# 753# 3.DATA DIRECTORY 754# 755# It is NOT advised to run many MySQL servers within the same data directory. 756# You can do so, but please make sure to understand and deal with the 757# underlying caveats. In short they are: 758# - Speed penalty 759# - Risk of table/data corruption 760# - Data synchronising problems between the running servers 761# - Heavily media (disk) bound 762# - Relies on the system (external) file locking 763# - Is not applicable with all table types. (Such as InnoDB) 764# Trying so will end up with undesirable results. 765# 766# 4.TCP/IP Port 767# 768# Every server requires one and it must be unique. 769# 770# 5.[mysqld#] Groups 771# 772# In the example below the first and the fifth mysqld group was 773# intentionally left out. You may have 'gaps' in the config file. This 774# gives you more flexibility. 775# 776# 6.MySQL Server User 777# 778# You can pass the user=... option inside [mysqld#] groups. This 779# can be very handy in some cases, but then you need to run $my_progname 780# as UNIX root. 781# 782# 7.A Start-up Manage Script for $my_progname 783# 784# In the recent MySQL distributions you can find a file called 785# mysqld_multi.server.sh. It is a wrapper for $my_progname. This can 786# be used to start and stop multiple servers during boot and shutdown. 787# 788# You can place the file in /etc/init.d/mysqld_multi.server.sh and 789# make the needed symbolic links to it from various run levels 790# (as per Linux/Unix standard). You may even replace the 791# /etc/init.d/mysql.server script with it. 792# 793# Before using, you must create a my.cnf file either in @sysconfdir@/my.cnf 794# or /root/.my.cnf and add the [mysqld_multi] and [mysqld#] groups. 795# 796# The script can be found from support-files/mysqld_multi.server.sh 797# in MySQL distribution. (Verify the script before using) 798# 799 800[mysqld_multi] 801mysqld = @bindir@/mysqld_safe 802mysqladmin = @bindir@/mysqladmin 803user = multi_admin 804password = my_password 805 806[mysqld2] 807socket = /tmp/mysql.sock2 808port = 3307 809pid-file = @localstatedir@2/hostname.pid2 810datadir = @localstatedir@2 811language = @datadir@/mysql/english 812user = unix_user1 813 814[mysqld3] 815mysqld = /path/to/mysqld_safe 816ledir = /path/to/mysqld-binary/ 817mysqladmin = /path/to/mysqladmin 818socket = /tmp/mysql.sock3 819port = 3308 820pid-file = @localstatedir@3/hostname.pid3 821datadir = @localstatedir@3 822language = @datadir@/mysql/swedish 823user = unix_user2 824 825[mysqld4] 826socket = /tmp/mysql.sock4 827port = 3309 828pid-file = @localstatedir@4/hostname.pid4 829datadir = @localstatedir@4 830language = @datadir@/mysql/estonia 831user = unix_user3 832 833[mysqld6] 834socket = /tmp/mysql.sock6 835port = 3311 836pid-file = @localstatedir@6/hostname.pid6 837datadir = @localstatedir@6 838language = @datadir@/mysql/japanese 839user = unix_user4 840EOF 841 exit(0); 842} 843 844#### 845#### usage 846#### 847 848sub usage 849{ 850 print <<EOF; 851$my_progname version $VER by Jani Tolonen 852 853Description: 854$my_progname can be used to start, reload, or stop any number of separate 855mysqld processes running in different TCP/IP ports and UNIX sockets. 856 857$my_progname can read group [mysqld_multi] from my.cnf file. You may 858want to put options mysqld=... and mysqladmin=... there. Since 859version 2.10 these options can also be given under groups [mysqld#], 860which gives more control over different versions. One can have the 861default mysqld and mysqladmin under group [mysqld_multi], but this is 862not mandatory. Please note that if mysqld or mysqladmin is missing 863from both [mysqld_multi] and [mysqld#], a group that is tried to be 864used, $my_progname will abort with an error. 865 866$my_progname will search for groups named [mysqld#] from my.cnf (or 867the given --defaults-extra-file=...), where '#' can be any positive 868integer starting from 1. These groups should be the same as the regular 869[mysqld] group, but with those port, socket and any other options 870that are to be used with each separate mysqld process. The number 871in the group name has another function; it can be used for starting, 872reloading, stopping, or reporting any specific mysqld server. 873 874Usage: $my_progname [OPTIONS] {start|reload|stop|report} [GNR,GNR,GNR...] 875or $my_progname [OPTIONS] {start|reload|stop|report} [GNR-GNR,GNR,GNR-GNR,...] 876 877The GNR means the group number. You can start, reload, stop or report any GNR, 878or several of them at the same time. (See --example) The GNRs list can 879be comma separated or a dash combined. The latter means that all the 880GNRs between GNR1-GNR2 will be affected. Without GNR argument all the 881groups found will either be started, reloaded, stopped, or reported. Note that 882syntax for specifying GNRs must appear without spaces. 883 884Options: 885 886These options must be given before any others: 887--no-defaults Do not read any defaults file 888--defaults-file=... Read only this configuration file, do not read the 889 standard system-wide and user-specific files 890--defaults-extra-file=... Read this configuration file in addition to the 891 standard system-wide and user-specific files 892Using: @{[join ' ', @defaults_options]} 893 894--example Give an example of a config file with extra information. 895--help Print this help and exit. 896--log=... Log file. Full path to and the name for the log file. NOTE: 897 If the file exists, everything will be appended. 898 Using: $opt_log 899--mysqladmin=... mysqladmin binary to be used for a server shutdown. 900 Since version 2.10 this can be given within groups [mysqld#] 901 Using: $mysqladmin 902--mysqld=... mysqld binary to be used. Note that you can give mysqld_safe 903 to this option also. The options are passed to mysqld. Just 904 make sure you have mysqld in your PATH or fix mysqld_safe. 905 Using: $mysqld 906 Please note: Since mysqld_multi version 2.3 you can also 907 give this option inside groups [mysqld#] in ~/.my.cnf, 908 where '#' stands for an integer (number) of the group in 909 question. This will be recognised as a special option and 910 will not be passed to the mysqld. This will allow one to 911 start different mysqld versions with mysqld_multi. 912--no-log Print to stdout instead of the log file. By default the log 913 file is turned on. 914--password=... Password for mysqladmin user. 915--silent Disable warnings. 916--tcp-ip Connect to the MySQL server(s) via the TCP/IP port instead 917 of the UNIX socket. This affects stopping and reporting. 918 If a socket file is missing, the server may still be 919 running, but can be accessed only via the TCP/IP port. 920 By default connecting is done via the UNIX socket. 921--user=... mysqladmin user. Using: $opt_user 922--verbose Be more verbose. 923--version Print the version number and exit. 924EOF 925 exit(0); 926} 927