How to create PHP files with Ansible blockinfile and fix headers already sent errors with correct markers

Written by - 0 comments

Published on - Listed in PHP Ansible


Ansible is an excellent helper to create or edit a file with multiple lines. These lines are called a "block", hence the name blockinfile for the relevant module.

However in combination with PHP files you need to pay special attention to the blockinfile module and it's parameters.

PHP error: headers already sent

In this particular situation, an Ansible playbook to deploy a PHP application was created. This PHP application supports an automated setup through the command line, by using a prepared config file (config.php). The following Ansible task was created which would create this config.php file with the needed content:

  - name: Application Setup - Create app config config.php
    blockinfile:
      path: "{{ documentroot }}/config.php"
      create: true
      owner: "{{ user }}"
      group: "{{ user }}"
      block: |
        <?php
        $dbconfig = array(
          'host' => 'localhost',
          'port' => '3306',
          'name' => '{{ database }}',
          'user' => '{{ dbuser }}',
          'password' => '{{ dbpass }}',
        );

So far so good, the Ansible task ran through and created the file:

TASK [Application Setup - Create app config config.php] ****************************************************************
changed: [target]

But the task executing the actual setup on the command line (using Ansible command) failed with an error:

Failed to start the session because headers have already been sent by \"/var  \n  /www/example/app/config.php\" at line 1.  

The error message is pretty clear (for someone having run into headers already sent error in the past). A closer look at the config.php file shows that on line 1 a non-PHP code is showing up:

root@target:~# cat /var/www/example/config.php
# BEGIN ANSIBLE MANAGED BLOCK
<?php
$dbconfig = array(
  'host' => 'localhost',
  'port' => '3306',
  'name' => 'example',
  'user' => 'example',
  'password' => 'eedo3LisaiFoong',
);
# END ANSIBLE MANAGED BLOCK

The "# BEGIN ANSIBLE MANAGED BLOCK" string on line 1 (known as the "marker" in the blockinfile module) causes problems here.

Adjust blockinfile marker when creating PHP files

To solve this, we can adjust the marker parameters of the blockinfile module.

Note: An empty marker (marker: "") won't work, as this would create a newline at the beginning of the PHP file, leading to the same error.

To use a correct marker for a PHP file, here's a quick reminder how comments are made inside PHP code:

// for a single line comment in PHP

/* for a
multi line
comment in PHP /*

With this knowlege we can adjust the blockinfile task and adjust the marker_begin to start with the PHP context (<?php) followed by the BEGIN comment. The marker_end simply shows a PHP comment marking the END of the Ansible block but could also contain a closing PHP context (?>). But as you might know this is not necessary in PHP. This results in the following modified blockinfile task:

  - name: Application Setup - Create app config config.php
    blockinfile:
      path: "{{ documentroot }}/config.php"
      create: true
      create: true
      owner: "{{ user }}"
      group: "{{ user }}"
      marker: "{mark} ANSIBLE MANAGED BLOCK"
      marker_begin: "<?php // BEGIN"
      marker_end: "// END"

      block: |
        $dbconfig = array(
          'host' => 'localhost',
          'port' => '3306',
          'name' => '{{ database }}',
          'user' => '{{ dbuser }}',
          'password' => '{{ dbpass }}',
        );

This results in the following final file config.php:

root@irczsrvc49:~# cat /var/www/example/config.php
<?php // BEGIN ANSIBLE MANAGED BLOCK
$dbconfig = array(
  'host' => 'localhost',
  'port' => '3306',
  'name' => 'example',
  'user' => 'example',
  'password' => 'shaeh7Pohz4cie5',
);
// END ANSIBLE MANAGED BLOCK

Now that this config.php is a valid PHP file (without any lines outside the PHP context), the setup task using /usr/bin/php completed successfully without errors.


More recent articles: