save this code in a file called portscan, save it to /usr/bin, and give it execution writes with chmod /usr/bin/portscan 777 (777 for simplicity, you may want to change it to suit your needs)
quik tutorial:
scan just one port example:
portscan host_ip -p port
portscan 127.0.0.1 -p 135

scan multiple ports example:
portscan host_ip -s port_start port_stop
portscan 127.0.0.1 -s 1 200

scan all ports example:
portscan host_ip -all
portscan 127.0.0.1 -all # takes awhile

dont show closed ports in port scan, add -c switch
safe open ports to file, use -f file_name
example:
portscan 127.0.0.1 -s 1 400 -f /usr/open_ports.scan

scan ports from a list, -l file_name (not supported yet)
run scans automated by a file -a file_name (in the works, you can play with it, but it dosnt work yet in this source copy)









#!/usr/bin/perl
# <~((((((((((((((((( Port Scan Linux Version )))))))))))))))))~>
# Author : Hex
# Email : Hex@devzoo.com
# Files : PortScan.pl
# Program : PortScan.pl
# Purpose : Small, simple port scanner writen in perl for linux
# Interpreter : Perl 5.8.0

#you are veiwing source curent to version 2.4/bL
my $version = "v2.4/bl"; #version string
####################################### main body ################################################
#vars for port scan
my $host; # host address
my $port1; # host port start
my $port2; # host port stop
my $port; # current port
my $socket; # socket var
my $open; # for eval'ing open sockets
my @open_p; # array of open ports found
my @ports; # array of ports for portscaning from list
my @commands; # holds command line for automated mode

my $count; #for place in array;

#vars for command line switches
my $auto; #holds file name of automation script
my $s; #scan port range switch
my $p; #scan just a single port switch
my $all; #scan all ports switch
my $f; #save output to file filename
my $c; #don't display closed ports durring scan switch
my $r; #scan range of ip's last 8 bits switch
my $l; #get ports list from file switch

use IO::Socket;

start(); #set all vars to empty

split_argv(); #split the arguments paced from the command line into the array of commands

if((@commands[0] eq "") || (@commands[1] eq ""))
{
print "Missing parameters\n";
usage();
}

$host = @commands[0]; #set host string

set_vars(); #set variables from command line and such, and then scans host

exit 0;

############# subs ###########
sub start
{
#vars for port scan
$host = ""; # host address
$port1 = 0; # host port start
$port2 = 0; # host port stop
$port = 0; # current port
$socket; # socket var
$open = ""; # for eval'ing open sockets
@open_p = ""; # array of open ports found
@ports = ""; # array of ports for portscaning from list
#@commands = ""; # holds command line for automated mode

$count = 0; #for place in array;

#vars for command line switches
#$auto = ""; #holds file name of automation script
$s = 0; #scan port range switch
$p = 0; #scan just a single port switch
$all = 0; #scan all ports switch
$f = ""; #save output to file filename
$c = 0; #don't display closed ports durring scan switch
$r = 0; #scan range of ip's last 8 bits switch
$l = ""; #get ports list from file switch
}


######################################### sub split_argv ################################################## ###
sub split_argv
{
$count = 0; #set place in array to 0

while($ARGV[$count]) #loops until end of console line arg's
{
push @commands, $ARGV[$count]; #place the each value of argv onto end of commands array

$count++; #advance place in array
}
}

######################################### sub usage ################################################## ##########
sub usage
{

print "\n-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-\n";
print " Portscan $version\n";
print " Written by hex\n";
print "Usage:\n";
print "portscan x.x.x.x\n";
print "[-a]\n";
print "[-all]\n";
print "[-c]\n";
print "[-f filename]\n";
print "[-l filename]\n";
print "[-p port_number]\n";
print "[-r start end]\n";
print "[-s port_start port_stop]\n";
print "\n[-h] Use for detailed command syntax\n";
print "-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-\n\n";
exit 0;

}

############################################# sub set_vars ################################################## #
sub set_vars
{
#set vars from command line input
if(@commands[0] eq "-a")
{
if($auto ne "")
{
print "Can not automate portscan from with in an automated portscan!\n";
usage();
}

if(@commands[1] eq "") #no file name
{
print "Missing parameter!\n";
usage();
}

$auto = @commands[1]; #set up file name of automated commands
automate();
}

if($auto ne "")
{
$count = 2; #skip ahead of host address in automation file command line
}
else
{
$count = 1; #holds place in @commands[$count]
}

######## command loop ##########
while((@commands[$count] ne "") && (@commands[$count] ne "#")) #loop until all agrs have been processed
{
######## -s ##########
if (@commands[$count] eq "-p") #scan a single port
{
if(($s == 1) || ($p == 1) || ($all == 1) || ($l ne "")) #check for command switch violations
{
print "Incompatible or duplicate command switch set used!\n";
usage();
}

$count++; #advance count;
if((@commands[$count] == "") || (@commands[$count] < 1) || (@commands[$count] > 65535)) #if port is invalid
{ # show error and exit
print "Invalid Port Specification!\n";
usage();
}
$port1 = @commands[$count]; #set to scan just the one port
$port2 = @commands[$count];

$count++; #advance again to get the next command switch
$p = 1; #set switch
}

######## -p ##########
if(@commands[$count] eq "-s") #scan a port range
{
if(($s == 1) || ($p == 1) || ($all == 1) || ($l ne "")) #check for command switch violations
{
print "Incompatible or duplicate command switch set used!\n";
usage();
}

$count++; #advance count
$port1 = @commands[$count]; #set to scan the range of ports
$count++; #advance count
$port2 = @commands[$count];

if(($port1 < 1) || ($port2 > 65535) || ($port2 < $port1)) #look for bad port specifications
{
print "Invalid Port Specifications!\n";
usage();
}

$count++; #advance place
$s = 1;
}

######## -all ##########
if(@commands[$count] eq "-all") #scan all ports
{
if(($s == 1) || ($p == 1) || ($all == 1) || ($l ne "")) #check for command switch violations
{
print "Incompatible or duplicate command switch set used!\n";
usage();
}

$port1 = 1; #set to scan the range of ports
$port2 = 65535;

$count++; #advance place
$all = 1;
}

######## -c ##########
if(@commands[$count] eq "-c") #don't display closed ports in console output
{
if($c == 1) #check for command switch violations
{
print "Incompatible or duplicate command switch set used!\n";
usage();
}

$count++; #advance place
$c = 1;
}

######## -f ##########
if(@commands[$count] eq "-f") #scan all ports
{
if($f ne "") #check for command switch violations
{
print "Incompatible or duplicate command switch set used!\n";
usage();
}

$count++;

if(@commands[$count] eq "")
{
print "No file name specified!\n";
usage();
}

$f = @commands[$count];
$count++; #advance place
}

######## erronious command check ##########
if((@commands[$count] ne "-f") && (@commands[$count] ne "-s") && (@commands[$count] ne "-p") &&
(@commands[$count] ne "-c") && (@commands[$count] ne "-f") && (@commands[$count] ne "-r") &&
(@commands[$count] ne "-l") && (@commands[$count] ne "") && (@commands[$count] ne "#"))
{
print "Invalid command switch!: @commands[$count]\n";
usage();
}

}
######## end of command loop ##########

chomp($host);
chomp($port1);
chomp($port2);
chomp($f);
chomp($l);

scan(); #go on and scan the host now that the command line has been processed
}

########################################### sub scan ################################################## ######
sub automate
{
if((@commands[2] ne "#") && (@commands[2] ne ""))
{
print "Incompatible command switch set used!\n";
usage();
}

open(a_file, "<$auto") || die "Could not open file for portscan automation! $!\n"; #open automation file or die

while(<a_file>)
{
$f = "";
$f = <a_file>; #$f only used as a quik way to not have to define any other variables
#chomp($f); #if you don't like it, tough. lol. declare your own variable and do it your self.
@commands=split(/ /, $f);

$f = ""; #clear $f to avoid file saving errors, see i cleaned it up

if(@commands[0] ne "#")
{
start();
$host = @commands[1];
set_vars();
}

for($count = 0; scalar(@commands) >= $count; $count++)
{
pop @commands;
}

}

close(a_file);
}


########################################### sub scan ################################################## ######
sub scan
{

if($f ne "")
{
# see if file exists before starting scan
open(file, ">$f") || die "Could not open file for data! $!\n"; #Linux
close(file);
}

$port = $port1;

print "\nScanning host $host...\n\n";

if($f ne "") #just a reminder for automated scans
{
print "saving to file $f\n";
}

print "=-=-=-=-=-=-=-=-=-=\n";
print " Portscan $version\n";
print " Written by hex\n";
print "=-=-=-=-=-=-=-=-=-=\n\n";
print "Port\t\tStaus\n";
print "=-=-=\t\t=-=-=\n";

for($port = $port1; $port <= $port2; $port++) # loop untill all ports in range are scanned
{
chomp($port);

if($c == 0) #if no -c switch then print "port" now
{
print $port;
}

$open = eval # evaluates if port can be opened
{
$socket = new IO::Socket::INET # opens a socket
(
PeerAddr => $host,
PeerPort => $port,
Proto => getprotobyname('tcp') || 6 # tcp socket or sopcket 6(for old comps)
)
};

chomp($port);
if ($open) # if port open
{
if($c == 1){print $port;} # if -c switch then print "port" now

print "\t\tOpen <<\n";
push @open_p, $port; #place the open port number into the array of open ports
}

else
{
if($c == 0)
{
print "\t\tClosed\n";
}
}

close($socket); #close the socket when we're done with it
}
print "=-=-=-=-=-=-=-=-=-=\n\n";
print "Overview of portscan:\n";

$open_p = sort {$a<=>$b;} @open_p; #sort the ports by numeric order

if(($s == 1) || ($all == 1)) #if a range of ports were scanned
{
print scalar(@open_p); #print number of ports found open and placed into array
print " open ports found between port $port1 and $port2 on host $host\n\n"; #state how many open ports were found between what ports

#this is statment is still in the works
#if(scalar(@open) >= 1) #if ports were open, show them
#{
print "Port\t\tStaus\n";
print "=-=-=\t\t=-=-=\n";

foreach $port (@open_p) #list all of the open ports found
{
print "$port\t\tOpen\n";
}
#}
}

if($p == 1) #if only a single port was closed
{
if(@open_p[0] ne "") #if the port was open, and thus put into the array of open ports
{
print "Port $port1 was open on host $host\n";
}

else
{
print "Port $port1 was NOT open on host $host\n";
}
}

if($f ne "") #if a file has been specified for saving
{
save_file();
}
print "\n"; #nice trailing empty line
}

################################################# sub save_file ##############################################
sub save_file
{
# saving scan results to a file
open(file, ">$f") || die "Could not open file for data! $!\n"; #open file to save data too

print file "=-=-=-=-=-=-=-=-=-=\n";
print file " Portscan $version\n";
print file " Written by hex\n";
print file "=-=-=-=-=-=-=-=-=-=\n\n";
print file "Host: $host\n";
print file "Command: @commands\n";

if(($s == 1) || ($all == 1)) #if a range of ports were scanned
{
print file "Ports scanned: $port1 to $port2\n\n";
print file "Overview of portscan:\n\n";
print file scalar(@open_p); #print number of ports found open and placed into array
print file " open ports found between port $port1 and $port2 on host $host\n\n"; #state how many open ports were found between what ports

print file "Port\t\tStaus\n";
print file "=-=-=\t\t=-=-=\n";

foreach $port (@open_p) #list all of the open ports found
{
print file "$port\t\tOpen\n";
}
}

if($p == 1) #if only a single port was closed
{
print file "Port scanned: $port1\n\n";
print file "Overview of portscan:\n\n";
if(@open_p[0] ne "") #if the port was open, and thus put into the array of open ports
{
print file "Port $port1 was open on host $host\n";
}

else
{
print file "Port $port1 was NOT open on host $host\n";
}
}
}