2

コマンドラインクライアントインスタンスを開くために利用したいCakePHP database.php 構成ファイルがあります。mysql

目標は、プロジェクト ルートなどからシェル スクリプトを実行し./db-login.sh、PHP 構成ファイルからデータベースの詳細 (ホスト、ポート、データベース名、ユーザー名、パスワード) を取得して、mysql引数としてコマンド ラインに渡すことができるようにすることです。 . これは、毎回詳細を入力する手間を省くためです。

値がハードコーディングされたシェル エイリアスを作成できることは理解しています。Cake プロジェクトに含めることができる移植可能なスクリプトが必要です。mysqlまた、クライアントの起動とは別に、DB 資格情報を bash 変数に取得するタスクを保持したいと考えています。mysqldumpこれにより、他のシェル スクリプト (バックアップ スクリプトなど) で DB 資格情報を簡単に再利用できるようになります。

これが私がこれまでに持っているものです:

データベース.php

この質問の目的のために、このファイルは不変であると考えてください。あなたが見ているとおりに存在しなければなりません。

<?php
class DATABASE_CONFIG {
    public $default = array(
        'host'        => 'localhost',
        'login'       => 'cakephpuser',
        'password'    => 'c4k3 roxx!',
        'database'    => 'my_cakephp_project',
    );
}

db-cred.sh

PHP 変数を bash (フレンドリ) 変数に変換するミドルウェアとして機能します。

#!/usr/bin/env php
<?php
include 'database.php';
$db = new DATABASE_CONFIG(); 

// Selectively wrap quotes. Has no real effect(?)
$p = (!empty($db->default['password']) ? "\"$db->default['password']\"" : '');

echo <<<EOD
DB_HOST="{$db->default['host']}"
DB_NAME="{$db->default['database']}"
DB_USER="{$db->default['login']}"
DB_PASS={$p}
EOD;

db-login.sh

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

助けが必要なこと:

  • db-login.shスクリプトは eval を使用して変数を吸い込みます。うん。
  • MySQL のパスワードがコマンド ラインで漏洩します。これはディールブレーカーではありませんが、それを回避するためのクリーンでポータブルな方法があれば、私はそれを受け入れます。
  • mysql パスワードのスペースと引用符は、bash に正しく渡されません。
    • のようなパスワードmy Passにより、DB_PASS が in に設定さmydb-login.shます。
    • 代わりにdb-cred.sh生成される文字列を引用します。"my
  • 同様に、私の引用の試みPASS_CLAUSEは効果的ではありません: スペース/引用符のないパスワードのみがmysqlクライアントに正常にログインします。
4

2 に答える 2

2
  1. db-login.sh スクリプトは、eval を使用して変数を吸い込みます。うん。

    の代わりに、次のコマンドevalを使用できます。source

    source db-cred.sh
    
  2. MySQL のパスワードがコマンド ラインで漏洩します。これは契約違反ではありませんが、それを回避するためのクリーンでポータブルな方法があれば、私はそれを受け入れます。

    MySQL パスワードは、使用後に設定解除できます。

    unset DB_PASS
    

    ただし、コマンド ライン経由で MySQL にパスワードを指定した場合は、常にこの問題が発生します。この句削除して-pPassword、MySQL がプロンプトを表示したときにユーザーにパスワードの入力を強制することもできますが、ユースケースからは、これは実現可能ではないようです。

  3. mysql パスワードのスペースと引用符は、bash に正しく渡されません。

  4. 同様に、PASS_CLAUSE を引用しようとする私の試みは効果的ではありません。スペース/引用符のないパスワードのみが 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;

に追加された引用符に注意してくださいDB_PASS="{$p}"

PHP では、引用符を でエスケープすることもできますaddslashes()

于 2013-05-01T15:38:27.323 に答える
0

さて、@ 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_CLAUSE に保存されるときに再度エスケープされます。1 レベルのエスケープが行われたまま MySQL に渡されるため、最初の接続は失敗しますが、元の変数を使用すると成功します。

最終的なスクリプト

db-cred.sh

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

db-login.sh

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

最終的な考え

  • 特にテストはしていませんが、二重引用符を含むパスワードにはまだ問題がある可能性があります。
  • これは、何らかの方法で の必要性を取り除くことで改善される可能性がありevalます。CSVを中間に使用するという@Daveのアイデアには可能性がありますが、私のテストでは、変数をbashにきれいに取得するために必要な別のレベルのエスケープ/エスケープ解除を追加することで、さらに複雑になります。
  • MySQL パスワードは、コマンド ラインで引き続き使用されます。mysql構成ファイルを作成し、それを使用して--defaults-extra-file=filename後で削除することは、それを回避する方法かもしれません。
  • db-login.shは、データベース資格情報を使用してコマンド ラインを実行するためのパターンを表し、mysqldump.
于 2013-05-01T18:22:13.450 に答える