Paul Whipp
Paul Whipp

Reputation: 16541

Why does sed not work within the PHP exec command?

I have a secure staging site accessible only via designated IP addresses. It needs to be able to switch apparent URLs to reflect the real site so I set up a simple form to allow the testers to switch between staging 'sites' by editing the .htaccess file on their behalf. The PHP command to edit the .htaccess file was set up thus:

$sed_cmd = "/bin/sed -i 's/^SetEnv MAGE_RUN_CODE=.*$/SetEnv MAGE_RUN_CODE=".$run_code."/' ../.htaccess";

A grep command run before and after invoking this command are run to check it thus:

<p>Previous switch: <strong><em><?php echo `grep 'SetEnv MAGE_RUN_CODE=' ../.htaccess`; ?></strong></em></p>
      <?php exec($sed_cmd, $sed_out, $sed_result); ?>
      <p>Command <strong><em><?php echo $sed_cmd?></em></strong> yielded:
      <br />Return: <?php echo $sed_result; ?>
      <br />Printed:<strong><em><?php print_r($sed_out); ?></em></strong></p>
<p>New switch: <strong><em><?php echo `grep 'SetEnv MAGE_RUN_CODE=' ../.htaccess`; ?></strong></em></p>

The grep commands work fine and copy/pasting the sed line to the command line also works fine. However the sed command fails when run on the web page via the PHP exec command as above yielding an exit status of 4:

Previous switch: SetEnv MAGE_RUN_CODE=naturapet_website

Command /bin/sed -i 's/^SetEnv MAGE_RUN_CODE=.*$/SetEnv MAGE_RUN_CODE=animal_health_store_website/' ../.htaccess yielded:
Return: 4
Printed:Array ( )

New switch: SetEnv MAGE_RUN_CODE=naturapet_website

The process has write access to the file and as I can't find a way to get any more information on the error I'm stumped.

I know I can work around the problem with a more complex solution using preg_replace but I would love to know why the above code does not work.

Can anyone tell me why sed is not working when invoked in exec the way I've set it up above?

Upvotes: 0

Views: 2944

Answers (2)

oHo
oHo

Reputation: 54661

Explanation

sed creates a temporary working file when used with option -i. Then, sed uses the content of this temporary file to update in place the source file (e.g. ../.htaccess).

However, when sed cannot create this temporary file, it returns the exit value 4.
(sed creates this temporary file in the directory where the source file is located)

Therefore the directory where .htaccess is located may be write-protected or something like that (ACL...). I have never seen the error 'Array ( )': Let me know if you find...

Possible workarounds

Use your own temporary .htaccess.tmp file (i.e. do not use -i option):

$sed_cmd = "/bin/sed 's/^SetEnv MAGE_RUN_CODE=.*$/SetEnv MAGE_RUN_CODE=".$run_code."/' ../.htaccess > ../.htaccess.tmp && cat ../.htaccess.tmp > ../.htaccess";

You may use cp instead of cat but cat will preserve original owner and permission of .htaccess.

Another idea is to retrieve the sed output, then to write back the .htaccess file:

$sed_cmd = "/bin/sed 's/^SetEnv MAGE_RUN_CODE=.*$/SetEnv MAGE_RUN_CODE=".$run_code."/' ../.htaccess";
exec ($sed_cmd, $sed_out, $sed_result);
$file = fopen ('../.htaccess', 'w');
fwrite ($file, $sed_out);
fclose ($file);

Upvotes: 1

oHo
oHo

Reputation: 54661

Put your sed stuff within a script set_MAGE_RUN_CODE.sh:

#!/bin/bash
FILE=../.htaccess
if [ -f "$FILE" ]
then 
   sed -i 's/^SetEnv MAGE_RUN_CODE=.*$/SetEnv MAGE_RUN_CODE=$@/' "$FILE"
else
   # print error
   echo >&2 "$(basename $0): Cannot find file '$FILE' in directory '$(pwd)'"
fi

Do not forget to give execution permission:

chmod +x /your/dir/set_MAGE_RUN_CODE.sh

Then update your PHP code:

<p>Previous switch: <strong><em>
    <?php echo `grep 'SetEnv MAGE_RUN_CODE=' ../.htaccess`; ?>
</strong></em></p>

<?php exec("/your/dir/set_MAGE_RUN_CODE.sh new_website", $sed_out, $sed_result); ?>

<p>Command <strong><em><?php echo $sed_cmd?></em></strong> yielded:
  <br />Return: <?php echo $sed_result; ?>
  <br />Printed:<strong><em><?php print_r($sed_out); ?>
</em></strong></p>

<p>New switch: <strong><em>
  <?php echo `grep 'SetEnv MAGE_RUN_CODE=' ../.htaccess`; ?>
</strong></em></p>

Upvotes: 0

Related Questions