Saturday, June 21, 2008

Non-interactive SSH in Linux

There are two machines, A and B in a network. Let the IP of A be 192.168.1.2, and IP of B be 192.168.1.8. You can access remotely from A to B using the command: ssh guest@192.168.1.8. It will ask you the password of the user guest in machine B. Now let me tell you a simple trick so that you don't need to enter the password any more. It's called non-interactive ssh.

Suppose your username in machine A is pypy. Open the terminal. Go to the directory /home/pypy/.ssh (cd /home/pypy/.ssh). Now enter the follwoing command:
ssh-keygen -t dsa
First it will ask you for a filename. Just press enter to keep it default (id_dsa) or you can enter any other name. Then it will ask you for a passphrase. Enter empty there (just press enter twice). Now you will see two files there named id_dsa (that has the private key) and id_dsa.pub (that contains the public key).

pypy@pypy-laptop:~/.ssh$ ssh-keygen -t dsa
Generating public/private dsa key pair.
Enter file in which to save the key (/home/pypy/.ssh/id_dsa):
Enter passphrase (empty for no passphrase):
Enter same passphrase again:
Your identification has been saved in /home/pypy/.ssh/id_dsa.
Your public key has been saved in /home/pypy/.ssh/id_dsa.pub.
The key fingerprint is:
fc:37:69:9e:bb:15:e7:55:cd:b9:52:12:e6:49:b1:6c pypy@pypy-laptop

Key generation complete. Check the directory

pypy@pypy-laptop:~/.ssh$ ls -lt
total 12
-rw------- 1 pypy pypy 668 2008-06-20 23:54 id_dsa
-rw-r--r-- 1 pypy pypy 610 2008-06-20 23:54 id_dsa.pub

Now append the content of id_dsa.pub file to the file named authorized_keys2 in /home/guest/.ssh directory (if the file doesn't exist first create it) of machine B. You can do this using this command also:
cat /home/pypy/.ssh/id_dsa.pub | ssh guest@192.168.1.8 'cat - >> ~/.ssh/authorized_keys2'

(it will ask you for the password of user guest of machine B).

Now done. Try to access machine B from machine A
pypy@pypy-laptop:~/.ssh$ ssh guest@192.168.1.8

Hopefully it won't ask you for a password :-)

Thursday, June 19, 2008

Perl script to display the content of a zip file

Here is a little script that shows the number of files in a zip file and the names of the files. Interesting thing is that, we don't need to unzip the file.

Here is the code

use Archive::Zip qw( :ERROR_CODES :CONSTANTS );

my $zip = Archive::Zip->new();

my $zip_file_name = 'scraper.zip';

$zip->read( $zip_file_name );

print "Number of files in the zip file: ".$zip->numberOfMembers()."\n";
print "List of files:\n";

my @members = $zip->memberNames();

#now print the name of the files
foreach (@members)
{
print $_, "\n";
}


For details, please check http://search.cpan.org/~adamk/Archive-Zip-1.23/lib/Archive/Zip.pm

Sunday, June 15, 2008

Your crawler freezes? Use BackgroundWorker in C#

When I wrote my first crawler with GUI in C#.NET (I used .NET so that I can create the GUI easily using Visual Studio) I got into a major problem. The GUI got frozen when I ran the crawler... I shared my problem with one of my friend who then told me about BackgroundWorker Thread. Then I got back home, explored BackgroundWorker, learned how to use it, and used it in my crawler and WOW! It worked fine then. So if you get into similar problem then you can also use BackgroundWorker.

You will find it in Toolbox > Component > BackgroundWorker. Just drag it and drop on your form. Right click on it (it's backgroundWorker1 until you change the name) to change it's properties and add events. Now just code the events...

You can go through this example in msdn http://msdn.microsoft.com/en-us/library/b2zk6580.aspx. It's a useful one I think.

Thursday, June 12, 2008

Problem uploading large file in CGI script

Today I had a problem uploading large file using the CGI upload script I have written using Perl couple of day back. I was getting the response: "413 Request entity too large". I searched Google and found out that this problem can occur for mainly two reasons: if size of the file being uploaded is greater than the value of $CGI::POST_MAX in the upload script, and if the value of the apache (web server) directive LimitRequestBody is lower than the file size. But both cases were handled. But I was still getting the 413 error. Then I found that it was my local server which prevented me to upload large file size. the 413 was coming from that machine instead of the server where the script is hosted :(

How to send custom error message in http header from cgi script

Couple of days ago, while I was writing a CGI script in Perl, it was needed to send custom error message in http response header. I would like to share with you how I have done this.

First I have decided that for any kind of error in the code (for example, file not found, insecure path etc.) I shall return status 500 with the error message. Before this decision my code looked like this:

...
my $query = new CGI;
print $query->header(-type=>'text/plain');
...

So for any error in the script, I added the line:
print $query->header(-type=>'text/plain', -status=>"500 $err_str");
But it wasn't working. The return value (status line in the response) still '200 OK'. Then I found that query header can't be set twice (once you set it, you can't change it). Then I removed the first line print $query->header(-type=>'text/plain'); and modified the code in such a way that the header is printed once. In order to return error, I wrote a function and just called it in case of any error occurs (but I made sure the header is not printed before I call it). Here is the function:

sub catch_n_die
{

my $err_str = shift;

print $query->header(-type=>'text/plain', -status=>"500 $err_str");

exit;

}

Friday, June 6, 2008

Perl script to check the number of instances of a program

To get the number of instances of a program running in your machine you can use the following Perl code:

my $program_name = 'abc.pl';
my $data = `ps ax | grep perl`;
my @ara = $data =~ /perl\s+$program_name/g;
my $count = @ara;
print "$count\n";


Sometime it might be useful for you to know at the start of a program whether it's already running. You can get the name of your current Perl script/program from $0. If the name of your Perl script is program.pl, then $0 will contain program.pl. You can try print $0;
Hope this tiny piece of code will be useful for you. :)

Wednesday, June 4, 2008

execute linux command using Perl, Python, PHP

Those who program in Linux often need to execute/run linux commands from programs/scripts.

Using python you can execute linux command is the following way:

import os
os.system('ls -lt')



If you use Perl, you can do it in the following ways:
1. system(mkdir $folder);
2. qw(mkdir $folder);
3. $temp = `mkdir $folder`; #back ticks
4. exec($command);

If you use back ticks or qw, $? will be set if any error occurs. So you can use it like this:

qw(rm $filename);
if($?) {
print STDERR "error deleting file\n";
}


There are also several options available to run linux commands using PHP. Take a look at here for detals: http://us2.php.net/manual/en/ref.exec.php

Tuesday, June 3, 2008

SQL command to dump data into file and load data from file

In order to migrate data, it is useful to dump data from database table to a file, and load data from file to a table.

To dump data for a specific range in a file, you can use the following SQL command:

SELECT $fields INTO OUTFILE '$dump_file_name' FIELDS TERMINATED BY "\t"
ENCLOSED BY '"' ESCAPED BY "\\" LINES TERMINATED BY '\n' FROM $table_name WHERE
id >= $start AND id < $end;

You can then load the file by using the following SQL command:

LOAD DATA INFILE '$dump_file_name' INTO TABLE $table_name FIELDS TERMINATED BY "\t"
ENCLOSED BY '"' ESCAPED BY "\\" LINES TERMINATED BY '\n' ($fields);


These two commands work fine with MySQL.