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.


Add a comment

Show form to leave a comment

Comments (newest first)

No comments yet.

RSS feed

Blog Tags:

  AWS   Android   Ansible   Apache   Apple   Atlassian   BSD   Backup   Bash   Bluecoat   CMS   Chef   Cloud   Coding   Consul   Containers   CouchDB   DB   DNS   Database   Databases   Docker   ELK   Elasticsearch   Filebeat   FreeBSD   Galera   Git   GlusterFS   Grafana   Graphics   HAProxy   HTML   Hacks   Hardware   Icinga   Influx   Internet   Java   KVM   Kibana   Kodi   Kubernetes   LVM   LXC   Linux   Logstash   Mac   Macintosh   Mail   MariaDB   Minio   MongoDB   Monitoring   Multimedia   MySQL   NFS   Nagios   Network   Nginx   OSSEC   OTRS   Office   PGSQL   PHP   Perl   Personal   PostgreSQL   Postgres   PowerDNS   Proxmox   Proxy   Python   Rancher   Rant   Redis   Roundcube   SSL   Samba   Seafile   Security   Shell   SmartOS   Solaris   Surveillance   Systemd   TLS   Tomcat   Ubuntu   Unix   VMWare   VMware   Varnish   Virtualization   Windows   Wireless   Wordpress   Wyse   ZFS   Zoneminder