mysqld_multi.pl 26 KB

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