0

I am trying to read some variables from a php config file using bash & it is working for the most part, but I am having issues trying to use the values passed back.
The variuable is found in config, but when it is passed back it still has the single or double quotes from PHP around it.

Here is what I am using.

DBPASS="$(grep -oE '\$database_password = .*;' $CONFIG | tail -1 | sed 's/$database_password = //g;s/;//g')"

now, the variables may be wrapped in either single or double quotes AND a single quote may be present in a password field. So I can't just strip all of them out.

any idea how to do this?

UPDATE

So going another way with this, I have added a bit to the bash script (which basically backs up a CMS) that will look for and write a little PHP "helper". That helper will just read the config, build an array & pass it back to the bash script.

HELPER="backup-helper.php";

CONFIG="../core/config/config.inc.php"

if [ ! -f "$HELPER" ]; then
    echo '<?php' >> $HELPER;
    echo '$config = "$argv[1]";' >> $HELPER;
    echo 'include_once($config);' >> $HELPER;
    echo 'echo $dbase;' >> $HELPER; 
    echo 'echo $modx_core_path;' >> $HELPER;

    echo 'return "this";' >> $HELPER;
    chmod 755 $HELPER;

    php $HELPER  $CONFIG;
fi

So this is basically just looking for the helper files & creating it if it does not exist, then runs it to test - this all works.

I can easily add the logic to create an array of what I need from the config file, but:

how do I format it (the array to be passed back) so that bash will understand it? how do I pass it (the array) back to bash? (basically how do I tell bash to expect a return value?)

Sean Kimball
  • 4,506
  • 9
  • 42
  • 73
  • None of the things you're doing in that pipeline would be problematic in pure PHP. What about just pulling `$CONFIG` into an array with [`file()`](http://php.net/file) and processing it natively? – ghoti May 02 '18 at 20:06
  • I'm trying to read the PHP variables into a bash shell script not doing anything with PHP, just reading a CMS config file so bash can run an automatic update. – Sean Kimball May 02 '18 at 20:17
  • If you needed these values in a PHP script, I'd suggest using a PHP function to `include()` the file, then cherry-pick the variable(s) you want (in an array if there's more than one) that gets passed back as the return value of the function. But if you really are trying to extract PHP variable values for use in a shell script, I'll put some options into an answer. – ghoti May 03 '18 at 03:52
  • Related: https://stackoverflow.com/questions/2464760/modify-config-file-using-bash-script – Jesse Nickles Jul 23 '22 at 18:19

1 Answers1

6

If you're feeling lucky, something like this:

eval $(sed -Ene '/^\$database_(username|password)/{s/ = /=/;s/^\$//;s/;$//;p;}' config.php)

I'll just say here that you absolutely shouldn't do this, it's a bad idea, and I only included as a counterexample. You WILL eventually shoot yourself in the foot if you write shell scripts like this.

Something like this would be safer:

db_username="$(php -r 'include("config.php"); print $database_username;')"
db_password="$(php -r 'include("config.php"); print $database_password;')"

Of course, it depends on having a PHP interpreter around to handle the reading and parsing of the PHP script. If that just isn't possible, then you run the risk of writing your shell-based PHP interpreter in a way that isn't fully compliant with how PHP interprets PHP scripts. Buyer beware, may contain nuts, etc.

You could do something really ugly like this:

#!/usr/bin/env bash

shopt -s extglob

while read -r line; do
  #echo "line = $line"
  case "$line" in
    '$database_username = '*|'$database_password = '*)
      output="${line#\$database_+([[:alpha:]]) = }"
      output="${output#\"}"     # strip leading double quote
      output="${output%\";}"    # strip trailing double quote and semicolon
      ;;
  esac
  case "$line" in
    '$database_username = '*)
      db_username="$output"
      ;;
    '$database_password = '*)
      db_password="$output"
      ;;
  esac
done < config.php

printf 'u = %s\np = %s\n' "$db_username" "$db_password"

This has the advantage of NO PIPELINES, all its functionality is self-contained within a bash script. But it will break if your config.php contains spaces trailing the semicolon, or spaces before the semicolon, or lines broken and continued with escaped newlines, or variables that are built over multiple lines with things like $database_password .= "MOAR"; or any number of other things that might be perfectly valid PHP.

My strong preference is Door Number Two, using a PHP interpreter to interpret your PHP.


UPDATE

If your PHP configuration is in an array (as with Drupal, for example), you might be able to export that array to bash with something like the following:

declare -A conf
while IFS== read -r -d '' key value; do
  conf["$key"]="$value"
done < <( php -r 'include("config.php"); foreach ($conf as $key => $value) printf("%s=%s\0",$key,$value);')'

This uses bash process to provide a dump of the PHP array in a format that can safely be read by bash's read command. This might be advantageous if you have A LOT of things you want to read from your PHP config, and you only want to launch PHP once rather than for every value you're fetching.

Note that you might have to adjust this if any of your keys contain an equals sign. Also, associative arrays are a feature of bash 4.

ghoti
  • 45,319
  • 8
  • 65
  • 104
  • 1
    plus one for the `php -r` approach. That's imo the right way to do it, at least for a production solution. – hek2mgl May 03 '18 at 04:37
  • Sort of going another way on this one - see my updated question – Sean Kimball May 03 '18 at 13:13
  • @SeanKimball, no edit is showing. Did you create a new question? – ghoti May 03 '18 at 13:16
  • Your solution looks good, if I had control over the format of the config file, unfortunately, I do not. can't guarantee spaces or even single/double quotes around values. Hence the 'helper file' – Sean Kimball May 03 '18 at 13:22
  • 1
    So .. you've asked a NEW question in the form of an update to your existing question. My answer to your new question is the "door number two" in my existing answer. Let PHP parse the PHP. But you don't need a helper app. Just do what I suggested using `php -r`. – ghoti May 03 '18 at 13:23
  • hmmm. you are right, I guess I didn't really think that one through – Sean Kimball May 03 '18 at 14:06