2 Stimmen

Konvertierung von PHP-Variablen in Bash-Variablen

Ich habe eine CakePHP database.php-Konfigurationsdatei, die ich nutzen möchte, um eine Befehlszeilen mysql Client-Instanz zu öffnen.

Das Ziel wäre, in der Lage zu sein, ein Shell-Skript wie ./db-login.sh vom Projektstamm auszuführen und die Datenbankdetails (Host, Port, Datenbankname, Benutzername, Passwort) aus der PHP-Konfigurationsdatei abzurufen und sie als Argumente an die Befehlszeile von mysql zu übergeben. Dies soll verhindern, dass die Details jedes Mal eingegeben werden müssen.

Es ist möglich, eine Shell-Alias zu erstellen, bei dem die Werte fest codiert sind: Ich möchte jedoch ein portables Skript, das bei jedem meiner Cake-Projekte enthalten sein könnte. Ich möchte auch die Aufgabe, die DB-Anmeldeinformationen in Bash-Variablen zu erhalten, getrennt vom Starten des mysql Clients halten. Dadurch würde es möglich sein, die DB-Anmeldeinformationen leicht in anderen Shell-Skripts wiederzuverwenden (wie z.B. ein mysqldump Backup-Skript).

Hier ist, was ich bisher habe:

database.php

Betrachte diese Datei als unveränderlich für die Zwecke dieser Frage. Sie muss genau so existieren, wie du sie siehst.

 'localhost',
        'login'       => 'cakephpuser',
        'password'    => 'c4k3 roxx!',
        'database'    => 'my_cakephp_project',
    );
}

db-cred.sh

Wirkt als Zwischenstelle zur Umwandlung der PHP-Variablen in bash (freundliche) Variablen.

#!/usr/bin/env php
default['password']) ? "\"$db->default['password']\"" : '');

echo <<

``

db-login.sh

#!/usr/bin/env bash
# Verwendet Cakes database.php-Datei, um mysql auf der Befehlszeile mit den korrekten Argumenten anzumelden.

# Widerlich, aber nichts anderes funktioniert!
eval $( db-cred.sh )

# Versuche, eine geeignete Passwort-Klausel zu setzen.
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

# Einen groben Überblick über das, was wir gleich ausführen werden.
echo mysql --host=${DB_HOST} --database=${DB_NAME} --user=${DB_USER}${PASS_CLAUSE}

# MySQL aufrufen.
mysql --host=${DB_HOST} --database=${DB_NAME} --user=${DB_USER}${PASS_CLAUSE}

Dinge, die Hilfe benötigen:

  • Das Skript db-login.sh verwendet eval, um die Variablen einzulesen. Yuck.
  • Das MySQL-Passwort wird auf der Befehlszeile preisgegeben. Dies ist kein Ausschlusskriterium, aber wenn es einen sauberen/portablen Weg gibt, dies zu vermeiden, bin ich dafür offen.
  • Leerzeichen und Anführungszeichen im mysql-Passwort werden nicht ordnungsgemäß an bash übergeben.
    • Ein Passwort wie my Pass wird dazu führen, dass DB_PASS in db-login.sh auf my gesetzt wird.
    • Das Umrahmen des Strings in db-cred.sh führt stattdessen zu "my.
  • Auch meine Versuche, PASS_CLAUSE zu umrahmen, sind nicht wirksam: Nur Passwörter ohne Leerzeichen/Anführungszeichen können sich erfolgreich am mysql Client anmelden.

``

2voto

nickb Punkte 58476
  1. Das Skript db-login.sh verwendet eval, um die Variablen einzulesen. Igitt.

    Anstelle von eval können Sie den Befehl source verwenden:

    source db-cred.sh
  2. Das MySQL-Passwort wird auf der Befehlszeile preisgegeben. Das ist kein Ausschlusskriterium, aber wenn es einen sauberen/portablen Weg gibt, dies zu vermeiden, bin ich offen dafür.

    Sie können einfach das MySQL-Passwort nach der Verwendung löschen:

    unset DB_PASS

    Allerdings werden Sie immer dieses Problem haben, wenn Ihnen das Passwort für MySQL über die Befehlszeile übergeben wird. Sie könnten die -pPasswort-Klausel entfernen und den Benutzer zwingen, das Passwort einzugeben, wenn MySQL danach fragt, aber in Ihrem Anwendungsfall scheint dies nicht praktikabel zu sein.

  3. Leerzeichen und Anführungszeichen im MySQL-Passwort werden nicht ordnungsgemäß an bash übergeben.

  4. Auch meine Versuche, PASS_CLAUSE zu zitieren, waren nicht erfolgreich: Nur Passwörter ohne Leerzeichen/Anführungszeichen können sich erfolgreich beim mysql-Client anmelden.

Für 3 und 4 glaube ich, dass Sie lediglich Ihre Variablenwerte ordnungsgemäß zitieren müssen.

In PHP:

echo <<

``

Beachten Sie die hinzugefügten Anführungszeichen in DB_PASS="{$p}".

Zur Erinnerung, Sie können die Anführungszeichen in PHP auch mit addslashes() escapen.

``

0voto

beporter Punkte 3451

Okay, so @nickb's Vorschläge haben mich auf den richtigen Weg gebracht, mit genügend Anpassungen.

Erklärung

Probleme treten auf, wenn Sie versuchen, das MySQL-Passwort durch mehrere Bash-Variablen zu übergeben. Hier ist ein vereinfachtes Beispiel:

#!/bin/bash
set -x
DB_PASS="pass mit Leerzeichen und 'Anführungszeichen"
PASS_CLAUSE=" -p'$DB_PASS'"

# Funktioniert nicht.
mysql $PASS_CLAUSE

# Funktioniert.
mysql -p"$DB_PASS"

Beachten Sie, dass wir mit set -x die tatsächlich ausgeführten Befehle sehen können. Das hat mir geholfen, das doppelte Escaping zu identifizieren. Der String in $DB_PASS wird erneut escaped, wenn er in $PASS_CLAUSE gespeichert wird. Da er mit einem noch vorhandenen Escaping an MySQL übergeben wird, schlägt die erste Verbindung fehl, aber die Verwendung der ursprünglichen Variablen ist erfolgreich.

Endskripte

db-cred.sh

#!/usr/bin/php
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

Endgedanken

  • Ich habe es nicht explizit getestet, aber es könnten immer noch Probleme mit Passwörtern auftreten, die doppelte Anführungszeichen enthalten.
  • Dies könnte noch verbessert werden, indem sie auf irgendeine Weise den Bedarf an eval entfernt. Die Idee von @Dave, CSV als Zwischenschritt zu verwenden, hat Potenzial, aber in meinen Tests hat es die Dinge weiter kompliziert, indem ein weiteres Escaping/Unescaping-Ebene notwendig war, um die Variablen sauber in den Bash zu bekommen.
  • Das MySQL-Passwort wird immer noch auf der Befehlszeile verwendet. Das Schreiben einer mysql Konfigurationsdatei, die Verwendung mit --defaults-extra-file=filename und anschließendes Löschen könnte ein Weg darum herum sein.
  • db-login.sh repräsentiert jetzt ein Muster für die Ausführung von Befehlszeilen mit den Datenbankanmeldeinformationen und kann leicht modifiziert/erweitert werden für andere Tools wie mysqldump.

CodeJaeger.com

CodeJaeger ist eine Gemeinschaft für Programmierer, die täglich Hilfe erhalten..
Wir haben viele Inhalte, und Sie können auch Ihre eigenen Fragen stellen oder die Fragen anderer Leute lösen.

Powered by:

X