mysqld_multi.pl 27 KB

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