将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 考虑到这个问题,这个文件是不可变的。它必须完全按照你所看到的那样存在

需要帮助的事情:
  • db login.sh
    脚本使用eval吸入变量。恶心
  • MySQL密码在命令行中泄漏。这不是一个交易破坏者,但如果有一个干净的/可移植的方法来避免它,我愿意接受
  • mysql密码中的空格和引号不能正确地传递给bash。
    • 类似于
      my Pass
      的密码将导致在
      DB login.sh
      中将DB_Pass设置为
      my
    • db cred.sh
      中引用字符串将生成
      “my
  • 同样,我尝试引用
    PASS_子句
    也无效:只有没有空格/引号的密码才能成功登录到
    mysql
    客户端
  • db-login.sh脚本使用eval来吸收变量

    您可以使用以下命令代替
    eval

  • MySQL密码在命令行中泄露。这不是一个破坏交易的行为,但是如果有一个干净的/可移植的方法来避免它,我愿意接受

    您可以在使用MySQL密码后将其取消设置:

    但是,如果通过命令行向MySQL提供密码,您将始终遇到此问题。您可以删除
    -pPassword
    子句,并在MySQL提示输入密码时强制用户输入密码,但从您的用例来看,这似乎不可行

  • mysql密码中的空格和引号不能正确地传递给bash

  • 同样,我尝试引用PASS_子句也无效:只有不带空格/引号的密码才能成功登录mysql客户端
  • 对于3和4,我相信您需要做的就是正确地引用变量值

    在PHP中:

    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