I developed an application to execute commands remotely from a Dancer application. It is not secure if you don't do it correctly but sometimes you may need it, if so, make sure the command is not enter as a parameter from the user and nobody can read your username or password to access to the server.
This is an example of how to execute a remote command using Dancer, Net::SSH2 and fork. It is NOT secure at all, it is just to have an idea and to get some lines of code to implement a function to execute a remote command.
How to send the public key to the remote servers?
To allow the remote server accept the connection, it is required this server knows and authorize the key. This is done by send the public key to the remote host execute this command:
Due to access restriction to the private key I copy it to a directory where the application can read it. Make sure it is only accessible from the dancer application.
May be good idea to have a function to parse the command and make sure it does not have malicious commands such as 'rm'.
I tried this code with threads but there are modules not thread-safe so I recommend to use fork instead.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
my %std=(); # hash of strings. store stdout/stderr results
$ssh2->blocking( 0 ); # needed for channel->poll
while(!$chan->eof) { # there still something to read from channel
$ssh2->poll( $args{'timeout'}, [ @poll ] ); # if any event, it will be store into $poll;
my( $n, $buf ); # number of bytes read (n) into buffer (buf)
foreach my $poll ( @poll ) { # for each event
foreach my $ev ( qw( in ext ) ) { #for each stdout/stderr
next unless $poll->{revents}{$ev};
#there are something to read here, into $std{$ev} hash
if( $n = $chan->read( $buf, $args{'bufsize'}, $ev eq 'ext' ) ) { #got n byte into buf for stdout ($ev='in') or stderr ($ev='ext')
$std{$ev}.=$buf;
}
} #done foreach
}
}
$chan->wait_closed(); #not really needed but cleaner
my $exit_code=$chan->exit_status();
$chan->close(); #not really needed but cleaner
$ssh2->blocking(1); # set it back for sanity (future calls)
return ($std{'in'},$std{'ext'},$exit_code);
}
sub execute ($$$$) {
my ($ip, $username, $password, $cmd) = @_;
my $pid = fork();
if ($pid) {
# This is the parent (DANCER)
debug "Process started with PID $pid\n";
} elsif ( $pid == 0 ) {
# This is the child
my $ssh2 = Net::SSH2->new();
$ssh2->connect( $ip ) or debug("Cannot connect to $ip");
my $publicKeyFile = './id_rsa.pub'; # path(setting('appdir'), 'db', 'id_rsa.pub'); # I prefer to copy the public key in your app dir due to permissions issues
my $privateKeyFile = './id_rsa'; # path(setting('appdir'), 'db', 'id_rsa'); # I prefer to copy the private key in your app dir due to permissions issues
if ( $ssh2->auth_publickey( $username, $publicKeyFile, $privateKeyFile, $password ) ) {
my ($stdout, $stderr, $exitcode) = execCommand($ssh2, $cmd);
} else {
debug "Could not authenticate to $ip with $username";
In a previous post about Preparing the dance floor I explain how to setup Dancer in several OS such as CygWin on Windows, Linux (Ubuntu and CentOS) and Mac OS X (OS X Mavericks) but recently I found that is possible to install and use Dancer on Nitrous.io.
Why Nitrous.io?
Why not? Nitrous.io is a cloud development environment this means you can code for free using a Web Browser in your computer or tablet; or even using a SSH client from anywhere. You also have access to a Web IDE and collaborative coding.
Nitrous.io allows to code in several programming language such as Ruby on Rails, Python with Django, Node.js and Go but it does not explain how to code with Perl on Dancer.
Installing Dancer on Nitrous.io.
The installation process is similar to what was explained in the post Preparing the dance floor but there is a few minor changes.
Cpanminus cannot be installed in a share directory you so cannot use the sudo option and the installation will be done in ~/perl5. After it is installed, the directory ~/perl5/bin need to be included in the PATH variable.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Now you are ready to update the Perl modules but this will increase the used storage. If you have some nitro (N2O) available it is recommended to get more storage.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Nitrous.io is just another good option to develop your dancer application. There are pros and cons about this, but this is a great opportunity to dance in the clouds.
Dancer is a RESTful framework like Sinatra but I want to use Dancer in a MVC application model because allow us to have more efficient code reusing components and separate the logic, the data management and the way the information is displayed.
What is MVC?
There are a lot of tutorials everywhere explaining what MVC is. As a quick explanation, MVC stand for Model View Controller. Model is the data, View is an interface to view the data that is changed or processed in the Controller. To know more about MVC you may read these:
This is all about this post will be: The Model. As mentioned above, the model does nothing else but data management. It does not depend of the controller or the view.
There are a lot of Perl modules to handle the data. I use Dancer::Plugin::Database which use DBI::db module, however there are others modules such as Rose::DB and Dancer::Plugin::DBIC which use DBIx::Class. I'll provide an example with Dancer::Plugin::Database and Dancer::Plugin::DBIC.
Dancer::Plugin::Database
I use Dancer::Plugin::Database for projects that do not require a complex database design. It handle the connection to the database and it support many database managers such as SQLite, MySQL, PostgresSQL, Oracle, etc... For development I use SQLite and it is the one I'll use in this post but you may consider MySQL or PostgresSQL.
First you have to do is to install the Dancer::Plugin::Database module executing this line and update the Modfile with same line. Also, make sure you have installed the module for the database manager you will use, in this case is SQLite
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Configure the connection to the DB. Open environments/development.yml to add these lines to the end:
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Remember to use space instead of tab in any YAML (.yml) file, Dancer will complain if you use tabs.
Create the directory db, where all the databases will be (just like Rails). Create the db/migrations directory to have the following SQL files to create the tables.
db/migration/001_up_teams.sql will be used to create the teams:
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
.. and db/migration/001_down_teams.sql to eliminate them:
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Same for the Users, use db/migration/002_up_users.sql to create the users:
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
.. and db/migration/002_down_users.sql to eliminate them:
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
IMPORTANT: For every statement you do in the UP sql file, you have to undo it in the DOWN sql file and in the opposite order.
In order to test your application you need to fill the database with some data. We can do that with a seeder sql file. Create the db/development.seed.sql file with this:
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
In case you want to confirm the same from the application, create this temporal route in the lib/myapplication.pm file:
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
IMPORTANT: You need to switch from Template::Simple to Template::Toolkit. I'll not explain this change here but basically you need to uncomment the template_toolkit lines and comment the template simple line in config.yml.
In a next post I'll write about Dancer::Plugin::DBIC but now you have at least one model to dance with.
I think the Dancer tutorial is very good explaining how to install Dancer and start your first application. However there are a few things that are not there - and should not be there either - but may be important to have in every Dancer project. Let's start up an application from scratch.
I have tested this in Linux (CentOS and Ubuntu), Mac OS (OS X Mavericks) and Cygwin on Windows but I have not tested it in Windows directly. If you have, please, share your comments about it.
Install cpanminus and update your Perl modules.
cpanminus (cpanm) is much user friendly than cpan, I really recommend to install it and also other cpanm helpers such as cpan-outdated and cpan-listchanges.
In Mac OS X you have to add to the PATH variable the directory where cpanm was installed. In my Mac OS X 10.9.1 was installed in /opt/local/libexec/perl5.12/sitebin but confirm the path before do this.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Now you have them installed it's time to update your Perl modules:
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
You can use the same command to update Dancer, in case you already have it installed.
Create your application scaffold
First thing you need to have is a working or hosting directory. If this is your development environment, you can use the directory Documents/workspace inside your home directory (Windows, Linux or Mac OS). If this is a Testing or Production environment, you can use /opt/ to host your application.
Now it is time to create the application with the command 'dancer -a application_name'. Notice that I used application_name, but you can use a module name like Dancer::application_name.
Once the application scaffold is created go to the application directory and execute it.
$ cd /home/$USER/Documents/workspace
# Or go to /opt if this is not a Development environment# cd /opt
$ dancer -a myapplication
+ myapplication
+ myapplication/bin
+ myapplication/bin/app.pl
+ myapplication/config.yml
+ myapplication/environments
+ myapplication/environments/development.yml
+ myapplication/environments/production.yml
+ myapplication/views
+ myapplication/views/index.tt
+ myapplication/views/layouts
+ myapplication/views/layouts/main.tt
+ myapplication/MANIFEST.SKIP
+ myapplication/lib
myapplication/lib/
+ myapplication/lib/myapplication.pm
+ myapplication/public
+ myapplication/public/css
+ myapplication/public/css/style.css
+ myapplication/public/css/error.css
+ myapplication/public/images
+ myapplication/public/500.html
+ myapplication/public/404.html
+ myapplication/public/dispatch.fcgi
+ myapplication/public/dispatch.cgi
+ myapplication/public/javascripts
+ myapplication/public/javascripts/jquery.js
+ myapplication/t
+ myapplication/t/002_index_route.t
+ myapplication/t/001_base.t
+ myapplication/Makefile.PL
$ cd myapplication/
$ ./bin/app.pl
Open a web browser and go to: http://localhost:3000 to see the new application with a page very similar to a new Ruby on Rails application.
I like to rename the bin/app.pl file to bin/server.pl.
mv bin/app.pl bin/server.pl
Here is where most of the tutorials finish with the installation or setup but what about git?
Git setup
This is an important step. Even if you are the only developer of the project, you always must have a version control and repository for the application. You can setup a git server in other server but I recommend to use GitHub if you can or your company permit it.
Create an account in http://github.com and create a new repository. Choose the same name of your application, enter a description, check on 'Initialize this repository with a README' and select .... What???, there is Perl, Ruby and Rails but no Dancer!!!!, well .... select Perl in the 'Add .gitignore'. Click on 'Create Repository' and that's it.
In the next page there is a box at the right bottom corner with the title 'SSH clone URL'. Click on the 'copy to clipboard' icon or just copy that line. It will be something like this: git@github.com:your_github_user/myapplication.git.
Assuming that you already have git installed - if not, go to http://git-scm.com/downloads or google how to install git in your OS - go to the application directory to setup git. Execute these commands:
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Now every time you made a change to the application you have to add the new files (if any), commit the changes and push them to github. Like this:
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
If you are working with a team or doing changes in different machines, you have to pull the latest changes from github before start working.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Or, if you want the code in a new machine or you want a new fresh copy just clone the application with:
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Unfortunately no, there is no such file in Dancer. However, you can make your own file, I name it Modfile and it have one module per line using the cpanm format:
Read the cpanm manual (man cpanm) to know more about this format. This is an example:
#!/bin/bash
cpanm Dancer
cpanm Dancer::Plugin::Database
cpanm Dancer::Plugin::FlashMessage
cpanm Template
cpanm Test::More # install Test::More
cpanm Net::SCP~1.0000 # 1.0000 or later
cpanm Net::FTP~">= 1.0000, < 2.0000"# latest of 1.xxxx
cpanm Net::SSH2@0.9990 # specific version. same as Net::SSH2~"== 0.9990"
cpanm git://github.com/plack/Plack.git
Save the file and give it execution permission with:
chmod +x Modfile
All the Perl modules required by the application will be updated, downgraded or installed to the latest or specified version executing the Modfile file:
./Modfile
You are almost ready to start coding, let's learn some steps first and you'll be ready to dance.
A few months ago I start working on a new Perl web application. I wanted to do it in Ruby on Rails but the client request to be in Perl for supportability reasons, this means: "If you go, will be easier and cheaper to find a Perl developer than a Ruby developer.". No matter how many reasons, pro and cons I presented, the final decision was to do the web application in Perl.
I was in the task to find a Perl web framework as good as Rails for Ruby. There are a ton of Perl web frameworks but the most famous or known and the top 3 I choose were: Catalysis. Mojolicious and Dancer. You can google and read a lot of comparisons about all of them and take your own decision about which to use for your application. I choose Dancer.
I do not want to criticize the other frameworks. Every framework or language are good but you need to choose one that fit the needs and requirements of your project. At that time I thought Catalysis would be a huge framework for this application, now I think it can fit perfectly because the application grow more than I expected or analyzed. Regarding Mojolicious, I tried once and I did not find enough documentation at that time, by the time I was comparing those 3 frameworks it continue to lack of documentation.
Dancer, as you can read in the excellent documented Dancer site, http://www.perldancer.org/, is a "simple but powerful web application framework for Perl", it was inspired in Sinatra, another Ruby web application framework. Then I read all the excellent documentation, tutorials and training; if you do it, I think you will also choose Dancer.
Dancer is a RESTful framework, just like Sinatra. I was looking something more MVC like Rails but I did not find a good, known and well documented framework in Perl. So, I give a try to REST and Dancer. If you are like me, looking for a MVC or Rails-like Perl framework, Dancer is not the answer but unfortunately there is no answer yet. If you know some framework, please, share your comments.
Even thought Dancer is well documented I had some difficulties to find well explained documents about how to use some modules or how to do some specific things or what modules were the best or recommended. So, base on that I decided to document what I have done and maybe it would be useful for you too. Also, I hope to receive feedback and we all can learn more about how to dance with Perl.