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