如何从 shell 脚本执行 MySQL 命令?

如何通过 shell 脚本执行 SQL 命令,使其自动化?

我想使用 shell 脚本恢复在 SQL 文件中收集的数据。我要连接到服务器并恢复数据。当通过 SSH 命令行单独执行时,该命令可以工作。

这是我使用的命令:

mysql -h "server-name" -u root "password" "database-name" < "filename.sql"

这是创建文件 ds_fbids.sql并将其导入 mysql 的 shell 脚本代码。

perl fb_apps_frm_fb.pl
perl fb_new_spider.pl ds_fbids.txt ds_fbids.sql
mysql -h dbservername -u username -ppassword dbname < ds_fbids.sql

做这件事的正确方法是什么?

381835 次浏览

您需要使用 -p标志来发送密码。这很棘手,因为在 -p和密码之间必须没有空格。

$ mysql -h "server-name" -u "root" "-pXXXXXXXX" "database-name" < "filename.sql"

如果你在 -p之后使用一个空格,它会让 mysql 客户端交互式地提示你输入密码,然后它将下一个命令参数解释为 database-name:

$ mysql -h "server-name" -u "root" -p "XXXXXXXX" "database-name" < "filename.sql"
Enter password: <you type it in here>
ERROR 1049 (42000): Unknown database 'XXXXXXXX'

实际上,我更喜欢将用户和密码存储在 ~/中。所以我根本不需要把它放在命令行上:

[client]
user = root
password = XXXXXXXX

然后:

$ mysql -h "server-name" "database-name" < "filename.sql"

回复你的评论:

我一直在命令行和 shell 脚本中运行上面这样的批处理模式 mysql 命令。很难诊断 shell 脚本出了什么问题,因为您没有共享确切的脚本或任何错误输出。我建议你编辑上面的原始问题,并提供出错的例子。

另外,当我对 shell 脚本进行故障排除时,我会使用 -x标志,这样我就可以看到它是如何执行每个命令的:

$ bash -x myscript.sh

如前所述,可以使用-p 将密码传递给服务器。

但我建议这样做:

mysql -h "hostaddress" -u "username" -p "database-name" < "sqlfile.sql"

注意,密码不在那里。然后它会提示您输入密码。然后我会把它打出来。这样您的密码就不会登录到服务器命令行历史记录中。

这是基本的安全措施。

如果不考虑安全性,我只是暂时从数据库用户中删除密码。然后在导入-重新添加它。

这样,任何其他帐户,您可能有共享相同的密码将不会被破坏。

在您的 shell 脚本中,您似乎没有等待/检查您试图导入的文件是否确实存在。Perl 脚本可能还没有完成。

你忘记了 -p或者 --password=(后者更易读) :

mysql -h "$server_name" "--user=$user" "--password=$password" "--database=$database_name" < "filename.sql"

(如果您确定您的凭据/名称不包含空格或 shell 特殊字符,则引号是不必要的。)

请注意,manpage 也表示在命令行上提供凭据是不安全的。因此,请遵循比尔关于 my.cnf 的建议。

以前的答案都很棒。如果您希望运行一个简单的 sql 命令,也可以使用-e 选项。

mysql -h <host> -u<user> -p<password> database -e \
"SELECT * FROM blah WHERE foo='bar';"

使用以下语法:

mysql -u $user -p$passsword -Bse "command1;command2;....;commandn"
mysql -h "hostname" -u usr_name -pPASSWD "db_name" < sql_script_file

(如有需要,使用 sql_script_file的完整路径)

如果要将输出重定向到文件

mysql -h "hostname" -u usr_name -pPASSWD "db_name" < sql_script_file > out_file

如何执行 SQL 脚本,请使用以下语法:

mysql --host= localhost --user=root --password=xxxxxx  -e "source dbscript.sql"

如果你使用 host 作为 localhost,你不需要提到它,你可以这样做:

mysql --user=root --password=xxxxxx  -e "source dbscript.sql"

这对 Windows 和 Linux 应该有效。

如果密码内容包含一个 !(叹号) ,你应该在它的前面加上一个 \(反斜杠)。

mysql_config_editor set --login-path=storedPasswordKey --host=localhost --user=root --password

如何使用安全密码执行命令行? 使用配置编辑器! ! !

在 mysql 5.6.6中,您可以将密码存储在一个配置文件中,然后执行如下的 cli 命令..。

mysql --login-path=storedPasswordKey ....

--登录路径替换变量... ... 主机、用户和密码!

这个问题的核心已经被回答过好几次了,我只是觉得我应该补充一下,反勾在 shell 脚本和 SQL 中都有用。如果需要在 SQL 中使用它们来指定表或数据库名称,则需要在 shell 脚本中转义它们,如下所示:

mysql -p=password -u "root" -Bse "CREATE DATABASE \`${1}_database\`;
CREATE USER '$1'@'%' IDENTIFIED BY '$2';
GRANT ALL PRIVILEGES ON `${1}_database`.* TO '$1'@'%' WITH GRANT OPTION;"

当然,除非你信任用户输入,否则不应该通过连接的用户输入(传递的参数)来生成 SQL。如果把它放到另一个支持参数/正确转义字符串以插入到 MySQL 的脚本语言中,会安全得多。

#!/bin/sh
#Procedures = update
#Scheduled at : Every 00.05


v_path=/etc/database_jobs
v_cnt=0


MAILTO="indd@abc.in joanson@abc.in sturt@abc.in"
touch "$v_path/db_db_log.log"


#test
mysql -uusername -ppassword -h111.111.111.111 db_name -e "CALL functionName()" > $v_path/db_db_log.log 2>&1
if [ "$?" -eq 0 ]
then
v_cnt=`expr $v_cnt + 1`
mail -s "db Attendance Update has been run successfully" $MAILTO < $v_path/db_db_log.log
else
mail -s "Alert : db Attendance Update has been failed" $MAILTO < $v_path/db_db_log.log
exit
fi

从 cron 中使用的 shell 脚本访问 mysql 的一个重要考虑是 mysql 查看登录的用户以确定。要加载 my.cnf。

这对 cron 不起作用。如果您使用 su/sudo 作为登录用户可能不是您正在运行的用户,那么这也会造成混淆。

我会这样说:

mysql --defaults-extra-file=/path/to/specific/.my.cnf -e 'SELECT something FROM sometable'

只需要确保在. my.cnf 文件上适当和严格地设置用户和组的所有权和权限。

使用

echo "your sql script;" | mysql -u -p -h db_name

为了“自动化”导入生成的 .sql文件的过程,同时避免在尝试通过 stdinstdout传递文件时可能隐藏的所有陷阱,只需告诉 MySQL 使用 MySQL 中的 SOURCE命令执行生成的 .sql文件。

简短但优秀的 回答语法从 Kshitij Sood开始,给出了最好的起点。简而言之,根据 Kshitij Sood 的语法修改 OP 的命令,并用 SOURCE命令替换其中的命令:

#!/bin/bash
mysql -u$user -p$password $dbname -Bse "SOURCE ds_fbids.sql
SOURCE ds_fbidx.sql"

如果生成的 .sql文件中包含数据库名称,则可以从命令中删除该名称。

这里的假设是,生成的文件是 有效,它本身是一个 .sql文件。由于没有重定向文件、管道文件或 shell 以任何其他方式处理文件,因此不需要因为 shell 而转义生成的输出中的任何字符。当然,关于 .sql文件中需要转义的内容的规则仍然适用。

如何处理命令行密码周围的安全问题,或者在 my.cnf文件中等等,已经在其他答案中得到了很好的解决,并提出了一些很好的建议。我的 最喜欢的答案,从 丹尼,涵盖了这一点,包括如何处理的问题时,与 cron的工作,或任何其他。


解答 评论(问题?)关于我提到的简短答案: 不,它不能与 HEREDOC 语法一起使用,因为已经给出了 shell 命令。HEREDOC 可以在 重定向版本语法中使用(没有 -Bse选项) ,因为 I/O 重定向是 HEREDOC 构建的基础。如果你需要 HEREDOC 的功能,最好使用它来创建一个 .sql文件,即使它是一个临时文件,并使用该文件作为“命令”来执行 MySQL 批处理行。

#!/bin/bash
cat >temp.sql <<SQL_STATEMENTS
...
SELECT \`column_name\` FROM \`table_name\` WHERE \`column_name\`='$shell_variable';
...
SQL_STATEMENTS
mysql -u $user -p$password $db_name -Be "SOURCE temp.sql"
rm -f temp.sql

请记住,由于 shell 扩展,您可以在 HEREDOC 中使用 shell 和环境变量。缺点是你必须逃避 每一个回勾。MySQL 使用它们作为标识符的分隔符,但是首先获取字符串的 shell 使用它们作为可执行命令的分隔符。只要在 MySQL 命令的一个反勾上错过转义,整个过程就会出现错误。整个问题可以通过对 HEREDOC 使用一个带引号的 LimitString 来解决:

#!/bin/bash
cat >temp.sql <<'SQL_STATEMENTS'
...
SELECT `column_name` FROM `table_name` WHERE `column_name`='constant_value';
...
SQL_STATEMENTS
mysql -u $user -p$password $db_name -Be "SOURCE temp.sql"
rm -f temp.sql

以这种方式删除 shell 扩展,就不需要转义反勾和其他 shell 特殊字符。它还取消了在其中使用 shell 和环境变量的能力。这几乎消除了一开始在 shell 脚本中使用 HEREDOC 的好处。

另一种选择是使用 Bash 中允许的带引号的多行字符串和批处理语法版本(使用 -Bse)。我不知道其他贝壳,所以我不能说它们是否也在那里工作。无论如何,对于使用 SOURCE命令执行多个 .sql文件,您都需要使用这个函数,因为与其他 MySQL 命令一样,没有也是以 ;结束的,而且每行只允许执行一个 .sql文件。多行字符串可以是单引号或双引号,对 shell 扩展有正常影响。它还有与使用 HEREDOC 语法处理反勾等相同的注意事项。

一个可能更好的解决方案是使用脚本语言、 Perl、 Python 等来创建 .sql文件,就像 OP 所做的那样,使用顶部的简单命令语法创建 SOURCE文件。脚本语言在字符串操作方面比 shell 要好得多,而且大多数脚本语言都有内置过程来处理处理 MySQL 时所需的引用和转义。

我已经编写了一个 shell 脚本,它将从属性文件读取数据,然后在 shell 脚本上运行 mysql 脚本。分享这些可能会对其他人有帮助。

#!/bin/bash
PROPERTY_FILE=filename.properties


function getProperty {
PROP_KEY=$1
PROP_VALUE=`cat $PROPERTY_FILE | grep "$PROP_KEY" | cut -d'=' -f2`
echo $PROP_VALUE
}


echo "# Reading property from $PROPERTY_FILE"
DB_USER=$(getProperty "db.username")
DB_PASS=$(getProperty "db.password")
ROOT_LOC=$(getProperty "root.location")
echo $DB_USER
echo $DB_PASS
echo $ROOT_LOC
echo "Writing on DB ... "
mysql -u$DB_USER -p$DB_PASS dbname<<EOFMYSQL


update tablename set tablename.value_ = "$ROOT_LOC" where tablename.name_="Root directory location";
EOFMYSQL
echo "Writing root location($ROOT_LOC) is done ... "
counter=`mysql -u${DB_USER} -p${DB_PASS} dbname -e "select count(*) from tablename where tablename.name_='Root directory location' and tablename.value_ = '$ROOT_LOC';" | grep -v "count"`;


if [ "$counter" = "1" ]
then
echo "ROOT location updated"
fi

Shell 脚本中自动化 密码 mysql

通过 shell 连接 mysql 的代码

#!/bin/bash
sudo mysql -u root -p "--password=pass"

或者

另外连接,显示值一个表

        #!/bin/bash
sudo mysql -u root -p "--password=4310260985" "database"
-e "select * from table order by id desc;"

提示: E = = = = = = > 你可以得到这个 BSE

要使用脚本 shell 从终端获取输入并将其发送到 mysql, 用 shell 脚本或 bash 脚本编写此命令。

echo "Creating MySQL user and database"


echo "What is your DB_NAME?"


read db_name


echo "What is your DB_PASS?"


read db_pass


echo "What is your DB_HOST?"


read db_host


echo "What is your USER_NAME?"


read user_name


echo "What is your USER_PASS?"


read user_pass


mysql -u$db_name -p$db_pass -h$db_host -e "CREATE USER '$user_name'@'%' IDENTIFIED BY '$user_pass';GRANT SELECT ON *.* TO '$user_name'@'%';"


echo "YOU HAVE SUCCESSFULLY CREATED A USER $user_name WITH PASSWORD $user_pass"