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