summaryrefslogtreecommitdiff
path: root/scripts
diff options
context:
space:
mode:
Diffstat (limited to 'scripts')
-rw-r--r--scripts/Makefile.am14
-rw-r--r--scripts/make_binary_distribution.sh17
-rw-r--r--scripts/mysql_config.sh13
-rw-r--r--scripts/mysql_explain_log.sh383
-rw-r--r--scripts/mysql_fix_privilege_tables.sh82
-rw-r--r--scripts/mysql_install_db.sh46
-rw-r--r--scripts/mysql_secure_installation.sh308
-rw-r--r--scripts/mysql_tableinfo.sh478
-rw-r--r--scripts/mysql_zap.sh2
-rw-r--r--scripts/mysqld_multi.sh45
-rw-r--r--scripts/mysqld_safe-watch.sh (renamed from scripts/safe_mysqld-watch.sh)2
-rw-r--r--scripts/mysqld_safe.sh (renamed from scripts/safe_mysqld.sh)100
12 files changed, 1416 insertions, 74 deletions
diff --git a/scripts/Makefile.am b/scripts/Makefile.am
index 18957b6422d..1469f3f2f2d 100644
--- a/scripts/Makefile.am
+++ b/scripts/Makefile.am
@@ -20,7 +20,9 @@ bin_SCRIPTS = @server_scripts@ \
msql2mysql \
mysql_config \
mysql_fix_privilege_tables \
+ mysql_fix_extensions \
mysql_setpermission \
+ mysql_secure_installation \
mysql_zap \
mysqlaccess \
mysqlbug \
@@ -28,14 +30,18 @@ bin_SCRIPTS = @server_scripts@ \
mysql_find_rows \
mysqlhotcopy \
mysqldumpslow \
+ mysql_explain_log \
+ mysql_tableinfo \
mysqld_multi
EXTRA_SCRIPTS = make_binary_distribution.sh \
msql2mysql.sh \
mysql_config.sh \
mysql_fix_privilege_tables.sh \
+ mysql_fix_extensions.sh \
mysql_install_db.sh \
mysql_setpermission.sh \
+ mysql_secure_installation.sh \
mysql_zap.sh \
mysqlaccess.sh \
mysqlbug.sh \
@@ -43,8 +49,10 @@ EXTRA_SCRIPTS = make_binary_distribution.sh \
mysql_find_rows.sh \
mysqlhotcopy.sh \
mysqldumpslow.sh \
+ mysql_explain_log.sh \
mysqld_multi.sh \
- safe_mysqld.sh
+ mysql_tableinfo.sh \
+ mysqld_safe.sh
EXTRA_DIST = $(EXTRA_SCRIPTS) \
mysqlaccess.conf \
@@ -59,7 +67,9 @@ CLEANFILES = @server_scripts@ \
msql2mysql \
mysql_config \
mysql_fix_privilege_tables \
+ mysql_fix_extensions \
mysql_setpermission \
+ mysql_secure_installation \
mysql_zap \
mysqlaccess \
mysql_convert_table_format \
@@ -95,6 +105,8 @@ SUFFIXES = .sh
-e 's!@''CXXFLAGS''@!@SAVE_CXXFLAGS@!'\
-e 's!@''LDFLAGS''@!@SAVE_LDFLAGS@!'\
-e 's!@''CLIENT_LIBS''@!@CLIENT_LIBS@!' \
+ -e 's!@''LIBS''@!@LIBS@!' \
+ -e 's!@''innodb_system_libs''@!@innodb_system_libs@!' \
-e 's!@''VERSION''@!@VERSION@!' \
-e 's!@''MYSQL_SERVER_SUFFIX''@!@MYSQL_SERVER_SUFFIX@!' \
-e 's!@''COMPILATION_COMMENT''@!@COMPILATION_COMMENT@!' \
diff --git a/scripts/make_binary_distribution.sh b/scripts/make_binary_distribution.sh
index bde77713d63..9d25943bb52 100644
--- a/scripts/make_binary_distribution.sh
+++ b/scripts/make_binary_distribution.sh
@@ -69,9 +69,12 @@ for i in extra/comp_err extra/replace extra/perror extra/resolveip \
myisam/myisampack sql/mysqld client/mysqlbinlog \
client/mysql sql/mysqld client/mysqlshow client/mysqlcheck \
client/mysqladmin client/mysqldump client/mysqlimport client/mysqltest \
+ client/mysqlmanagerc client/mysqlmanager-pwgen tools/mysqlmanager \
client/.libs/mysql client/.libs/mysqlshow client/.libs/mysqladmin \
client/.libs/mysqldump client/.libs/mysqlimport client/.libs/mysqltest \
- client/.libs/mysqlcheck client/.libs/mysqlbinlog
+ client/.libs/mysqlcheck client/.libs/mysqlbinlog \
+ client/.libs/mysqlmanagerc client/.libs/mysqlmanager-pwgen \
+ tools/.libs/mysqlmanager
do
if [ -f $i ]
then
@@ -91,7 +94,7 @@ do
fi
done
-for i in libmysql/.libs/libmysqlclient.a libmysql/.libs/libmysqlclient.so* libmysql/libmysqlclient.* libmysql_r/.libs/libmysqlclient_r.a libmysql_r/.libs/libmysqlclient_r.so* libmysql_r/libmysqlclient_r.* mysys/libmysys.a strings/libmystrings.a dbug/libdbug.a $BASE/lib
+for i in libmysql/.libs/libmysqlclient.a libmysql/.libs/libmysqlclient.so* libmysql/libmysqlclient.* libmysql_r/.libs/libmysqlclient_r.a libmysql_r/.libs/libmysqlclient_r.so* libmysql_r/libmysqlclient_r.* mysys/libmysys.a strings/libmystrings.a dbug/libdbug.a libmysqld/.libs/libmysqld.a libmysqld/.libs/libmysqld.so* libmysqld/libmysqld.a
do
if [ -f $i ]
then
@@ -120,11 +123,15 @@ $CP scripts/* $BASE/bin
rm -f $BASE/bin/Makefile* $BASE/bin/*.in $BASE/bin/*.sh $BASE/bin/mysql_install_db $BASE/bin/make_binary_distribution $BASE/bin/setsomevars $BASE/support-files/Makefile* $BASE/support-files/*.sh
$BASE/bin/replace \@localstatedir\@ ./data \@bindir\@ ./bin \@scriptdir\@ ./bin \@libexecdir\@ ./bin \@sbindir\@ ./bin \@prefix\@ . \@HOSTNAME\@ @HOSTNAME@ < $SOURCE/scripts/mysql_install_db.sh > $BASE/scripts/mysql_install_db
-$BASE/bin/replace \@prefix\@ /usr/local/mysql \@bindir\@ ./bin \@MYSQLD_USER\@ root \@localstatedir\@ /usr/local/mysql/data < $SOURCE/support-files/mysql.server.sh > $BASE/support-files/mysql.server
-$BASE/bin/replace /my/gnu/bin/hostname /bin/hostname -- $BASE/bin/safe_mysqld
+$BASE/bin/replace \@prefix\@ /usr/local/mysql \@bindir\@ ./bin \@MYSQLD_USER\@ root \@localstatedir\@ /usr/local/mysql/data \@HOSTNAME\@ @HOSTNAME@ < $SOURCE/support-files/mysql.server.sh > $BASE/support-files/mysql.server
+$BASE/bin/replace /my/gnu/bin/hostname /bin/hostname -- $BASE/bin/mysqld_safe
+
+# Make safe_mysqld a symlink to mysqld_safe for backwards portability
+# To be removed in MySQL 4.1
+(cd $BASE/bin ; ln -s mysqld_safe safe_mysqld )
mv $BASE/support-files/binary-configure $BASE/configure
-chmod a+x $BASE/bin/* $BASE/scripts/* $BASE/support-files/mysql-* $BASE/configure
+chmod a+x $BASE/bin/* $BASE/scripts/* $BASE/support-files/mysql-* $BASE/support-files/mysql.server $BASE/configure
$CP -r sql-bench/* $BASE/sql-bench
rm -f $BASE/sql-bench/*.sh $BASE/sql-bench/Makefile* $BASE/lib/*.la
diff --git a/scripts/mysql_config.sh b/scripts/mysql_config.sh
index 9320efdd2a1..3cc5b3a5016 100644
--- a/scripts/mysql_config.sh
+++ b/scripts/mysql_config.sh
@@ -87,16 +87,18 @@ client_libs='@CLIENT_LIBS@'
libs="$ldflags -L'$pkglibdir' -lmysqlclient $client_libs"
libs=`echo $libs | sed -e 's; +;;'`
cflags="-I'$pkgincludedir'"
+embedded_libs="$ldflags -L'$pkglibdir' -lmysqld @LIBS@ @innodb_system_libs@"
usage () {
cat <<EOF
Usage: $0 [OPTIONS]
Options:
- --cflags [$cflags]
- --libs [$libs]
- --socket [$socket]
- --port [$port]
- --version [$version]
+ --cflags [$cflags]
+ --libs [$libs]
+ --socket [$socket]
+ --port [$port]
+ --version [$version]
+ --libmysqld-libs [$embedded_libs]
EOF
exit 1
}
@@ -110,6 +112,7 @@ while test $# -gt 0; do
--socket) echo "$socket" ;;
--port) echo "$port" ;;
--version) echo "$version" ;;
+ --embedded-libs | --embedded | --libmysqld-libs) echo "$embedded_libs" ;;
*) usage ;;
esac
diff --git a/scripts/mysql_explain_log.sh b/scripts/mysql_explain_log.sh
new file mode 100644
index 00000000000..c4a4ef21568
--- /dev/null
+++ b/scripts/mysql_explain_log.sh
@@ -0,0 +1,383 @@
+#!@PERL@ -w
+use strict;
+use DBI;
+
+use Getopt::Long;
+$Getopt::Long::ignorecase=0;
+
+print "explain_log provided by http://www.mobile.de\n";
+print "=========== ================================\n";
+
+my $Param={};
+
+$Param->{host}='';
+$Param->{user}='';
+$Param->{password}='';
+$Param->{PrintError}=0;
+
+if (!GetOptions ('date|d:i' => \$Param->{ViewDate},
+ 'host|h:s' => \$Param->{host},
+ 'user|u:s' => \$Param->{user},
+ 'password|p:s' => \$Param->{password},
+ 'printerror|e:s' => \$Param->{PrintError},
+ )) {
+ ShowOptions();
+}
+else {
+ $Param->{UpdateCount} = 0;
+ $Param->{SelectCount} = 0;
+ $Param->{IdxUseCount} = 0;
+ $Param->{LineCount} = 0;
+
+ $Param->{Init} = 0;
+ $Param->{Field} = 0;
+ $Param->{Refresh} = 0;
+ $Param->{QueryCount} = 0;
+ $Param->{Statistics} =0;
+
+ $Param->{Query} = undef;
+ $Param->{ALL} = undef ;
+ $Param->{Comment} = undef ;
+
+ @{$Param->{Rows}} = (qw|possible_keys key type|);
+
+ if ($Param->{ViewDate}) {
+ $Param->{View} = 0;
+ }
+ else {
+ $Param->{View} = 1;
+ }
+
+ #print "Date=$Param->{ViewDate}, host=$Param->{host}, user=$Param->{user}, password=$Param->{password}\n";
+
+ $Param->{dbh}=DBI->connect("DBI:mysql:host=$Param->{host}",$Param->{user},$Param->{password},{PrintError=>0});
+ if (DBI::err()) {
+ print "Error: " . DBI::errstr() . "\n";
+ }
+ else {
+ $Param->{Start} = time;
+ while(<STDIN>) {
+ $Param->{LineCount} ++ ;
+
+ if ($Param->{ViewDate} ) {
+ if (m/^(\d{6})\s+\d{1,2}:\d\d:\d\d\s.*$/) { # get date
+ #print "# $1 #\n";
+ if ($1 == $Param->{ViewDate}) {
+ $Param->{View} = 1;
+ }
+ else {
+ $Param->{View} = 0;
+ }
+ }
+ }
+ if ($Param->{View} ) {
+ #print "->>>$_";
+
+ if (m/^(\d{6}\s+\d{1,2}:\d\d:\d\d\s+|\s+)(\d+)\s+Connect.+\s+on\s+(.*)$/i) { # get connection ID($2) and database($3)
+ #print "C-$1--$2--$3------\n";
+ RunQuery($Param);
+ if (defined $3) {
+ $Param->{CID}->{$2} = $3 ;
+ #print "DB:$Param->{CID}->{$2} .. $2 .. $3 \n";
+ }
+ }
+
+ elsif (m/^(\d{6}\s+\d{1,2}:\d\d:\d\d\s+|\s+)(\d+)\s+Connect.+$/i) { # get connection ID($2) and database($3)
+ #print "\n <<<<<<<<<<<<<<<<<<----------------------------<<<<<<<<<<<<<<<< \n";
+ #print "Connect \n";
+ RunQuery($Param);
+ }
+ elsif (m/^(\d{6}\s+\d{1,2}:\d\d:\d\d\s+|\s+)(\d+)\s+Change user .*\s+on\s+(.*)$/i) { # get connection ID($2) and database($3)
+ #print "C-$1--$2--$3------\n";
+ RunQuery($Param);
+ if (defined $3) {
+ $Param->{CID}->{$2} = $3 ;
+ #print "DB:$Param->{CID}->{$2} .. $2 .. $3 \n";
+ }
+ }
+
+ elsif (m/^(\d{6}\s+\d{1,2}:\d\d:\d\d\s+|\s+)(\d+)\s+Quit\s+$/i) { # remove connection ID($2) and querystring
+ #print "Q-$1--$2--------\n";
+ RunQuery($Param);
+ delete $Param->{CID}->{$2} ;
+ }
+
+ elsif (m/^(\d{6}\s+\d{1,2}:\d\d:\d\d\s+|\s+)(\d+)\s+Query\s+(select.+)$/i) { # get connection ID($2) and querystring
+ #print "S1-$1--$2--$3------\n";
+ RunQuery($Param);
+ unless ($Param->{CID}->{$2}) {
+ #print "Error: No Database for Handle: $2 found\n";
+ }
+ else {
+ $Param->{DB}=$Param->{CID}->{$2};
+
+ my $s = "$3";
+ $s =~ s/from\s/from $Param->{DB}./i;
+ $Param->{Query}="EXPLAIN $s";
+
+ #$s =~ m/from\s+(\w+[.]\w+)/i;
+ #$Param->{tab} =$1;
+ #print "-- $Param->{tab} -- $s --\n";
+ }
+ }
+
+ elsif (m/^(\d{6}\s+\d{1,2}:\d\d:\d\d\s+|\s+)(\d+)\s+Query\s+(update.+)$/i) { # get connection ID($2) and querystring
+ #print "S2--$1--$2--$3------\n";
+ RunQuery($Param);
+ unless ($Param->{CID}->{$2}) {
+ #print "Error: No Database for Handle: $2 found\n";
+ }
+ else {
+ $Param->{DB}=$Param->{CID}->{$2};
+
+ my $ud = $3;
+ $ud =~ m/^update\s+(\w+).+(where.+)$/i;
+ $Param->{Query} ="EXPLAIN SELECT * FROM $1 $2";
+ $Param->{Query} =~ s/from\s/from $Param->{DB}./i;
+
+ #$Param->{Query} =~ m/from\s+(\w+[.]\w+)/i;
+ #$Param->{tab} =$1;
+ }
+ }
+
+ elsif (m/^(\d{6}\s+\d{1,2}:\d\d:\d\d\s+|\s+)(\d+)\s+Statistics\s+(.*)$/i) { # get connection ID($2) and info?
+ $Param->{Statistics} ++;
+ #print "Statistics--$1--$2--$3------\n";
+ RunQuery($Param);
+ }
+ elsif (m/^(\d{6}\s+\d{1,2}:\d\d:\d\d\s+|\s+)(\d+)\s+Query\s+(.+)$/i) { # get connection ID($2)
+ $Param->{QueryCount} ++;
+ #print "Query-NULL $3\n";
+ RunQuery($Param);
+ }
+ elsif (m/^(\d{6}\s+\d{1,2}:\d\d:\d\d\s+|\s+)(\d+)\s+Refresh\s+(.+)$/i) { # get connection ID($2)
+ $Param->{Refresh} ++;
+ #print "Refresh\n";
+ RunQuery($Param);
+ }
+ elsif (m/^(\d{6}\s+\d{1,2}:\d\d:\d\d\s+|\s+)(\d+)\s+Init\s+(.+)$/i) { # get connection ID($2)
+ $Param->{Init} ++;
+ #print "Init $3\n";
+ RunQuery($Param);
+ }
+ elsif (m/^(\d{6}\s+\d{1,2}:\d\d:\d\d\s+|\s+)(\d+)\s+Field\s+(.+)$/i) { # get connection ID($2)
+ $Param->{Field} ++;
+ #print "Field $3\n";
+ RunQuery($Param);
+ }
+
+ elsif (m/^\s+(.+)$/ ) { # command could be some lines ...
+ #print "multi-lined ($1)\n";
+ my ($A)=$1;
+ chomp $A;
+ $Param->{Query} .= " $1";
+ #print "multi-lined ($1)<<$Param->{Query}>>\n";
+ }
+
+
+ }
+
+ }
+
+ $Param->{dbh}->disconnect();
+
+ if (1 == 0) {
+ print "\nunclosed handles----------------------------------------\n";
+ my $count=0;
+ foreach (sort keys %{$Param->{CID}}) {
+ print "$count | $_ : $Param->{CID}->{$_} \n";
+ $count ++;
+ }
+ }
+
+ print "\nIndex usage ------------------------------------\n";
+ foreach my $t (sort keys %{$Param->{Data}}) {
+ print "\nTable\t$t: ---\n";
+ foreach my $k (sort keys %{$Param->{Data}->{$t}}) {
+ print " count\t$k:\n";
+ my %h = %{$Param->{Data}->{$t}->{$k}};
+ foreach (sort {$h{$a} <=> $h{$b}} keys %h) {
+ print " $Param->{Data}->{$t}->{$k}->{$_}\t$_\n";
+ }
+ }
+ }
+
+ $Param->{AllCount}=0;
+ print "\nQueries causing table scans -------------------\n\n";
+ foreach (@{$Param->{ALL}}) {
+ $Param->{AllCount} ++;
+ print "$_\n";
+ }
+ print "Sum: $Param->{AllCount} table scans\n";
+
+ print "\nSummary ---------------------------------------\n\n";
+ print "Select: \t$Param->{SelectCount} queries\n";
+ print "Update: \t$Param->{UpdateCount} queries\n";
+ print "\n";
+
+ print "Init: \t$Param->{Init} times\n";
+ print "Field: \t$Param->{Field} times\n";
+ print "Refresh: \t$Param->{Refresh} times\n";
+ print "Query: \t$Param->{QueryCount} times\n";
+ print "Statistics:\t$Param->{Statistics} times\n";
+ print "\n";
+
+ print "Logfile: \t$Param->{LineCount} lines\n";
+ print "Started: \t".localtime($Param->{Start})."\n";
+ print "Finished: \t".localtime(time)."\n";
+
+ }
+}
+
+
+###########################################################################
+#
+#
+#
+sub RunQuery {
+ my $Param = shift ;
+
+ if (defined $Param->{Query}) {
+ if (defined $Param->{DB} ) {
+
+ $Param->{Query} =~ m/from\s+(\w+[.]\w+|\w+)/i;
+ $Param->{tab} =$1;
+ #print "||$Param->{tab} -- $Param->{Query}\n";
+
+ my $sth=$Param->{dbh}->prepare("USE $Param->{DB}");
+ if (DBI::err()) {
+ if ($Param->{PrintError}) {print "Error: ".DBI::errstr()."\n";}
+ }
+ else {
+ $sth->execute();
+ if (DBI::err()) {
+ if ($Param->{PrintError}) {print "Error: ".DBI::errstr()."\n";}
+ }
+ else {
+ $sth->finish();
+
+ $sth=$Param->{dbh}->prepare($Param->{Query});
+ if (DBI::err()) {
+ if ($Param->{PrintError}) {print "Error: ".DBI::errstr()."\n";}
+ }
+ else {
+ #print "$Param->{Query}\n";
+ $sth->execute();
+ if (DBI::err()) {
+ if ($Param->{PrintError}) {print "[$Param->{LineCount}]<<$Param->{Query}>>\n";}
+ if ($Param->{PrintError}) {print "Error: ".DBI::errstr()."\n";}
+ }
+ else {
+ my $row = undef;
+ while ($row = $sth->fetchrow_hashref()) {
+ $Param->{SelectCount} ++;
+
+ if (defined $row->{Comment}) {
+ push (@{$Param->{Comment}}, "$row->{Comment}; $_; $Param->{DB}; $Param->{Query}");
+ }
+ foreach (@{$Param->{Rows}}) {
+ if (defined $row->{$_}) {
+ #if (($_ eq 'type' ) and ($row->{$_} eq 'ALL')) {
+ if ($row->{type} eq 'ALL') {
+ push (@{$Param->{ALL}}, "$Param->{Query}");
+ #print ">> $row->{$_} $_ $Param->{DB} $Param->{Query}\n";
+ }
+ $Param->{IdxUseCount} ++;
+ $Param->{Data}->{$Param->{tab}}->{$_}->{$row->{$_}} ++;
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+ $sth->finish();
+ }
+ $Param->{Query} = undef ;
+ }
+}
+
+###########################################################################
+#
+#
+#
+sub ShowOptions {
+ print <<EOF;
+Usage: $0 [OPTIONS] < LOGFILE
+
+--date=YYMMDD select only entrys of date
+-d=YYMMDD
+--host=HOSTNAME db-host to ask
+-h=HOSTNAME
+--user=USERNAME db-user
+-u=USERNAME
+--password=PASSWORD password of db-user
+-p=PASSWORD
+
+Read logfile from STDIN an try to EXPLAIN all SELECT statements. All UPDATE statements are rewritten to an EXPLAIN SELECT statement. The results of the EXPLAIN statement are collected and counted. All results with type=ALL are collected in an separete list. Results are printed to STDOUT.
+
+EOF
+}
+
+1;
+
+__END__
+
+=pod
+
+=head1 NAME
+
+explain_log.pl
+
+Feed a mysqld general logfile (created with mysqld --log) back into mysql
+and collect statistics about index usage with EXPLAIN.
+
+=head1 DISCUSSION
+
+To optimize your indices, you have to know which ones are actually
+used and what kind of queries are causing table scans. Especially
+if you are generating your queries dynamically and you have a huge
+amount of queries going on, this isn't easy.
+
+Use this tool to take a look at the effects of your real life queries.
+Then add indices to avoid table scans and remove those which aren't used.
+
+=head1 USAGE
+
+explain_log.pl [--date=YYMMDD] --host=dbhost] [--user=dbuser] [--password=dbpw] < logfile
+
+--date=YYMMDD select only entrys of date
+
+-d=YYMMDD
+
+--host=HOSTNAME db-host to ask
+
+-h=HOSTNAME
+
+--user=USERNAME db-user
+
+-u=USERNAME
+
+--password=PASSWORD password of db-user
+
+-p=PASSWORD
+
+=head1 EXAMPLE
+
+explain_log.pl --host=localhost --user=foo --password=bar < /var/lib/mysql/mobile.log
+
+=head1 AUTHOR
+
+ Stefan Nitz
+ Jan Willamowius <jan@mobile.de>, http://www.mobile.de
+
+=head1 RECRUITING
+
+If you are looking for a MySQL or Perl job, take a look at http://www.mobile.de
+and send me an email with your resume (you must be speaking German!).
+
+=head1 SEE ALSO
+
+mysql documentation
+
+=cut
diff --git a/scripts/mysql_fix_privilege_tables.sh b/scripts/mysql_fix_privilege_tables.sh
index 86312fdab52..247e3399b8b 100644
--- a/scripts/mysql_fix_privilege_tables.sh
+++ b/scripts/mysql_fix_privilege_tables.sh
@@ -12,6 +12,17 @@ echo "and give the MySQL root user password as a argument!"
root_password="$1"
host="localhost"
+echo "Converting all privilege tables to MyISAM format"
+@bindir@/mysql -f --user=root --password="$root_password" --host="$host" mysql <<END_OF_DATA
+ALTER TABLE user type=MyISAM;
+ALTER TABLE db type=MyISAM;
+ALTER TABLE host type=MyISAM;
+ALTER TABLE func type=MyISAM;
+ALTER TABLE columns_priv type=MyISAM;
+ALTER TABLE tables_priv type=MyISAM;
+END_OF_DATA
+
+
# Fix old password format, add File_priv and func table
echo ""
echo "If your tables are already up to date or partially up to date you will"
@@ -57,6 +68,21 @@ END_OF_DATA
fi
#
+# The second alter changes ssl_type to new 4.0.2 format
+
+echo "Adding columns needed by GRANT .. REQUIRE (openssl)"
+echo "You can ignore any Duplicate column errors"
+@bindir@/mysql -f --user=root --password="$root_password" --host="$host" mysql <<END_OF_DATA
+ALTER TABLE user
+ADD ssl_type enum('','ANY','X509', 'SPECIFIED') NOT NULL,
+ADD ssl_cipher BLOB NOT NULL,
+ADD x509_issuer BLOB NOT NULL,
+ADD x509_subject BLOB NOT NULL;
+ALTER TABLE user MODIFY ssl_type enum('','ANY','X509', 'SPECIFIED') NOT NULL;
+END_OF_DATA
+echo ""
+
+#
# Create tables_priv and columns_priv if they don't exists
#
@@ -91,11 +117,12 @@ END_OF_DATA
#
echo "Changing name of columns_priv.Type -> columns_priv.Column_priv"
-echo "You can ignore any errors from this"
+echo "You can ignore any Unknown column errors from this"
@bindir@/mysql -f --user=root --password="$root_password" --host="$host" mysql <<END_OF_DATA
ALTER TABLE columns_priv change Type Column_priv set('Select','Insert','Update','References') DEFAULT '' NOT NULL;
END_OF_DATA
+echo ""
#
# Add the new 'type' column to the func table.
@@ -107,3 +134,56 @@ echo "You can ignore any Duplicate column errors"
@bindir@/mysql --user=root --password=$root_password mysql <<EOF
alter table func add type enum ('function','aggregate') NOT NULL;
EOF
+echo ""
+
+#
+# Change the user,db and host tables to MySQL 4.0 format
+#
+
+echo "Adding new fields used by MySQL 4.0.2 to the privilege tables"
+echo "You can ignore any Duplicate column errors"
+
+@bindir@/mysql --user=root --password="$root_password" --host="$host" mysql <<END_OF_DATA
+alter table user
+add Show_db_priv enum('N','Y') DEFAULT 'N' NOT NULL AFTER alter_priv,
+add Super_priv enum('N','Y') DEFAULT 'N' NOT NULL AFTER Show_db_priv,
+add Create_tmp_table_priv enum('N','Y') DEFAULT 'N' NOT NULL AFTER Super_priv,
+add Lock_tables_priv enum('N','Y') DEFAULT 'N' NOT NULL AFTER Create_tmp_table_priv,
+add Execute_priv enum('N','Y') DEFAULT 'N' NOT NULL AFTER Lock_tables_priv,
+add Repl_slave_priv enum('N','Y') DEFAULT 'N' NOT NULL AFTER Execute_priv,
+add Repl_client_priv enum('N','Y') DEFAULT 'N' NOT NULL AFTER Repl_slave_priv;
+END_OF_DATA
+
+if test $? -eq "0"
+then
+ # Convert privileges so that users have similar privileges as before
+ echo ""
+ echo "Updating new privileges in MySQL 4.0.2 from old ones"
+ @bindir@/mysql --user=root --password="$root_password" --host="$host" mysql <<END_OF_DATA
+ update user set show_db_priv= select_priv, super_priv=process_priv, execute_priv=process_priv, create_tmp_table_priv='Y', Lock_tables_priv='Y', Repl_slave_priv=file_priv, Repl_client_priv=file_priv where user<>"";
+END_OF_DATA
+ echo ""
+fi
+
+# Add fields that can be used to limit number of questions and connections
+# for some users.
+
+@bindir@/mysql -f --user=root --password="$root_password" --host="$host" mysql <<END_OF_DATA
+alter table user
+add max_questions int(11) NOT NULL AFTER x509_subject,
+add max_updates int(11) unsigned NOT NULL AFTER max_questions,
+add max_connections int(11) unsigned NOT NULL AFTER max_updates;
+END_OF_DATA
+
+#
+# Add Create_tmp_table_priv and Lock_tables_priv to db and host
+#
+
+@bindir@/mysql --user=root --password="$root_password" --host="$host" mysql <<END_OF_DATA
+alter table db
+add Create_tmp_table_priv enum('N','Y') DEFAULT 'N' NOT NULL,
+add Lock_tables_priv enum('N','Y') DEFAULT 'N' NOT NULL;
+alter table host
+add Create_tmp_table_priv enum('N','Y') DEFAULT 'N' NOT NULL,
+add Lock_tables_priv enum('N','Y') DEFAULT 'N' NOT NULL;
+END_OF_DATA
diff --git a/scripts/mysql_install_db.sh b/scripts/mysql_install_db.sh
index 850432fecc7..2f27f5d7c1a 100644
--- a/scripts/mysql_install_db.sh
+++ b/scripts/mysql_install_db.sh
@@ -1,5 +1,5 @@
#!/bin/sh
-# Copyright (C) 1997, 1998, 1999 TCX DataKonsult AB & Monty Program KB & Detron HB
+# Copyright (C) 2002 MySQL AB
# For a more info consult the file COPYRIGHT distributed with this file.
# This scripts creates the privilege tables db, host, user, tables_priv,
@@ -171,13 +171,15 @@ then
c_d="$c_d References_priv enum('N','Y') DEFAULT 'N' NOT NULL,"
c_d="$c_d Index_priv enum('N','Y') DEFAULT 'N' NOT NULL,"
c_d="$c_d Alter_priv enum('N','Y') DEFAULT 'N' NOT NULL,"
+ c_d="$c_d Create_tmp_table_priv enum('N','Y') DEFAULT 'N' NOT NULL,"
+ c_d="$c_d Lock_tables_priv enum('N','Y') DEFAULT 'N' NOT NULL,"
c_d="$c_d PRIMARY KEY Host (Host,Db,User),"
c_d="$c_d KEY User (User)"
c_d="$c_d )"
c_d="$c_d comment='Database privileges';"
- i_d="INSERT INTO db VALUES ('%','test','','Y','Y','Y','Y','Y','Y','N','Y','Y','Y');
- INSERT INTO db VALUES ('%','test\_%','','Y','Y','Y','Y','Y','Y','N','Y','Y','Y');"
+ i_d="INSERT INTO db VALUES ('%','test','','Y','Y','Y','Y','Y','Y','N','Y','Y','Y','Y','Y');
+ INSERT INTO db VALUES ('%','test\_%','','Y','Y','Y','Y','Y','Y','N','Y','Y','Y','Y','Y');"
fi
if test ! -f $mdata/host.frm
@@ -197,6 +199,8 @@ then
c_h="$c_h References_priv enum('N','Y') DEFAULT 'N' NOT NULL,"
c_h="$c_h Index_priv enum('N','Y') DEFAULT 'N' NOT NULL,"
c_h="$c_h Alter_priv enum('N','Y') DEFAULT 'N' NOT NULL,"
+ c_h="$c_h Create_tmp_table_priv enum('N','Y') DEFAULT 'N' NOT NULL,"
+ c_h="$c_h Lock_tables_priv enum('N','Y') DEFAULT 'N' NOT NULL,"
c_h="$c_h PRIMARY KEY Host (Host,Db)"
c_h="$c_h )"
c_h="$c_h comment='Host privileges; Merged with database privileges';"
@@ -224,18 +228,32 @@ then
c_u="$c_u References_priv enum('N','Y') DEFAULT 'N' NOT NULL,"
c_u="$c_u Index_priv enum('N','Y') DEFAULT 'N' NOT NULL,"
c_u="$c_u Alter_priv enum('N','Y') DEFAULT 'N' NOT NULL,"
+ c_u="$c_u Show_db_priv enum('N','Y') DEFAULT 'N' NOT NULL,"
+ c_u="$c_u Super_priv enum('N','Y') DEFAULT 'N' NOT NULL,"
+ c_u="$c_u Create_tmp_table_priv enum('N','Y') DEFAULT 'N' NOT NULL,"
+ c_u="$c_u Lock_tables_priv enum('N','Y') DEFAULT 'N' NOT NULL,"
+ c_u="$c_u Execute_priv enum('N','Y') DEFAULT 'N' NOT NULL,"
+ c_u="$c_u Repl_slave_priv enum('N','Y') DEFAULT 'N' NOT NULL,"
+ c_u="$c_u Repl_client_priv enum('N','Y') DEFAULT 'N' NOT NULL,"
+ c_u="$c_u ssl_type enum('','ANY','X509', 'SPECIFIED') DEFAULT '' NOT NULL,"
+ c_u="$c_u ssl_cipher BLOB NOT NULL,"
+ c_u="$c_u x509_issuer BLOB NOT NULL,"
+ c_u="$c_u x509_subject BLOB NOT NULL,"
+ c_u="$c_u max_questions int(11) unsigned DEFAULT 0 NOT NULL,"
+ c_u="$c_u max_updates int(11) unsigned DEFAULT 0 NOT NULL,"
+ c_u="$c_u max_connections int(11) unsigned DEFAULT 0 NOT NULL,"
c_u="$c_u PRIMARY KEY Host (Host,User)"
c_u="$c_u )"
c_u="$c_u comment='Users and global privileges';"
- i_u="INSERT INTO user VALUES ('localhost','root','','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y');
- INSERT INTO user VALUES ('$hostname','root','','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y');
+ i_u="INSERT INTO user VALUES ('localhost','root','','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','','','','',0,0,0);
+ INSERT INTO user VALUES ('$hostname','root','','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','','','','',0,0,0);
- REPLACE INTO user VALUES ('localhost','root','','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y');
- REPLACE INTO user VALUES ('$hostname','root','','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y');
+ REPLACE INTO user VALUES ('localhost','root','','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','','','','',0,0,0);
+ REPLACE INTO user VALUES ('$hostname','root','','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','','','','',0,0,0);
- INSERT INTO user VALUES ('localhost','','','N','N','N','N','N','N','N','N','N','N','N','N','N','N');
- INSERT INTO user VALUES ('$hostname','','','N','N','N','N','N','N','N','N','N','N','N','N','N','N');"
+ INSERT INTO user (host,user) values ('localhost','');
+ INSERT INTO user (host,user) values ('$hostname','');"
fi
if test ! -f $mdata/func.frm
@@ -290,7 +308,7 @@ fi
echo "Installing all prepared tables"
if eval "$execdir/mysqld $defaults --bootstrap --skip-grant-tables \
- --basedir=$basedir --datadir=$ldata --skip-innodb --skip-gemini --skip-bdb $args" << END_OF_DATA
+ --basedir=$basedir --datadir=$ldata --skip-innodb --skip-bdb $args" << END_OF_DATA
use mysql;
$c_d
$i_d
@@ -317,8 +335,8 @@ then
fi
echo "PLEASE REMEMBER TO SET A PASSWORD FOR THE MySQL root USER !"
echo "This is done with:"
- echo "$bindir/mysqladmin -u root password 'new-password'"
- echo "$bindir/mysqladmin -u root -h $hostname password 'new-password'"
+ echo "$bindir/mysqladmin -u root password 'new-password'"
+ echo "$bindir/mysqladmin -u root -h $hostname password 'new-password'"
echo "See the manual for more instructions."
#
# Print message about upgrading unless we have created a new db table.
@@ -333,10 +351,10 @@ then
if test "$IN_RPM" -eq 0
then
echo "You can start the MySQL daemon with:"
- echo "cd @prefix@ ; $bindir/safe_mysqld &"
+ echo "cd @prefix@ ; $bindir/mysqld_safe &"
echo
echo "You can test the MySQL daemon with the benchmarks in the 'sql-bench' directory:"
- echo "cd sql-bench ; run-all-tests"
+ echo "cd sql-bench ; perl run-all-tests"
echo
fi
echo "Please report any problems with the @scriptdir@/mysqlbug script!"
diff --git a/scripts/mysql_secure_installation.sh b/scripts/mysql_secure_installation.sh
new file mode 100644
index 00000000000..d6392c57731
--- /dev/null
+++ b/scripts/mysql_secure_installation.sh
@@ -0,0 +1,308 @@
+#!/bin/sh
+
+# Copyright (C) 2002 MySQL AB and Jeremy Cole
+#
+# This program is free software; you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation; either version 2 of the License, or
+# (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program; if not, write to the Free Software
+# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+
+config=".my.cnf.$$"
+command=".mysql.$$"
+
+trap "interrupt" 2
+
+rootpass=""
+
+prepare() {
+ touch $config $command
+ chmod 600 $config $command
+}
+
+do_query() {
+ echo $1 >$command
+ mysql --defaults-file=$config <$command
+ return $?
+}
+
+make_config() {
+ echo "# mysql_secure_installation config file" >$config
+ echo "[mysql]" >>$config
+ echo "user=root" >>$config
+ echo "password=$rootpass" >>$config
+}
+
+get_root_password() {
+ status=1
+ while [ $status -eq 1 ]; do
+ stty -echo
+ echo -n "Enter current password for root (enter for none): "
+ read password
+ echo
+ stty echo
+ if [ "x$password" = "x" ]; then
+ hadpass=0
+ else
+ hadpass=1
+ fi
+ rootpass=$password
+ make_config
+ do_query ""
+ status=$?
+ done
+ echo "OK, successfully used password, moving on..."
+ echo
+}
+
+set_root_password() {
+ stty -echo
+ echo -n "New password: "
+ read password1
+ echo
+ echo -n "Re-enter new password: "
+ read password2
+ echo
+ stty echo
+
+ if [ "$password1" != "$password2" ]; then
+ echo "Sorry, passwords do not match."
+ echo
+ return 1
+ fi
+
+ if [ "$password1" = "" ]; then
+ echo "Sorry, you can't use an empty password here."
+ echo
+ return 1
+ fi
+
+ do_query "SET PASSWORD FOR root=PASSWORD('$password1');"
+ if [ $? -eq 0 ]; then
+ echo "Password updated successfully!"
+ echo
+ rootpass=$password1
+ make_config
+ else
+ echo "Password update failed!"
+ exit 1
+ fi
+
+ return 0
+}
+
+remove_anonymous_users() {
+ do_query "DELETE FROM mysql.user WHERE User='';"
+ if [ $? -eq 0 ]; then
+ echo " ... Success!"
+ else
+ echo " ... Failed!"
+ exit 1
+ fi
+
+ return 0
+}
+
+remove_remote_root() {
+ do_query "DELETE FROM mysql.user WHERE User='root' AND Host!='localhost';"
+ if [ $? -eq 0 ]; then
+ echo " ... Success!"
+ else
+ echo " ... Failed!"
+ fi
+}
+
+remove_test_database() {
+ echo " - Dropping test database..."
+ do_query "DROP DATABASE test;"
+ if [ $? -eq 0 ]; then
+ echo " ... Success!"
+ else
+ echo " ... Failed! Not critical, keep moving..."
+ fi
+
+ echo " - Removing privileges on test database..."
+ do_query "DELETE FROM mysql.db WHERE Db='test' OR Db='test\\_%'"
+ if [ $? -eq 0 ]; then
+ echo " ... Success!"
+ else
+ echo " ... Failed! Not critical, keep moving..."
+ fi
+
+ return 0
+}
+
+reload_privilege_tables() {
+ do_query "FLUSH PRIVILEGES;"
+ if [ $? -eq 0 ]; then
+ echo " ... Success!"
+ else
+ echo " ... Failed!"
+ fi
+
+ return 0
+}
+
+interrupt() {
+ echo
+ echo "Aborting!"
+ echo
+ cleanup
+ stty echo
+ exit 1
+}
+
+cleanup() {
+ echo "Cleaning up..."
+ rm -f $config $command
+}
+
+
+# The actual script starts here
+
+prepare
+
+echo
+echo
+echo
+echo
+echo "NOTE: RUNNING ALL PARTS OF THIS SCRIPT IS RECOMMENDED FOR ALL MySQL"
+echo " SERVERS IN PRODUCTION USE! PLEASE READ EACH STEP CAREFULLY!"
+echo
+echo
+
+echo "In order to log into MySQL to secure it, we'll need the current"
+echo "password for the root user. If you've just installed MySQL, and"
+echo "you haven't set the root password yet, the password will be blank,"
+echo "so you should just press enter here."
+echo
+
+get_root_password
+
+
+#
+# Set the root password
+#
+
+echo "Setting the root password ensures that nobody can log into the MySQL"
+echo "root user without the proper authorisation."
+echo
+
+if [ $hadpass -eq 0 ]; then
+ echo -n "Set root password? [Y/n] "
+else
+ echo "You already have a root password set, so you can safely answer 'n'."
+ echo
+ echo -n "Change the root password? [Y/n] "
+fi
+
+read reply
+if [ "$reply" = "n" ]; then
+ echo " ... skipping."
+else
+ status=1
+ while [ $status -eq 1 ]; do
+ set_root_password
+ status=$?
+ done
+fi
+echo
+
+
+#
+# Remove anonymous users
+#
+
+echo "By default, a MySQL installation has an anonymous user, allowing anyone"
+echo "to log into MySQL without having to have a user account created for"
+echo "them. This is intended only for testing, and to make the installation"
+echo "go a bit smoother. You should remove them before moving into a"
+echo "production environment."
+echo
+
+echo -n "Remove anonymous users? [Y/n] "
+
+read reply
+if [ "$reply" = "n" ]; then
+ echo " ... skipping."
+else
+ remove_anonymous_users
+fi
+echo
+
+
+#
+# Disallow remote root login
+#
+
+echo "Normally, root should only be allowed to connect from 'localhost'. This"
+echo "ensures that someone cannot guess at the root password from the network."
+echo
+
+echo -n "Disallow root login remotely? [Y/n] "
+read reply
+if [ "$reply" = "n" ]; then
+ echo " ... skipping."
+else
+ remove_remote_root
+fi
+echo
+
+
+#
+# Remove test database
+#
+
+echo "By default, MySQL comes with a database named 'test' that anyone can"
+echo "access. This is also intended only for testing, and should be removed"
+echo "before moving into a production environment."
+echo
+
+echo -n "Remove test database and access to it? [Y/n] "
+read reply
+if [ "$reply" = "n" ]; then
+ echo " ... skipping."
+else
+ remove_test_database
+fi
+echo
+
+
+#
+# Reload privilege tables
+#
+
+echo "Reloading the privilege tables will ensure that all changes made so far"
+echo "will take effect immediately."
+echo
+
+echo -n "Reload privilege tables now? [Y/n] "
+read reply
+if [ "$reply" = "n" ]; then
+ echo " ... skipping."
+else
+ reload_privilege_tables
+fi
+echo
+
+cleanup
+
+echo
+echo
+echo
+echo "All done! If you've completed all of the above steps, your MySQL"
+echo "installation should now be secure."
+echo
+echo "Thanks for using MySQL!"
+echo
+echo
+
+
diff --git a/scripts/mysql_tableinfo.sh b/scripts/mysql_tableinfo.sh
new file mode 100644
index 00000000000..bfe9be377c7
--- /dev/null
+++ b/scripts/mysql_tableinfo.sh
@@ -0,0 +1,478 @@
+#!@PERL@ -w
+
+use strict;
+use Getopt::Long;
+use DBI;
+
+=head1 NAME
+
+mysql_tableinfo - creates and populates information tables with
+the output of SHOW DATABASES, SHOW TABLES (or SHOW TABLE STATUS),
+SHOW COLUMNS and SHOW INDEX.
+
+This is version 1.0.
+
+=head1 SYNOPSIS
+
+ mysql_tableinfo [OPTIONS] database_to_write [database_like_wild] [table_like_wild]
+
+ Do not backquote (``) database_to_write,
+ and do not quote ('') database_like_wild or table_like_wild
+
+ Examples:
+
+ mysql_tableinfo info
+
+ mysql_tableinfo info this_db
+
+ mysql_tableinfo info %a% b%
+
+ mysql_tableinfo info --clear-only
+
+ mysql_tableinfo info --col --idx --table-status
+
+=cut
+
+# Documentation continued at end of file
+
+
+sub usage {
+ die @_,"\nExecute 'perldoc $0' for documentation\n";
+}
+
+my %opt = (
+ 'user' => scalar getpwuid($>),
+ 'host' => "localhost",
+ 'prefix' => "", #to avoid 'use of uninitialized value...'
+);
+Getopt::Long::Configure(qw(no_ignore_case)); # disambuguate -p and -P
+GetOptions( \%opt,
+ "help",
+ "user|u=s",
+ "password|p=s",
+ "host|h=s",
+ "port|P=s",
+ "socket|S=s",
+ "tbl-status",
+ "col",
+ "idx",
+ "clear",
+ "clear-only",
+ "prefix=s",
+ "quiet|q",
+) or usage("Invalid option");
+
+if ($opt{help}) {usage();}
+
+my ($db_to_write,$db_like_wild,$tbl_like_wild);
+if (@ARGV==0)
+{
+ usage("Not enough arguments");
+}
+$db_to_write="`$ARGV[0]`"; shift @ARGV;
+$db_like_wild=($ARGV[0])?$ARGV[0]:"%"; shift @ARGV;
+$tbl_like_wild=($ARGV[0])?$ARGV[0]:"%"; shift @ARGV;
+if (@ARGV>0) { usage("Too many arguments"); }
+
+my $info_db="`".$opt{'prefix'}."db`";
+my $info_tbl="`".$opt{'prefix'}."tbl".
+ (($opt{'tbl-status'})?"_status":"")."`";
+my $info_col="`".$opt{'prefix'}."col`";
+my $info_idx="`".$opt{'prefix'}."idx`";
+
+
+# --- connect to the database ---
+
+my $dsn = ";host=$opt{'host'}";
+$dsn .= ";port=$opt{port}" if $opt{port};
+$dsn .= ";mysql_socket=$opt{socket}" if $opt{socket};
+
+my $dbh = DBI->connect("dbi:mysql:$dsn;mysql_read_default_group=perl",
+ $opt{user}, $opt{password},
+{
+ RaiseError => 1,
+ PrintError => 0,
+ AutoCommit => 1,
+});
+
+$db_like_wild=$dbh->quote($db_like_wild);
+$tbl_like_wild=$dbh->quote($tbl_like_wild);
+
+#Ask
+
+if (!$opt{'quiet'})
+{
+ print "\n!! This program is doing to do:\n\n";
+ print "**DROP** TABLE ...\n" if ($opt{'clear'} or $opt{'clear-only'});
+ print "**DELETE** FROM ... WHERE `Database LIKE $db_like_wild AND `Table` LIKE $tbl_like_wild
+**INSERT** INTO ...
+
+on the following tables :\n";
+ my $i;
+ foreach $i (($info_db, $info_tbl),
+ (($opt{'col'})?$info_col:()),
+ (($opt{'idx'})?$info_idx:()))
+ {
+ print(" $db_to_write.$i\n");
+ }
+ print "\nContinue (you can skip this confirmation step with --quiet) ? (y|n) [n]";
+ my $answer=<STDIN>;
+ unless ($answer =~ /^\s*y\s*$/i)
+ {
+ print "Nothing done!\n";exit;
+ }
+}
+
+if ($opt{'clear'} or $opt{'clear-only'})
+{
+#do not drop the $db_to_write database !
+ my $i;
+ foreach $i (($info_db, $info_tbl),
+ (($opt{'col'})?$info_col:()),
+ (($opt{'idx'})?$info_idx:()))
+ {
+ $dbh->do("DROP TABLE IF EXISTS $db_to_write.$i");
+ }
+ if ($opt{'clear-only'})
+ {
+ print "Wrote to database $db_to_write .\n" unless ($opt{'quiet'});
+ exit();
+ }
+}
+
+
+my %sth;
+my %extra_col_desc;
+my %row;
+my %done_create_table;
+
+#create the $db_to_write database
+$dbh->do("CREATE DATABASE IF NOT EXISTS $db_to_write");
+$dbh->do("USE $db_to_write");
+
+#get databases
+$sth{db}=$dbh->prepare("SHOW DATABASES LIKE $db_like_wild");
+$sth{db}->execute;
+
+#create $info_db which will receive info about databases.
+#Ensure that the first column to be called "Database" (as SHOW DATABASES LIKE
+#returns a varying
+#column name (of the form "Database (%...)") which is not suitable)
+$extra_col_desc{db}=do_create_table("db",$info_db,undef,"`Database`");
+#we'll remember the type of the `Database` column (as returned by
+#SHOW DATABASES), which we will need when creating the next tables.
+
+#clear out-of-date info from this table
+$dbh->do("DELETE FROM $info_db WHERE `Database` LIKE $db_like_wild");
+
+
+while (@{$row{db}}=$sth{db}->fetchrow_array) #go through all databases
+{
+
+#insert the database name
+ $dbh->do("INSERT INTO $info_db VALUES("
+ .join_quote(@{$row{db}}).")");
+
+#for each database, get tables
+
+ $sth{tbl}=$dbh->prepare("SHOW TABLE"
+ .( ($opt{'tbl-status'}) ?
+ " STATUS"
+ : "S" )
+ ." from `${$row{db}}[0]` LIKE $tbl_like_wild");
+ $sth{tbl}->execute;
+ unless ($done_create_table{$info_tbl})
+
+#tables must be created only once, and out-of-date info must be
+#cleared once
+ {
+ $done_create_table{$info_tbl}=1;
+ $extra_col_desc{table}=
+ do_create_table("tbl",$info_tbl,
+#add an extra column (database name) at the left
+#and ensure that the table name will be called "Table"
+#(this is unncessesary with
+#SHOW TABLE STATUS, but necessary with SHOW TABLES (which returns a column
+#named "Tables_in_..."))
+ "`Database` ".$extra_col_desc{db},"`Table`");
+ $dbh->do("DELETE FROM $info_tbl WHERE `Database` LIKE $db_like_wild AND `Table` LIKE $tbl_like_wild");
+ }
+
+ while (@{$row{tbl}}=$sth{tbl}->fetchrow_array)
+ {
+ $dbh->do("INSERT INTO $info_tbl VALUES("
+ .$dbh->quote(${$row{db}}[0]).",".join_quote(@{$row{tbl}}).")");
+
+#for each table, get columns...
+
+ if ($opt{'col'})
+ {
+ $sth{col}=$dbh->prepare("SHOW COLUMNS FROM `${$row{tbl}}[0]` FROM `${$row{db}}[0]`");
+ $sth{col}->execute;
+ unless ($done_create_table{$info_col})
+ {
+ $done_create_table{$info_col}=1;
+ do_create_table("col",$info_col,
+ "`Database` ".$extra_col_desc{db}.","
+ ."`Table` ".$extra_col_desc{table}.","
+ ."`Seq_in_table` BIGINT(3)");
+#We need to add a sequence number (1 for the first column of the table,
+#2 for the second etc) so that users are able to retrieve columns in order
+#if they want. This is not needed for INDEX
+#(where there is already Seq_in_index)
+ $dbh->do("DELETE FROM $info_col WHERE `Database`
+ LIKE $db_like_wild
+ AND `Table` LIKE $tbl_like_wild");
+ }
+ my $col_number=0;
+ while (@{$row{col}}=$sth{col}->fetchrow_array)
+ {
+ $dbh->do("INSERT INTO $info_col VALUES("
+ .$dbh->quote(${$row{db}}[0]).","
+ .$dbh->quote(${$row{tbl}}[0]).","
+ .++$col_number.","
+ .join_quote(@{$row{col}}).")");
+ }
+ }
+
+#and get index.
+
+ if ($opt{'idx'})
+ {
+ $sth{idx}=$dbh->prepare("SHOW INDEX FROM `${$row{tbl}}[0]` FROM `${$row{db}}[0]`");
+ $sth{idx}->execute;
+ unless ($done_create_table{$info_idx})
+ {
+ $done_create_table{$info_idx}=1;
+ do_create_table("idx",$info_idx,
+ "`Database` ".$extra_col_desc{db});
+ $dbh->do("DELETE FROM $info_idx WHERE `Database`
+ LIKE $db_like_wild
+ AND `Table` LIKE $tbl_like_wild");
+ }
+ while (@{$row{idx}}=$sth{idx}->fetchrow_array)
+ {
+ $dbh->do("INSERT INTO $info_idx VALUES("
+ .$dbh->quote(${$row{db}}[0]).","
+ .join_quote(@{$row{idx}}).")");
+ }
+ }
+ }
+}
+
+print "Wrote to database $db_to_write .\n" unless ($opt{'quiet'});
+exit;
+
+sub join_quote
+{
+ my (@list)=@_; my $i;
+ foreach $i (@list) { $i=$dbh->quote($i); }
+ return (join ',',@list);
+}
+
+sub do_create_table
+{
+ my ($sth_key,$target_tbl,$extra_col_desc,$first_col_name)=@_;
+ my $create_table_query=$extra_col_desc;
+ my ($i,$type,$first_col_desc,$col_desc);
+
+ for ($i=0;$i<$sth{$sth_key}->{NUM_OF_FIELDS};$i++)
+ {
+ if ($create_table_query) { $create_table_query.=", "; }
+ $type=$sth{$sth_key}->{mysql_type_name}->[$i];
+ $col_desc=$type;
+ if ($type =~ /char|int/i)
+ {
+ $col_desc.="($sth{$sth_key}->{PRECISION}->[$i])";
+ }
+ elsif ($type =~ /decimal|numeric/i) #(never seen that)
+ {
+ $col_desc.=
+ "($sth{$sth_key}->{PRECISION}->[$i],$sth{$sth_key}->{SCALE}->[$i])";
+ }
+ elsif ($type !~ /date/i) #date and datetime are OK,
+ #no precision or scale for them
+ {
+ warn "unexpected column type '$type'
+(neither 'char','int','decimal|numeric')
+when creating $target_tbl, hope table creation will go OK\n";
+ }
+ if ($i==0) {$first_col_desc=$col_desc};
+ $create_table_query.=
+ ( ($i==0 and $first_col_name) ?
+ "$first_col_name " :"`$sth{$sth_key}->{NAME}->[$i]` " )
+ .$col_desc;
+ }
+if ($create_table_query)
+{
+ $dbh->do("CREATE TABLE IF NOT EXISTS $target_tbl ($create_table_query)");
+}
+return $first_col_desc;
+}
+
+__END__
+
+
+=head1 DESCRIPTION
+
+mysql_tableinfo asks a MySQL server information about its
+databases, tables, table columns and index, and stores this
+in tables called `db`, `tbl` (or `tbl_status`), `col`, `idx`
+(with an optional prefix specified with --prefix).
+After that, you can query these information tables, for example
+to build your admin scripts with SQL queries, like
+
+SELECT CONCAT("CHECK TABLE ",`database`,".",`table`," EXTENDED;")
+FROM info.tbl WHERE ... ;
+
+as people usually do with some other RDBMS
+(note: to increase the speed of your queries on the info tables,
+you may add some index on them).
+
+The database_like_wild and table_like_wild instructs the program
+to gather information only about databases and tables
+whose names match these patterns. If the info
+tables already exist, their rows matching the patterns are simply
+deleted and replaced by the new ones. That is,
+old rows not matching the patterns are not touched.
+If the database_like_wild and table_like_wild arguments
+are not specified on the command-line they default to "%".
+
+The program :
+
+- does CREATE DATABASE IF NOT EXISTS database_to_write
+where database_to_write is the database name specified on the command-line.
+
+- does CREATE TABLE IF NOT EXISTS database_to_write.`db`
+
+- fills database_to_write.`db` with the output of
+SHOW DATABASES LIKE database_like_wild
+
+- does CREATE TABLE IF NOT EXISTS database_to_write.`tbl`
+(respectively database_to_write.`tbl_status`
+if the --tbl-status option is on)
+
+- for every found database,
+fills database_to_write.`tbl` (respectively database_to_write.`tbl_status`)
+with the output of
+SHOW TABLES FROM found_db LIKE table_like_wild
+(respectively SHOW TABLE STATUS FROM found_db LIKE table_like_wild)
+
+- if the --col option is on,
+ * does CREATE TABLE IF NOT EXISTS database_to_write.`col`
+ * for every found table,
+ fills database_to_write.`col` with the output of
+ SHOW COLUMNS FROM found_tbl FROM found_db
+
+- if the --idx option is on,
+ * does CREATE TABLE IF NOT EXISTS database_to_write.`idx`
+ * for every found table,
+ fills database_to_write.`idx` with the output of
+ SHOW INDEX FROM found_tbl FROM found_db
+
+Some options may modify this general scheme (see below).
+
+As mentioned, the contents of the info tables are the output of
+SHOW commands. In fact the contents are slightly more complete :
+
+- the `tbl` (or `tbl_status`) info table
+ has an extra column which contains the database name,
+
+- the `col` info table
+ has an extra column which contains the table name,
+ and an extra column which contains, for each described column,
+ the number of this column in the table owning it (this extra column
+ is called `Seq_in_table`). `Seq_in_table` makes it possible for you
+ to retrieve your columns in sorted order, when you are querying
+ the `col` table.
+
+- the `index` info table
+ has an extra column which contains the database name.
+
+Caution: info tables contain certain columns (e.g.
+Database, Table, Null...) whose names, as they are MySQL reserved words,
+need to be backquoted (`...`) when used in SQL statements.
+
+=head1 OPTIONS
+
+=over 4
+
+=item --clear
+
+Does DROP TABLE on the info tables (only those that the program is
+going to fill, for example if you do not use --col it won't drop
+the `col` table) and processes normally. Does not drop database_to_write.
+
+=item --clear-only
+
+Same as --clear but exits after the DROPs.
+
+=item --col
+
+Adds columns information (into table `col`).
+
+=item --idx
+
+Adds index information (into table `idx`).
+
+=item --prefix prefix
+
+The info tables are named from the concatenation of prefix and,
+respectively, db, tbl (or tbl_status), col, idx. Do not quote ('')
+or backquote (``) prefix.
+
+=item -q, --quiet
+
+Does not warn you about what the script is going to do (DROP TABLE etc)
+and does not ask for a confirmation before starting.
+
+=item --tbl-status
+
+Instead of using SHOW TABLES, uses SHOW TABLE STATUS
+(much more complete information, but slower).
+
+=item --help
+
+Display helpscreen and exit
+
+=item -u, --user=#
+
+user for database login if not current user. Give a user
+who has sufficient privileges (CREATE, ...).
+
+=item -p, --password=#
+
+password to use when connecting to server
+
+=item -h, --host=#
+
+host to connect to
+
+=item -P, --port=#
+
+port to use when connecting to server
+
+=item -S, --socket=#
+
+UNIX domain socket to use when connecting to server
+
+=head1 WARRANTY
+
+This software is free and comes without warranty of any kind. You
+should never trust backup software without studying the code yourself.
+Study the code inside this script and only rely on it if I<you> believe
+that it does the right thing for you.
+
+Patches adding bug fixes, documentation and new features are welcome.
+
+=head1 TO DO
+
+Use extended inserts to be faster (for servers with many databases
+or tables). But to do that, must care about net-buffer-length.
+
+=head1 AUTHOR
+
+2002-06-18 Guilhem Bichot (guilhem.bichot@mines-paris.org)
+
+And all the authors of mysqlhotcopy, which served as a model for
+the structure of the program.
diff --git a/scripts/mysql_zap.sh b/scripts/mysql_zap.sh
index 312d15e34d6..f485d164282 100644
--- a/scripts/mysql_zap.sh
+++ b/scripts/mysql_zap.sh
@@ -12,7 +12,7 @@ $opt_f= 0;
$opt_t= 0;
$opt_a = "";
-$BSD = -f '/vmunix' || $ENV{"OS"} eq "SunOS4";
+$BSD = -f '/vmunix' || $ENV{"OS"} eq "SunOS4" || $^O eq 'darwin';
$LINUX = $^O eq 'linux';
$pscmd = $BSD ? "/bin/ps -auxww" : $LINUX ? "/bin/ps axuw" : "/bin/ps -ef";
diff --git a/scripts/mysqld_multi.sh b/scripts/mysqld_multi.sh
index 1adaa458271..b868006ee40 100644
--- a/scripts/mysqld_multi.sh
+++ b/scripts/mysqld_multi.sh
@@ -4,7 +4,7 @@ use Getopt::Long;
use POSIX qw(strftime);
$|=1;
-$VER="2.2";
+$VER="2.4";
$opt_config_file = undef();
$opt_example = 0;
@@ -183,7 +183,7 @@ sub report_mysqlds
sub start_mysqlds()
{
- my (@groups, $com, $i, @options, $j);
+ my (@groups, $com, $tmp, $i, @options, $j);
if (!$opt_no_log)
{
@@ -202,11 +202,20 @@ sub start_mysqlds()
@options = `$com`;
chop @options;
- $com = "$mysqld";
- for ($j = 0; defined($options[$j]); $j++)
+ $com= "$mysqld";
+ for ($j = 0, $tmp= ""; defined($options[$j]); $j++)
{
- $com.= " $options[$j]";
+ if ("--mysqld=" eq substr($options[$j], 0, 9))
+ {
+ $options[$j]=~ s/\-\-mysqld\=//;
+ $com= $options[$j];
+ }
+ else
+ {
+ $tmp.= " $options[$j]";
+ }
}
+ $com.= $tmp;
$com.= " >> $opt_log 2>&1" if (!$opt_no_log);
$com.= " &";
system($com);
@@ -457,12 +466,12 @@ sub example
# directory, that you have (just change the socket, -S=...)
# See more detailed information from chapter:
# '6 The MySQL Access Privilege System' from the MySQL manual.
-# 2.pid-file is very important, if you are using safe_mysqld to start mysqld
-# (e.g. --mysqld=safe_mysqld) Every mysqld should have it's own pid-file.
-# The advantage using safe_mysqld instead of mysqld directly here is, that
-# safe_mysqld 'guards' every mysqld process and will restart it, if mysqld
+# 2.pid-file is very important, if you are using mysqld_safe to start mysqld
+# (e.g. --mysqld=mysqld_safe) Every mysqld should have it's own pid-file.
+# The advantage using mysqld_safe instead of mysqld directly here is, that
+# mysqld_safe 'guards' every mysqld process and will restart it, if mysqld
# process fails due to signal kill -9, or similar. (Like segmentation fault,
-# which MySQL should never do, of course ;) Please note that safe_mysqld
+# which MySQL should never do, of course ;) Please note that mysqld_safe
# script may require that you start it from a certain place. This means that
# you may have to CD to a certain directory, before you start the
# mysqld_multi. If you have problems starting, please see the script.
@@ -497,10 +506,10 @@ sub example
# give you extra performance in a threaded system!
#
[mysqld_multi]
-mysqld = @bindir@/safe_mysqld
+mysqld = @bindir@/mysqld_safe
mysqladmin = @bindir@/mysqladmin
-user = multi_admin
-password = multipass
+user = root
+password = your_password
[mysqld2]
socket = /tmp/mysql.sock2
@@ -591,10 +600,16 @@ Options:
Using: $opt_log
--mysqladmin=... mysqladmin binary to be used for a server shutdown.
Using: $mysqladmin
---mysqld=... mysqld binary to be used. Note that you can give safe_mysqld
+--mysqld=... mysqld binary to be used. Note that you can give mysqld_safe
to this option also. The options are passed to mysqld. Just
- make sure you have mysqld in your PATH or fix safe_mysqld.
+ make sure you have mysqld in your PATH or fix mysqld_safe.
Using: $mysqld
+ Please note: Since mysqld_multi version 2.3 you can also
+ give this option inside groups [mysqld#] in ~/.my.cnf,
+ where '#' stands for an integer (number) of the group in
+ question. This will be recognized as a special option and
+ will not be passed to the mysqld. This will allow one to
+ start different mysqld versions with mysqld_multi.
--no-log Print to stdout instead of the log file. By default the log
file is turned on.
--password=... Password for user for mysqladmin.
diff --git a/scripts/safe_mysqld-watch.sh b/scripts/mysqld_safe-watch.sh
index 30f95fd7a86..c59b3b2614d 100644
--- a/scripts/safe_mysqld-watch.sh
+++ b/scripts/mysqld_safe-watch.sh
@@ -8,7 +8,7 @@
# binary installation that has other paths than you are using.
#
# mysql.server works by first doing a cd to the base directory and from there
-# executing safe_mysqld
+# executing mysqld_safe
# Check if we are starting this relative (for the binary release)
if test -f ./data/mysql/db.frm -a -f ./share/mysql/english/errmsg.sys -a \
diff --git a/scripts/safe_mysqld.sh b/scripts/mysqld_safe.sh
index 2b625dbdfa3..9dea2eb3935 100644
--- a/scripts/safe_mysqld.sh
+++ b/scripts/mysqld_safe.sh
@@ -8,7 +8,7 @@
# binary installation that has other paths than you are using.
#
# mysql.server works by first doing a cd to the base directory and from there
-# executing safe_mysqld
+# executing mysqld_safe
trap '' 1 2 3 15 # we shouldn't let anyone kill us
@@ -23,32 +23,37 @@ parse_arguments() {
# We only need to pass arguments through to the server if we don't
# handle them here. So, we collect unrecognized options (passed on
# the command line) into the args variable.
- pick_args=$1; shift
+ pick_args=
+ if test "$1" = PICK-ARGS-FROM-ARGV
+ then
+ pick_args=1
+ shift
+ fi
for arg do
case "$arg" in
# these get passed explicitly to mysqld
- --basedir=*) MY_BASEDIR_VERSION=`echo "$arg" | sed -e "s;--[^=]*=;;"` ;;
- --datadir=*) DATADIR=`echo "$arg" | sed -e "s;--[^=]*=;;"` ;;
- --pid-file=*) pid_file=`echo "$arg" | sed -e "s;--[^=]*=;;"` ;;
+ --basedir=*) MY_BASEDIR_VERSION=`echo "$arg" | sed -e "s;--basedir=;;"` ;;
+ --datadir=*) DATADIR=`echo "$arg" | sed -e "s;--datadir=;;"` ;;
+ --pid-file=*) pid_file=`echo "$arg" | sed -e "s;--pid-file=;;"` ;;
--user=*) user=`echo "$arg" | sed -e "s;--[^=]*=;;"` ; SET_USER=1 ;;
- # these two might have been set in a [safe_mysqld] section of my.cnf
- # they get passed via environment variables to safe_mysqld
- --socket=*) MYSQL_UNIX_PORT=`echo "$arg" | sed -e "s;--[^=]*=;;"` ;;
- --port=*) MYSQL_TCP_PORT=`echo "$arg" | sed -e "s;--[^=]*=;;"` ;;
+ # these two might have been set in a [mysqld_safe] section of my.cnf
+ # they get passed via environment variables to mysqld_safe
+ --socket=*) MYSQL_UNIX_PORT=`echo "$arg" | sed -e "s;--socket=;;"` ;;
+ --port=*) MYSQL_TCP_PORT=`echo "$arg" | sed -e "s;--port=;;"` ;;
- # safe_mysqld-specific options
- --ledir=*) ledir=`echo "$arg" | sed -e "s;--[^=]*=;;"` ;;
- --err-log=*) err_log=`echo "$arg" | sed -e "s;--[^=]*=;;"` ;;
+ # mysqld_safe-specific options - must be set in my.cnf ([mysqld_safe])!
+ --ledir=*) ledir=`echo "$arg" | sed -e "s;--ledir=;;"` ;;
+ --err-log=*) err_log=`echo "$arg" | sed -e "s;--err-log=;;"` ;;
# QQ The --open-files should be removed
- --open-files=*) open_files=`echo "$arg" | sed -e "s;--[^=]*=;;"` ;;
- --open-files-limit=*) open_files=`echo "$arg" | sed -e "s;--[^=]*=;;"` ;;
- --core-file-size=*) core_file_size=`echo "$arg" | sed -e "s;--[^=]*=;;"` ;;
- --timezone=*) TZ=`echo "$arg" | sed -e "s;--[^=]*=;;"` ; export TZ; ;;
- --mysqld=*) MYSQLD=`echo "$arg" | sed -e "s;--[^=]*=;;"` ;;
+ --open-files=*) open_files=`echo "$arg" | sed -e "s;--open-files=;;"` ;;
+ --open-files-limit=*) open_files=`echo "$arg" | sed -e "s;--open-files-limit=;;"` ;;
+ --core-file-size=*) core_file_size=`echo "$arg" | sed -e "s;--core_file_size=;;"` ;;
+ --timezone=*) TZ=`echo "$arg" | sed -e "s;--timezone=;;"` ; export TZ; ;;
+ --mysqld=*) MYSQLD=`echo "$arg" | sed -e "s;--mysqld=;;"` ;;
--mysqld-version=*)
- tmp=`echo "$arg" | sed -e "s;--[^=]*=;;"`
+ tmp=`echo "$arg" | sed -e "s;--mysqld-version=;;"`
if test -n "$tmp"
then
MYSQLD="mysqld-$tmp"
@@ -57,7 +62,7 @@ parse_arguments() {
fi
;;
*)
- if test $pick_args -eq 1
+ if test -n "$pick_args"
then
# This sed command makes sure that any special chars are quoted,
# so the arg gets passed exactly to the server.
@@ -110,7 +115,7 @@ pid_file=
err_log=
SET_USER=0
-# Get first arguments from the my.cnf file, groups [mysqld] and [safe_mysqld]
+# Get first arguments from the my.cnf file, groups [mysqld] and [mysqld_safe]
# and then merge with the command line arguments
if test -x ./bin/my_print_defaults
then
@@ -126,15 +131,15 @@ else
fi
args=
-parse_arguments 0 `$print_defaults $defaults mysqld server safe_mysqld`
-parse_arguments 1 "$@"
+parse_arguments `$print_defaults $defaults mysqld server mysqld_safe safe_mysqld`
+parse_arguments PICK-ARGS-FROM-ARGV "$@"
if test ! -x $ledir/$MYSQLD
then
echo "The file $ledir/$MYSQLD doesn't exist or is not executable"
echo "Please do a cd to the mysql installation directory and restart"
echo "this script from there as follows:"
- echo "./bin/safe_mysqld".
+ echo "./bin/mysqld_safe".
exit 1
fi
@@ -154,15 +159,48 @@ export MYSQL_TCP_PORT
NOHUP_NICENESS="nohup"
-if test -w /
+
+# Using nice with no args to get the niceness level is GNU-specific.
+# This check could be extended for other operating systems (e.g.,
+# BSD could use "nohup sh -c 'ps -o nice -p $$' | tail -1").
+# But, it also seems that GNU nohup is the only one which messes
+# with the priority, so this is okay.
+if nohup nice > /dev/null 2>&1
then
- NOHUP_NICENESS=`nohup nice 2>&1`
- if test $? -eq 0 && test x"$NOHUP_NICENESS" != x0 && nice --1 echo foo > /dev/null 2>&1
- then
- NOHUP_NICENESS="nice --$NOHUP_NICENESS nohup"
- else
- NOHUP_NICENESS="nohup"
- fi
+ normal_niceness=`nice`
+ nohup_niceness=`nohup nice`
+
+ numeric_nice_values=1
+ for val in $normal_niceness $nohup_niceness
+ do
+ case "$val" in
+ -[0-9] | -[0-9][0-9] | -[0-9][0-9][0-9] | \
+ [0-9] | [0-9][0-9] | [0-9][0-9][0-9] )
+ ;;
+ * )
+ numeric_nice_values=0 ;;
+ esac
+ done
+
+ if test $numeric_nice_values -eq 1
+ then
+ nice_value_diff=`expr $nohup_niceness - $normal_niceness`
+ if test $? -eq 0 && test $nice_value_diff -gt 0 && \
+ nice --$nice_value_diff echo testing > /dev/null 2>&1
+ then
+ # nohup increases the priority (bad), and we are permitted
+ # to lower the priority
+ NOHUP_NICENESS="nice --$nice_value_diff nohup"
+ fi
+ fi
+else
+ if nohup echo testing > /dev/null 2>&1
+ then
+ :
+ else
+ # nohup doesn't work on this system
+ NOHUP_NICENESS=""
+ fi
fi
USER_OPTION=""