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


131

如何通过外壳程序脚本执行SQL命令,以便使其自动化?

我想使用外壳程序脚本恢复在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

正确的方法是什么?

Answers:


176

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

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

如果在空格之后-p使mysql客户端以交互方式提示您输入密码,然后将下一个命令参数解释为数据库名称,则使用空格:

$ 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'

实际上,我更喜欢将用户名和密码存储在〜/ .my.cnf中,因此根本不必将其放在命令行中:

[client]
user = root
password = XXXXXXXX

然后:

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

发表您的评论:

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

另外,在对shell脚本进行故障排除时,我使用该-x标志,以便查看其如何执行每个命令:

$ bash -x myscript.sh

感谢您的快速回复。通过将密码放在命令行本身中,我感到很累。真正的问题是我将此命令放在.sh文件中,然后执行此Shell脚本。文件中的命令不是在命令行上执行的,但是当我仅在命令行上执行命令时,相同的命令可以很好地工作。
MUFC

+ mysql -h dbservername -u user-name -ppassword dbname</br> : No such file or directoryids.sql</br> + $'\r' : command not found2:这是我收到的错误消息
MUFC

好的,那我就推断您当前的工作目录不在ids.sql文件所在的位置。另外,您可能在脚本中嵌入了换行符。
比尔·卡文

在每个命令之后,我的外壳脚本中确实都嵌入了新行。我的shell脚本包含的所有内容都是3个命令行命令,我不想单独运行,因此我创建了一个shell脚本以使它们在没有我干预的情况下运行,并且我在每个命令后都添加了换行符。这是造成问题吗?
MUFC

最好避免-p密码为空或空字符串,也许您可​​以更新您的帖子?:)
James Oravec

118

使用以下语法:

mysql -u $user -p$passsword -Bse "command1;command2;....;commandn"

8
我从Google登陆到此页面,这是我期望的解决方案(与问题的标题匹配)。
Janaka R Rajapaksha

15
有关手册中选项的更多详细信息:-B用于批处理,使用制表符作为列分隔符打印结果,每一行均在新行中。使用该选项,mysql不使用历史文件。批处理模式产生非表格输出格式并转义特殊字符。-s是静默模式。产生较少的输出。-e是要执行该语句并退出
ranvaud

谢谢你的帮助!:)
haotang

可以和heredoc一起运行吗?
zx1986 '18

1
@ zx1986是和否,发送给HEREDOC。取决于您的使用意图。用它代替"command1;command2;....;commandn"该答案的一部分将不起作用。使用它来替换OP语法中重定向文件的使用可以起作用。我在回答这个问题时已经解决了这个问题。
Chindraba,

45

先前的所有答案都很棒。如果它是您希望运行的简单的单行sql命令,则也可以使用-e选项。

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

我需要做的是在double(“”)引号内进行查询。谢谢
user3132107

我知道了,我认为您是否需要在查询末尾添加分号?
洛里(Lori)

19

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

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

如果将host用作本地主机,则无需提及。您可以使用此:

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

这应该适用于Windows和Linux。

如果密码内容包含!(感叹号),则应\在其前面添加(反斜杠)。


1
如何指定数据库?是否应该在-e内部,例如-e“ use abc; source dbscript.sql”?
Abdul Muneer 2014年

9

这个问题的核心已经被回答了好几次了,我只是想补充一下,反引号(`s)在shell脚本和SQL中都有bean。如果需要在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。


5
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

@Gus,首先感谢您的宝贵意见。对我来说,它就像是一种魅力。我希望输出为Excel或.csv文件。我该如何实现。提前致谢。
Ash_and_Perl 2014年

@Ash_and_Perl我只编辑了这个答案,谢谢vine不是我,这是他的答案。如果您有自己的问题,并且已经尝试自己找到解决方案,建议您提出一个问题。这样,您可以详细说明尝试的内容,失败的方式,然后人们可以为您提供完整,完整的答案(并获得分数!)。
2014年

5

您忘记了-p--password=(后者更易于阅读):

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

(如果您确定凭据/名称不包含空格或shell特殊字符,则无需使用引号。)

请注意,联机帮助页还指出,在命令行上提供凭据是不安全的。因此,请遵循Bill关于my.cnf的建议。


4

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

但我建议这样做:

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

请注意,密码不存在。然后会提示您输入密码。我会再输入一次。这样您的密码就不会登录到服务器的命令行历史记录中。

这是基本的安全措施。

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

这样,您拥有共享相同密码的任何其他帐户都不会受到损害。

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


1
您错过了问题的“自动”部分,并且暂时删除密码是一个绝妙的主意。
PointedEars 2011年

我将其读为“恢复”和“自动”,意思是“自动但不是永远”。但是就像我说的“如果安全不是问题”。我同意-这是一个非常糟糕的主意。
斯特林·汉密尔顿,

很抱歉,如果我造成了混乱。我的意思是,我有两个Perl脚本,用于生成.sql文件,但是将文件转储到DB的命令不是由Shell脚本运行的,但是如果我运行该命令,它绝对可以正常工作在命令行上。我想消除在命令行上运行该命令并通过shell脚本本身运行它的努力。
MUFC

1
Vaibav:如果您可以将实际的shell脚本放入您的问题中,我也许可以提供进一步的帮助。
斯特林·汉密尔顿,

perl fb_apps_frm_fb.pl</br> perl fb_new_spider.pl ds_fbids.txt ds_fbids.sql` </br>mysql -h dbservername -u username -ppassword dbname < ds_fbids.sql
MUFC


3

要“自动化”导入生成的.sql文件的过程,同时避免试图通过stdin和传递文件时可能隐藏的所有陷阱stdout,只需告诉MySQL .sql使用SOURCEMySQL中的命令执行生成的文件即可。

在短,但优秀的,语法的答案,从Kshitij苏德,提供了最好的起点。简而言之,根据Kshitij Sood的语法修改OP的命令,并用以下命令替换其中的SOURCE命令:

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

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

这里的假设是生成的文件作为单独的文件有效.sql。通过不让文件重定向,管道传输或由外壳程序以任何其他方式处理文件,就不会因为外壳程序而需要在生成的输出中转义任何字符。关于什么需要逃脱的规则.sql当然,文件中仍然适用。

my.cnf在其他答案中,已经很好地解决了如何处理命令行或文件等中密码周围的安全性问题,并提出了一些很好的建议。我最喜欢的答案丹尼(Danny),涵盖了这一点,包括如何处理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

请记住,由于外壳扩展,您可以在HEREDOC中使用外壳和环境变量。不利的一面是,您必须逃避每一个反推。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特殊字符。它还消除了在其中使用外壳程序和环境变量的能力。这样做几乎消除了在外壳程序脚本中使用HEREDOC的好处。

另一个选择是将Bash允许的多行带引号的字符串与批处理语法版本一起使用(带有-Bse)。我不知道其他外壳,所以我不能说它们是否也可以在其中使用。无论如何,您都需要使用此命令来执行一个以上的.sql文件SOURCE,因为该文件不会;像其他MySQL命令那样被a终止,并且每行只允许一个文件。多行字符串可以用单引号或双引号引起来,这对shell扩展具有正常的影响。它也有与使用HEREDOC语法处理反引号等相同的警告。

可能更好的解决方案是使用脚本语言,Perl,Python等来创建.sql文件(如OP一样),并SOURCE使用顶部的简单命令语法来创建该文件。脚本语言在字符串操作方面比外壳程序要好得多,并且大多数语言都具有内置的过程来处理与MySQL交互时所需的引用和转义。


2

从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文件上正确且紧密地设置了用户和组的所有权和权限即可。


1
#!/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

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

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

从mysql 5.6.6开始,您可以将密码存储在配置文件中,然后执行类似这样的cli命令。

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

--login-path替换变量...主机,用户和密码。优秀的权利!



0

我写了一个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
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.