如何用Bash运行含ENCRYPT()的MySQL脚本?密码非空报错排查
解决Bash脚本中MySQL ENCRYPT()函数返回NULL的问题
这个错误的核心原因是Bash会解析双引号here-document里的美元符号$,导致你的MySQL语句里的$6$被Bash当成了变量引用——而这个变量根本不存在,所以直接被替换成了空字符串。
具体来说,你的CONCAT('$6$', SUBSTRING(SHA(RAND()), -16))经过Bash处理后,会变成CONCAT('', SUBSTRING(SHA(RAND()), -16)),传给ENCRYPT的盐值完全无效,最终ENCRYPT函数返回NULL,触发了Column 'password' cannot be null的错误。
有两种简单的修复方式:
方式1:用单引号包裹here-document分界符
把<< EOF改成<<'EOF',这样Bash会把here-document里的内容当作纯文本,不会解析任何变量或特殊符号:
#!/bin/bash db_root_user='root' db_root_password='rootpassword' mail_db='mail' mysql --user="$db_root_user" --password="$db_root_password" <<'EOF' CREATE DATABASE mail; USE mail; CREATE TABLE domains (domain varchar(50) NOT NULL, PRIMARY KEY (domain) ) ENGINE=InnoDB DEFAULT CHARSET=utf8; CREATE TABLE users (staff_id SMALLINT unsigned NOT NULL,email_addr varchar(100) NOT NULL, password varchar(106) NOT NULL, PRIMARY KEY (email_addr)) ENGINE=InnoDB DEFAULT CHARSET=utf8; INSERT INTO domains (domain) VALUES ('myd1.com'),('myd2.com'),('myd3.com'); INSERT INTO users (staff_id,email_addr, password) VALUES ('1','admin@myd1.com',ENCRYPT('mypassword',CONCAT('$6$', SUBSTRING(SHA(RAND()), -16)))),('1','admin@myd2.com',ENCRYPT('mypassword',CONCAT('$6$', SUBSTRING(SHA(RAND()), -16)))),('1','admin@myd3.com',ENCRYPT('mypassword',CONCAT('$6$', SUBSTRING(SHA(RAND()), -16)))); EOF
注意:这种方式下,原来的$mail_db变量也不会被Bash解析了,所以需要把库名改成硬编码的mail,或者拆分语句单独传递变量。
方式2:转义美元符号
保留双引号的here-document,但把$6$里的$转义成\$,让Bash保留这些符号不做解析:
#!/bin/bash db_root_user='root' db_root_password='rootpassword' mail_db='mail' mysql --user="$db_root_user" --password="$db_root_password" << EOF CREATE DATABASE $mail_db; USE $mail_db; CREATE TABLE domains (domain varchar(50) NOT NULL, PRIMARY KEY (domain) ) ENGINE=InnoDB DEFAULT CHARSET=utf8; CREATE TABLE users (staff_id SMALLINT unsigned NOT NULL,email_addr varchar(100) NOT NULL, password varchar(106) NOT NULL, PRIMARY KEY (email_addr)) ENGINE=InnoDB DEFAULT CHARSET=utf8; INSERT INTO domains (domain) VALUES ('myd1.com'),('myd2.com'),('myd3.com'); INSERT INTO users (staff_id,email_addr, password) VALUES ('1','admin@myd1.com',ENCRYPT('mypassword',CONCAT('\$6\$', SUBSTRING(SHA(RAND()), -16)))),('1','admin@myd2.com',ENCRYPT('mypassword',CONCAT('\$6\$', SUBSTRING(SHA(RAND()), -16)))),('1','admin@myd3.com',ENCRYPT('mypassword',CONCAT('\$6\$', SUBSTRING(SHA(RAND()), -16)))); EOF
这种方式的好处是原来的$mail_db变量依然能被Bash正确解析,不需要修改其他语句,是更推荐的方案。
内容的提问来源于stack exchange,提问作者kittygirl
相关产品推荐
相关产品推荐

