Here’s a quick and easy way to tail log files from multiple hosts using Capistrano and the Foreman gem.

Capistrano Task

First you’ll need to make sure the foreman gem is installed. This can be done globally using gem install foreman, or by adding gem 'foreman' to your Gemfile.

Next, create a new Capistrano task file called tail.rake and place it in the lib/capistrano/tasks directory; Copy & paste the following code into that file.

require 'tempfile'
namespace :tail do

  # == Tasks ==

  desc "Tail syslogs from all hosts"
  task :syslog do
    foremanize! do |foreman|
      on roles(:all) do |server|
        name          = capture("hostname").chomp.gsub(/[^0-9a-z\-]/, "_")
        command       = ssh_cmd(server, "sudo tail -f /var/log/syslog")
        foreman[name] = command
      end
    end
  end

  # == Helpers ==

  def ssh_cmd(server, command)
    "ssh %{user}@%{host} -o StrictHostKeyChecking=no %{command}" % {
      :user    => server.user,
      :host    => server.netssh_options[:host_name],
      :command => command
    }
  end

  def foremanize!
    tasks = {}
    yield(tasks)
    file = Tempfile.new("pf")
    tasks.each {|name, command| file.write("#{name}: #{command} \n") }
    file.close
    exec "foreman start --procfile=#{file.path}"
  end

end

Command & Result

cap production tail:syslog

21:34:23 production_web_000.1    | started with pid 27053
21:34:23 production_worker_000.1 | started with pid 27054
21:34:23 production_web_001.1    | started with pid 27055
21:34:23 production_worker_000.1 | Aug 11 21:33:29 supervisord: ...
21:34:23 production_worker_000.1 | Aug 11 21:34:01 CRON[17904]: ...
21:35:02 production_web_001.1    | Aug 11 21:35:01 CRON[21946]: ...
21:35:02 production_web_000.1    | Aug 11 21:35:01 CRON[20170]: ...
21:35:03 production_web_001.1    | Aug 11 21:35:02 WEB[19793]: ...

Press CTRL+C when you’re done tailing the logs.

Environment

This post was written for, and tested under, the following technologies…

  • Ruby (>= 1.9)
  • Capistrano (3)
  • Foreman (0.84.0)
  • Ubuntu (>= 12.04) – OS of Remote Hosts

Summary

I’ve been using this technique since 2015 and it has made debugging issues occurring across multiple hosts a breeze. If you would like to tail other types of logs just duplicate the :syslog task and change the name and log file path.

Using Eloquent outside of a Laravel project? – Me too!

Collector Class

class PHPDebugBarEloquentCollector extends \DebugBar\DataCollector\PDO\PDOCollector
{
    public function __construct()
    {
        parent::__construct();
        $this->addConnection($this->getTraceablePdo(), 'Eloquent PDO');
    }

    /**
     * @return Illuminate\Database\Capsule\Manager;
     */
    protected function getEloquentCapsule() {
        // ... Return your Illuminate\Database\Capsule\Manager instance here...
    }

    /**
     * @return PDO
     */
    protected function getEloquentPdo() {
        return $this->getEloquentCapsule()->getConnection()->getPdo();
    }

    /**
     * @return \DebugBar\DataCollector\PDO\TraceablePDO
     */
    protected function getTraceablePdo() {
        return new \DebugBar\DataCollector\PDO\TraceablePDO($this->getEloquentPdo());
    }

    // Override
    public function getName() {
        return "eloquent_pdo";
    }

    // Override
    public function getWidgets()
    {
        return array(
            "eloquent" => array(
                "icon"    => "inbox",
                "widget"  => "PhpDebugBar.Widgets.SQLQueriesWidget",
                "map"     => "eloquent_pdo",
                "default" => "[]"
            ),
            "eloquent:badge" => array(
                "map"     => "eloquent_pdo.nb_statements",
                "default" => 0
            )
        );
    }
}

Collector Registration

require_once '/path/to/PHPDebugBarEloquentCollector.php';

$debugbar = new DebugBar\StandardDebugBar();

$debugbar->addCollector(new PHPDebugBarEloquentCollector());

Result

Eloquent Tab in the PHP Debug Bar

Don’t Like Separate Tabs?

Multiple PDO objects can be merged into the default Database tab using this approach…

/* @var Illuminate\Database\Capsule\Manager $capsule */
/* @var Doctrine\ORM\EntityManager          $em */
/* @var DebugBar\StandardDebugBar           $debugbar */

$ormToPdo = [
    "Eloquent" => $capsule->getConnection()->getPdo(),
    "Doctrine" => $em->getConnection()->getWrappedConnection()
];

$collector = new \DebugBar\DataCollector\PDO\PDOCollector();

foreach($ormToPdo as $orm => $pdo) {
    $traceablePDO = new \DebugBar\DataCollector\PDO\TraceablePDO($pdo);
    $collector->addConnection($traceablePDO, $orm);
}

$debugbar->addCollector($collector);

Environment

This post was written for, and tested under, the following technologies…

  • PHP (~5.5)
  • PHP Debug Bar (~1.10)
  • Eloquent ORM (~5.1)
  • Doctrine (~2.0)

Where, oh where, is that pesky Doctrine 2 PDO object…

Doctrine actually uses a base class called \Doctrine\DBAL\Driver\PDOConnection which extends the native PHP PDO class. It’s used by all PDO-based drivers as the common database connection interface.

Code

Access to the \Doctrine\DBAL\Driver\PDOConnection instance can be gained through the Doctrine\ORM\EntityManager instance.

<?php

/* @var \Doctrine\DBAL\Driver\PDOConnection $pdo */
$pdo = $entityManager->getConnection()->getWrappedConnection();

API Docs

Announcing the next release of WordPress Domain Changer – version 2.0!

This release marks the completion of a total rewrite that brings an updated user interface, improved stability, fine-grained control, improved testing, and a few bug fixes.

Redesigned UI & Workflow

Precise Control

The ability to specify database tables has finally arrived!

Safety Net

A Preview & Confirm step has been added in order to help make the domain change process a bit more user-friendly.

Integration Testing

Verifying that WPDC works with every supported version of WordPress would be a slow and tedious process if done by hand. Integration testing to the rescue…

Running RSpec/Capybara suite...

Change Domain of WordPress 2.0.4
  Drop WordPress database
  Create WordPress database
  Unzip WordPress archive
  Start a PHP web server for the OLD domain
  Run through WordPress configuration setup script
  Run through WordPress installation script
  Ensure WordPress site can be reach at OLD domain
  Ensure WordPress site only references the OLD domain
  Install WordPress-Domain-Changer into the root directory of the WordPress site
  Change the URL of the WordPress site using WordPress-Domain-Changer
  Start a different PHP web server for the NEW domain
  Ensure the WordPress site can be reached at the NEW domain
  Ensure the WordPress site only references the NEW domain

Change Domain of WordPress 2.0.5
  Drop WordPress database...

... ( continues up to the latest WordPress release ) ...

Finished in 8 minutes 32 seconds (files took 0.62827 seconds to load)

Continuous Integration

Travis CI has been implemented in order to support the aforementioned testing efforts. Changes pushed to Github will automatically trigger a Travis Build, which verifies that both the unit and integration tests are still passing.

Travis is currently reporting WPDC’s status as – Build Status

Odds & Ends

  • Improvement - All WordPress versions between 2.0.4 and 4.0.0 are officially supported.
  • Improvement - Multi-byte characters support has been added.
  • Bug Fix - Multiple inconsistencies were found in the find & replace logic used for PHP Serialized strings. This logic was rewritten using a more simplistic approach.

See the Change Log for a complete list of changes.

License

WordPress Domain Changer’s code is released under the New-BSD License.

Download

The source code and usage instructions are available at https://github.com/veloper/WordPress-Domain-Changer.

When I decided to port my blog away from WordPress I found myself torn between two great static site generators — Middleman and Jekyll

Feature Envy

One of the features that I’ve grown quite fond in Middleman is their LiveReload Extension. All one needs to do is add activate :livereload to the config.rb file and Middleman will automatically reload the browser when a file change is detected – it’s really slick!

Unfortunately, LiveReload is not available as an out-of-the-box feature for Jekyll. However, the good news is that the same feature can be implemented by using the guard-livereload gem in combination with some simple configuration.

Implementation

Bundler & Gemfile Setup

We start out by ensuring that a Gemfile exists in the Jekyll project’s root directory. Run bundle init to create the Gemfile, open it in an editor, and then add the following gems…

gem 'jekyll'
gem 'guard'
gem 'guard-jekyll-plus'
gem 'guard-livereload'

Install the gems via Bundler and try building your site using the commands below…

$ bundler install
$ jekyll build

It’s very possible that an error will occur after running these commands – don’t worry!

  • The last line of the error should look like this: Missing dependency: xxxxxxxxx.
  • Add the missing dependency to the Gemfile and repeat the last two commands.
  • Continue these steps until your site builds successfully.

Guardfile Configuration

guard 'jekyll-plus', :serve => true do
  watch /.*/
  ignore /^_site/
end

guard 'livereload' do
  watch /.*/
end

Browser Extension

Lastly you’ll need to download and install the Live Reload Extension for your browser – Chrome, Firefox and Safari are supported. This extension automatically refreshes your browser when a change is detected.

Workflow

With :serve => true specified in the jekyll-plus guard options we can now start the Jekyll Web Server + LiveReload by using one simple command…

$ guard

After the guard is executed some output will appear that looks something like this…

Configuration file: _config.yml
22:46:55 - INFO - Guard is using to send notifications.
22:46:55 - INFO - Jekyll building...
    Server address: http://0.0.0.0:4000
  Server running... press ctrl-c to stop.
22:46:56 - INFO - Jekyll build complete ./ → _site
22:46:56 - INFO - Jekyll watching and serving at 0.0.0.0:4000/
22:46:56 - INFO - LiveReload is waiting for a browser to connect.
22:46:56 - INFO - Guard is now watching at '/Users/daniel/projects/my-blog'
[1] guard(main)>

Now, switch to the browser, make sure the LiveReload extension is turned on, and navigate to a blog post. If everything is configured correctly the line below will appear in the terminal…

22:46:58 - INFO - Browser connected.

Open up the blog post in an editor, modify it and save the changes. When you switch back to the browser you should find that the page has automatically reloaded.

Environment

This post was written for, and tested under, the following technologies…

  • Jekyll (1.4.3)
  • Guard (1.8.3)
  • Guard-Jekyll-Plus (1.4.10)
  • Guard-LiveReload (1.4.0)
  • Bundler (1.3.5)
  • Ruby (1.9.3)

Summary

Since implementing Guard-LiveReload in Jekyll I’ve found the process of writing and editing blog posts to be a much more enjoyable experience.

If you’ve found the post useful, or run into any unexpected issues, please feel free to contact me or leave a comment below.