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