将PHP变量转换为bash变量
我有一个可以用来打开命令行将PHP变量转换为bash变量,php,mysql,bash,Php,Mysql,Bash,我有一个可以用来打开命令行mysql客户端实例的工具 目标是能够从项目根目录运行shell脚本,如/db login.sh,并让它从PHP配置文件中提取数据库详细信息(主机、端口、数据库名称、用户名、密码),并将其作为参数传递到mysql命令行。这是为了避免每次都必须输入详细信息 我知道有可能创建一个具有硬编码值的shell别名:我想要一个可移植脚本,它可以包含在我的任何Cake项目中。我还希望将数据库凭证放入bash变量的任务与启动mysql客户机分开。这将打开在其他shell脚本(例如mys
mysql
客户端实例的工具
目标是能够从项目根目录运行shell脚本,如/db login.sh
,并让它从PHP配置文件中提取数据库详细信息(主机、端口、数据库名称、用户名、密码),并将其作为参数传递到mysql
命令行。这是为了避免每次都必须输入详细信息
我知道有可能创建一个具有硬编码值的shell别名:我想要一个可移植脚本,它可以包含在我的任何Cake项目中。我还希望将数据库凭证放入bash变量的任务与启动mysql
客户机分开。这将打开在其他shell脚本(例如mysqldump
backup脚本)中轻松重用DB凭证的能力
以下是我目前掌握的情况:
database.php
考虑到这个问题,这个文件是不可变的。它必须完全按照你所看到的那样存在
需要帮助的事情:
脚本使用eval吸入变量。恶心db login.sh
- MySQL密码在命令行中泄漏。这不是一个交易破坏者,但如果有一个干净的/可移植的方法来避免它,我愿意接受
- mysql密码中的空格和引号不能正确地传递给bash。
- 类似于
的密码将导致在my Pass
中将DB_Pass设置为DB login.sh
my
- 在
中引用字符串将生成db cred.sh
”“my
- 类似于
- 同样,我尝试引用
也无效:只有没有空格/引号的密码才能成功登录到PASS_子句
客户端mysql
eval
:
-pPassword
子句,并在MySQL提示输入密码时强制用户输入密码,但从您的用例来看,这似乎不可行
echo <<<EOD
DB_HOST="{$db->default['host']}"
DB_NAME="{$db->default['database']}"
DB_USER="{$db->default['login']}"
DB_PASS="{$p}"
EOD;
echo好的,@nickb的建议引导我走上了正确的道路,做了足够的修改
解释
如果您试图通过多个bash变量传递MySQL密码,就会出现问题。下面是一个简化的示例:
#!/bin/bash
set -x
DB_PASS="pass with space and 'quote"
PASS_CLAUSE=" -p'$DB_PASS'"
# Doesn't work.
mysql $PASS_CLAUSE
# Works.
mysql -p"$DB_PASS"
请注意,使用set-x
我们可以看到实际运行的命令。这有助于我识别双重转义。$DB_PASS中的字符串在保存到$PASS_子句时会重新转义。由于它在一个转义级别仍然存在的情况下被传递到MySQL,第一个连接失败,但使用ori基纳尔变量成功
最终脚本
db-cred.sh
最后的想法
- 我还没有专门测试过,但是包含双引号的密码可能仍然存在问题
- 通过某种方式消除对
eval
@Dave使用CSV作为中间人的想法仍然可以改进这一点,但在我的测试中,它添加了另一个级别的转义/取消转义,以使变量干净地进入bash,从而使事情更加复杂
- MySQL密码仍然在命令行中使用。编写、与之一起使用,然后删除它可能是一种解决方法
db login.sh
现在代表了一种使用数据库凭据执行命令行的模式,并且可以很容易地为其他工具(如mysqldump
)修改/扩展
您能创建一个可以由bash和PHP进行评估的文件吗?比如db\u config('host','hostname'))
可以用两种语言工作。让你的database.php以逗号分隔的列表回显变量,如果传递了像?echosh之类的标志,那么你就不需要db-cred.sh。你可以将你的database.php直接包含到db-login.sh中,然后使用将返回的字符串拆分成一个数组,你就可以访问你的数组元素直接。Cake的database.php配置文件的格式是固定的,这是整件事的关键。我确实可以在另一个文件中设置您建议的变量,并将它们拉到Cake的配置文件中,但我必须为我的所有Cake项目都这样做。这否定了可移植性,也不比shell al更好带有硬编码值的ias。@Dave-正如我所提到的,database.php在这种情况下不适合更改。需要有另一种方法将其内容桥接到bash变量中,才能使其干净地工作。至于Shebang,请随意提出一个更好的替代方案。不过,您可以很容易地编辑您的cake database.php,请记住to以后使用新的而不是他们的应用程序?或者正如你所说,更好的可移植性方法是将你的凭据存储到其他地方,并将它们包含到cake配置中。1.我尝试了source
。它不起作用,因为脚本实际上是PHP代码,而不是bash语句(source
忽略了#!).2.解释为什么-p
通常是不安全的。这不是解除VAR的问题,而是暴露在日志中,ps
等。4.我想你可能是对的
#!/usr/bin/env bash
# Uses Cake's database.php file to log into mysql on the
# command line with the correct arguments.
# Holy yuck, but nothing else works!
eval $( db-cred.sh )
# Try to set an appropriate password clause.
PATTERN=" |'"
if [ -n "$DB_PASS" ]; then
if [[ $DB_PASS =~ $PATTERN ]]; then
PASS_CLAUSE=" -p'${DB_PASS}'"
else
PASS_CLAUSE=" -p${DB_PASS}"
fi
else
PASS_CLAUSE=""
fi
# Get a rough look at what we're about to run.
echo mysql --host=${DB_HOST} --database=${DB_NAME} --user=${DB_USER}${PASS_CLAUSE}
# Call MySQL.
mysql --host=${DB_HOST} --database=${DB_NAME} --user=${DB_USER}${PASS_CLAUSE}
source db-cred.sh
unset DB_PASS
echo <<<EOD
DB_HOST="{$db->default['host']}"
DB_NAME="{$db->default['database']}"
DB_USER="{$db->default['login']}"
DB_PASS="{$p}"
EOD;
#!/bin/bash
set -x
DB_PASS="pass with space and 'quote"
PASS_CLAUSE=" -p'$DB_PASS'"
# Doesn't work.
mysql $PASS_CLAUSE
# Works.
mysql -p"$DB_PASS"
#!/usr/bin/php
<?php
include 'database.php';
$db = new DATABASE_CONFIG();
echo <<<EOD
DB_HOST="{$db->default['host']}"
DB_NAME="{$db->default['database']}"
DB_USER="{$db->default['login']}"
DB_PASS="{$db->default['password']}"
EOD;
#!/bin/bash
# Holy yuck, but nothing else works!
eval $( db-cred.sh )
CMD="mysql --host=${DB_HOST} --database=${DB_NAME} --user=${DB_USER}"
PATTERN=" |'"
if [[ ${DB_PASS} =~ ${PATTERN} ]]; then
${CMD} -p"${DB_PASS}"
elif [ -n "${DB_PASS}" ]; then
${CMD} -p${DB_PASS}
else
${CMD}
fi