I am relatively new to Perl. I am trying to store a URL in a variable. Here's my code:
my $port = qx{/usr/bin/perl get_port.pl};
print $port;
my $url = "http://localhost:$port/cds/ws/CDS";
print "\n$url\n";
This gives me the below output:
4578
/cds/ws/CDS
So the get_port.pl script is giving me the port correctly but the URL isn't getting stored properly. I believe there's some issue with the slash / but I am not sure how to get around it. I have tried escaping it with backslash and I have also tried qq{} but it keeps giving the same output.
Please advise.
Output for perl get_port.pl | od -a
0000000 nl 4 5 7 8 nl
0000006
There is noithing wrong with your $url string. The problem is almost certainly that the $port string contains carriage-return characters. Presumably you are working on Windows?
Try this code instead, which extracts the first string of digits it finds in the value returned by get_port.pl and discards everything else.
my ($port) = qx{/usr/bin/perl get_port.pl} =~ /(\d+)/;
print $port, "\n";
my $url = "http://localhost:$port/cds/ws/CDS";
print $url, "\n";
As #Сухой27 I think was trying to point out, you can use other character besides '/' with qx, to simplify syntax and then you don't have to escape the slashes.
I also added a default port 8080 in case get_port.pl does not exist.
This seems to work properly.
#!/usr/bin/perl -w
# make 8080 the default port
my $port = qx{/usr/bin/perl get_port.pl} || 8080;
print $port;
my $url = "http://localhost:$port/cds/ws/CDS";
print "\n$url\n";
output
paul#ki6cq:~/SO$ ./so1.pl
Can't open perl script "get_port.pl": No such file or directory
8080
http://localhost:8080/cds/ws/CDS
Related
I would like to inplace edit ssd_config file where i need to replace the #Port to a custom port.
Before:
#Port <portnum>
ex: #Port 22
After:
Port <customport>
ex: Port 2022
Here the custom port is coming in a variable $port.
I tried the below script but does nothing.
my $prt = "Port 2022";
my $cmd = "sed -i \'s/#Port [0-9]\+/$prt/g\' sshd_config";
system($cmd);
Tried even with tick operator.
`sed -i \"s/#Port [0-9]\+/\$prt/g\" sshd_config`;
I'd suggest to do all that in Perl, once you are running a Perl program. That way one doesn't have to run external programs, not to mention the benefits of not having to mess with all the quoting and escaping if you actually need a shell (not in the shown example though).
Then we need a few more lines of code, to read the file and and edit its content and write it back out. That shouldn't matter, given all the benefits -- but there are libraries that cut out even that as well, for example the very handy Path::Tiny
use Path::Tiny;
...
path($filename)->edit_lines( sub { s/#Port [0-9]+/Port $prt/ } );
I take it that $filename and $prt have been introduced earlier in the program.
There is also a edit method, which slurps the whole file.
Anything sed can do, Perl can do.
If this is your entire Perl program:
my $prt = "Port 2022";
my $cmd = "sed -i \'s/#Port [0-9]\+/$prt/g\' sshd_config";
system($cmd);
Then you can do it all in Perl itself from the command line.
perl -i -p -e's/#Port [0-9]+/Port 2022/g' sshd_config
system("sed ....") is invoking a shell to parse the command line, which means that everything needs to be properly escaped according to the rules of the shell. This together with string escaping inside Perl makes it hard to get right. A much simpler way is to skip the shell and call sed directly and also use string concatenation to add the $prt at the right place (and don't forget to also include the "Port" string itself since you want to have it in the output):
system('sed','-i','s/#Port [0-9]+/Port ' . $prt . '/', 'sshd_config');
Alternatively one could do it in Perl directly, i.e. something like this:
open(my $fh,'<','sshd_config') or die $!;
my #lines = map { s/#Port \d+/Port $prt/ } <$fh>;
open($fh,'>','sshd_config') or die $!;
print $fh #lines;
close($fh);
This is a bit longer but does not rely on starting an external program and is thus faster. And if there is more to do than a simple replacement it is also more flexible.
my code :
if ($funcarg =~ /^test (.*)/) {
my $target1 = "http://$1/script/so.php";
system("wget $target1");
so, when i type perl a.pl 127.0.0.1 the script must download http://127.0.0.1/script/so.php, but unfortunately it doesn't. where is my mistake?
[root#localhost perl]# perl a.pl 127.0.0.1
http:///script/so.php: Invalid host name.
It's not clear how your command line argument gets from #ARGV to $funcarg. Or how it goes from 127.0.0.1 to (presumably) test 127.0.0.1. And I think that's where you're going wrong. I think that $funcarg doesn't contain what you think it does before you run the regex match.
This code does what I think you want. But I've had to make up two lines (as marked with a comment) and I'm pretty sure that your version of those two lines is where your misunderstanding is.
#!/usr/bin/perl
use strict;
use warnings;
#ARGV or die "No argument given\n";
# I've made up the next two lines. But I think
# this is where your bug is.
my $host = $ARGV[0];
my $funcarg = "test $host";
if ($funcarg =~ /^test (.*)/) {
my $target1 = "http://$1/script/so.php";
print "$target1\n";
system("wget $target1");
}
Very new to perl and have been stuck for quite awhile on this.
If I change the variable from READSTDIN to google.com, it says google.com is online as it should. If I use the STDIN and input google.com and print $host it prints google.com, however in the ping it doesn't work.
Sample output:
perl perl.pl
What is the website that is offline or displaying an error?google.com
Warning: google.com
appears to be down or icmp packets are blocked by their server
Code:
use strict;
use warnings;
use Net::Ping;
#optionally specify a timeout in seconds (Defaults to 5 if not set)
my $timeout = 10;
# Create a new ping object
my $p = Net::Ping->new("icmp");
#Domain variable
print "What is the website that is offline or displaying an error?";
my $host = readline STDIN;
# perform the ping
if ( $p->ping( $host, $timeout ) ) {
print "Host $host is alive\n";
} else {
print "Warning: $host appears to be down or icmp packets are blocked by their server\n";
}
# close our ping handle
$p->close();
If I change the variable from READSTDIN to google.com, it says google.com is online as it should. If I use the STDIN and input google.com and print $host it prints google.com, however in the ping it doesn't work. I appreciate anyone who can help me at all!
Note the newline in your input:
perl perl.pl
What is the website that is offline or displaying an error?google.com
Warning: google.com <--- newline after google.com puts the rest of the output on the next line...
appears to be down or icmp packets are blocked by their server
You should be using chomp to remove the newline from your input:
chomp( my $host = readline STDIN );
Or more simply:
chomp( my $host = <STDIN> ); # same thing as above
i wrote a little script which executes the ls command. Now I want to store the output of that command in a variable to work with it in the further perl script. Unfortunately I cannot grab the output from the ls command.
my ($core) = "servername";
my $tel_con = "ssh ".$core. " -l $user";
$ssh = Expect->spawn("$tel_con");
$ssh->log_stdout(1);
unless ( $ssh->expect( 5, -re => '$' ) ) {
return "Never connected " . $ssh->exp_error() . "\n";
}
sleep 1;
$ssh->send_slow(0, "ls -l\r");
$ssh->clear_accum();
my $str = $ssh->exp_after();
print "STR = '$str'\n";
Maybe you can give me some help please?
use Net::OpenSSH;
my $ssh = Net::OpenSSH->new($core, user => $user);
$ssh->error and die $ssh->error;
my $output = $ssh->capture('ls -l');
print "command output:\n$output\n\n";
In case you can not or don't want to use Net::OpenSSH you may do:
my #output = $exp->expect(5);
print 'OUT: '.$output[3].'END';
To get the whole output (including the used command, return string, console information)
you could call expect in a seperate process and grab the output via qx or open a pipe
What is send_slow? Depending on how this command sends the ls command, the output can be received in different ways.
Most probably, the error output of the command is stored in the $? variable, possibly byte-shifted.
It seems that Expect will redirect everything to STDOUT and log it internally. Since you enabled output with $ssh->log_stdout(1), you should be able to get the results of ls -l directly from STDOUT (maybe by redirecting standard out to a variable). You can also see try grab the data from the internal logging. Just make sure to grab the output before doing clear_accum().
From CPAN: $object->send_slow($delay, #strings);
... After each character $object will be checked to determine whether or not it has any new data ready and if so update the accumulator for future expect() calls and print the output to STDOUT and #listen_group if log_stdout and log_group are appropriately set.
Layman's terms?
I must obligatorily post this link - I still go there from time-to-time, it is the most layman-y explanation I've ever found of all things regex:
http://www.anaesthetist.com/mnm/perl/Findex.htm
Perl Question. I'm trying to get this script running in a debugger.
I've got Aptana + Epic + ActivePerl 5.12.4 working on Windows 7x64. The script is starting fine but I'm getting an error:
curl -sS http://intranet.mycompany.org/directory/directory.xml
The above command works fine... but if I start the debugger I get this error:
curl: (1) Protocol 'http not supported or disabled in libcurl
First part of the script below:
#!/usr/bin/perl
use strict;
use XML::Parser;
use Data::Dumper;
my $url = 'http://intranet.atlanticgeneral.org/directory/directory.xml';
my $output = 'C:\global.gabook';
my $file = "curl -sS '$url' |";
my $parser = new XML::Parser(Style => 'Tree');
my $tree = $parser->parsefile($file)->[1];
Windows doesn't like single quotes in commands. Try using double quotes in the command, using qq{} escaping. Just change one line:
my $file = qq{curl -sS "$url" |};
Wooble~
"I'm guessing it's the extra single quotes around $url that's
causing it"
When I removed the quotes around the '$url' it worked. Quotes worked in redhat perl, but didn't work in my windows perl debugger:
#!/usr/bin/perl
use strict;
use XML::Parser;
use Data::Dumper;
my $url = 'http://intranet.atlanticgeneral.org/directory/directory.xml';
my $output = 'C:\global.gabook';
my $file = "curl -sS $url |";
my $parser = new XML::Parser(Style => 'Tree');
my $tree = $parser->parsefile($file)->[1];
Posting as answer since Wooble didn't.
I was getting the same error when I was using the curl command in my java program as follows
String command = "curl 'http://google.com'";
try
{
Process proc = Runtime.getRuntime().exec(command);
.......
}catch(Exception e){}
Changing command to the following fixed this error
String command = "curl http://google.com";
Actually, It may be an issue because of shell interpretor.
I used curl command like below example
String command = "curl -duser.name=hdfs -dexecute=select+*+from+logdata.test; -dstatusdir=test.output http://hostname:50111/templeton/v1/hive";
As an alternative (and not needing an external program), you could use LWP::UserAgent to fetch the document.
You pass a wrongly spelled protocol part as in "htpt://example.com" or as in the less evident case if you prefix the protocol part with a space as in " http://example.com/".
Source : https://curl.haxx.se/docs/faq.html