I mentioned at the outset of this series that Mojolicious applications are more than just web servers. I then showed how you can start a web server using the daemon or prefork commands. In the previous post, I mentioned an inflate command that can help you with growing your app from Lite to Full.

But there are other commands, built right in to your app, that can help you be more productive right away!

Command Basics

Before I start, I want to briefly discuss the mojo application/script that comes bundled with the Mojolicious distribution. This command is a tiny Mojolicious app (actually another "hello world") which can be thought of as the "null app". The built-in commands work both for your application and this null one, so use whichever is more appropriate. When it doesn't matter which application runs a command, you can just use mojo.

Each command comes with a one-line description and a (possibly multi-line) usage statement. To see the available commands, run mojo help and you will see all of the commands and their description. You should see something like this:

$ mojo help
Usage: APPLICATION COMMAND [OPTIONS]

  mojo version
  mojo generate lite_app
  ./myapp.pl daemon -m production -l http://*:8080
  ./myapp.pl get /foo
  ./myapp.pl routes -v

Tip: CGI and PSGI environments can be automatically detected very often and
    work without commands.

Options (for all commands):
  -h, --help          Get more information on a specific command
      --home <path>   Path to home directory of your application, defaults to
                      the value of MOJO_HOME or auto-detection
  -m, --mode <name>   Operating mode for your application, defaults to the
                      value of MOJO_MODE/PLACK_ENV or "development"

Commands:
cgi       Start application with CGI
cpanify   Upload distribution to CPAN
daemon    Start application with HTTP and WebSocket server
eval      Run code against application
generate  Generate files and directories from templates
get       Perform HTTP request
inflate   Inflate embedded files to real files
prefork   Start application with pre-forking HTTP and WebSocket server
psgi      Start application with PSGI
routes    Show available routes
test      Run tests
version   Show versions of available modules

See 'APPLICATION help COMMAND' for more information on a specific command.

As it says, you can now see the more detailed information on each command by running mojo help COMMAND for one of those commands.

The Built-In Commands

Since we've already briefly discussed deployment I'll skip over the servers this time, including the cgi and psgi commands. Similarly I'll skip the inflate command. In the interest of space, I'll skip the test command that simply runs your application's tests like prove. I'll also skip cpanify which lets CPAN authors upload modules to CPAN (I use it all the time).

The generate Command

Perhaps the first command you use should be the generate command. It lets you generate a new application (or other) project skeleton from templates.

It has a few subcommands, including one for generating each type of app. To create a Lite app, pass the name of the script to create

$ mojo generate lite_app myapp.pl

To create a Full app, pass the name of the class

$ mojo generate app MyApp

You can also create a plugin project or generate a Makefile.

There is some more to say on the subject of file generation, but since this is an overview post, I'll leave it at that for now.

The version Command

The version command is a simple utility to check your Mojolicious installation.

It outputs your current version of Perl and Mojolicious along with any installed optional libraries. For example, you'll want to install IO::Socket::SSL if you want to fetch or serve sites over HTTPS. It then checks to see if there is an updated version of Mojolicious available.

The routes Command

Once you started writing your application, you might want to introspect it a little bit, especially for debugging purposes. The most straightforward command of that nature is routes. Simply run it on your app to see what routes you have defined.

For example, we can run it on Santa's application from day 3.

$ perl santa.pl routes
/toy/:toy_name  GET  "toy"
/meet/:name     GET  "staff"
/               GET  "home"

This shows you the three routes that were defined. It shows the paths for each route including their placeholders, that all three handle GET, and their route name. Using this output is especially helpful when using named routes, as we learned in that post; all the information you need is right in that table!

We can go a little deeper and ask for verbose output by adding a flag

$ perl santa.pl routes -v
/toy/:toy_name  ....  GET  "toy"    ^\/toy/([^/.]+)/?(?:\.([^/]+))?$
/meet/:name     ....  GET  "staff"  ^\/meet/([^/.]+)/?(?:\.([^/]+))?$
/               ....  GET  "home"   ^/?(?:\.([^/]+))?$

This output includes all the same stuff as before but this time it also adds a few extra items. Certain routes are more complex, and while all these were simple and so no flags are shown, if one were an under route or a websocket it would be noted where the .... are. Finally it includes a pattern that is what is actually matched by the router. This can be helpful sometimes when debugging why certain requests match (or more likely don't match) a certain route. Note that the router checks each route in order top to bottom, the first to match is what is used.

The get Command

Now we're getting to the fun stuff!

Mojolicious comes with a user agent and lots of post-processing power, including HTML/XML and JSON parsers. This command exposes those features together on the command line, like a smart version of cURL or wget.

Output is written to STDOUT so that you can redirect the result to a file if you'd like. Because of that, headers are omitted from the output unless you pass -v.

Let's see what it can do! You can find the latest version of IO::Socket::SSL using the Meta::CPAN JSON API. The response is parsed as JSON and only the version element is output.

mojo get https://fastapi.metacpan.org/v1/module/IO::Socket::SSL /version

You can fetch the Perl headlines from reddit. To do so we fetch the url (following redirects with -r), then we give it a CSS3 selector, and finally extract the text from each found element.

mojo get -r old.reddit.com/r/perl 'p.title > a.title' text

How fun is that?!

  • You can POST or PUT or DELETE data.
  • It handles HTTP basic authentication using username:password@ in the URL.
  • You can submit forms, even with file uploads using the standard @filename syntax.
  • You can pipe data to the command if you just want to send the raw contents of a file rather than url-encode it.
  • See lots more examples in the documentation.

But I haven't even touched on its coolest feature yet. This command also works on your application when you request a relative url. This is so handy for debugging requests during rapid development; you don't even need a browser!

perl santa.pl get /meet/rudolph 'p' text

The eval Command

Finally in this whirlwind tour, I'll show you my favorite command. The eval command. This command has the magic power to run one-off commands using your application! The application is available as app in your one-liner.

So say you can't figure out what is wrong with your configuration, just ask it to dump what it thinks its configuration is

perl myapp.pl eval -v 'app->home'
perl myapp.pl eval -V 'app->config'

The -v flag prints the string result of the last statement to STDOUT, the -V flag does the same but for data structures. Maybe you want to see why it can't find your templates.

perl myapp.pl eval -V 'app->renderer->paths'

This is especially helpful once you have database interactions setup via some model layer. If you want to see the result for some query, just check.

perl myapp.pl eval -V 'app->model->users->find({name => "Joel"})'

Though of course that will depend on how your model layer works. Or maybe you want to deploy your schema, or roll it back.

perl myapp.pl eval 'app->pg->migrations->migrate'

Or just check that the database is reachable.

perl myapp.pl eval -V 'app->pg->db->query("SELECT NOW()")->hash'

These last two database examples assumed that your app was using Mojo::Pg but similar one-liners could work for any database that your app knows about.

There really is nothing like debugging or administering your application without having to copy and paste a bunch of your logic from your app to some script. Although if you really find yourself using the eval command for the same tasks often ... well that should wait until tomorrow.

Image by Gsaisudha75 (editor). For the original file: NASA/Scott Andrews - Derivative work of: File:STS-125 Atlantis Liftoff 02.jpg (while the modifications is Own work). Original file: http://mediaarchive.ksc.nasa.gov/detail.cfm?mediaid=41220, CC BY-SA 4.0

Tagged in : advent, command, debugging, administration

author image
Joel Berger

Joel has Ph.D. in Physics from the University of Illinois at Chicago. He an avid Perl user and author and is a member of the Mojolicious Core Team.