I am sort of new to Perl. I was trying to write a script which will take a mysqldump and restore it in a new database. The main idea is to migrate a DB from one server to another.
Here's the scrip that I wrote:
#!/usr/bin/perl
use warnings;
print "Starting the migration process!\n";
print "Enter the source server address, make sure you enter the FQDN of the server";
$source_address = promt ("Source server address: ");
check_string($source_address);
print "Enter the destination server address, make sure you enter the FQDN of the server";
$destination_address = promt ("Destination server address:");
check_string($destination_address);
print "Enter the Source server password for the root user";
$source_password = promt ("Source server address:");
check_string($source_password);
print "Enter the destination server password for the root user";
$destination_password = promt ("Destination server address:");
check_string($destination_password);
$current_dir = cwd();
system("mysqldump --single-transaction -u root -p$source_password --force -h $source_address -A -R -E --triggers
--routines --max_allowed_packet=512M | gzip -c >$current_dir/old_db_dump.sql") or die "system call to create Mysqldump failed: $?";
system("pt-show-grants -uroot -p$source_password -h $source_address > $current_dir/old_grants.sql") or die "system call to create grant failed: $?";
system("mysql -u root -p$destination_password -h $destination_address < $current_dir/old_db_dump.sql") or die "System call to import the sqldump failed: $?";
system("mysql -u root -p$destination_password -h $destination_address < $current_dir/old_grants.sql") or die "System call to import the grants failed: $?";
# A function that checks if the passed string is null or not
sub check_string{
$string_to_check = $_[0];
if ($string_to_check eq '') {
print "The entered value is empty, the program will exit now, re-run the program";
exit 0;
}
}
sub prompt {
my ($text) = #_;
print $text;
my $answer = <STDIN>;
chomp $answer;
return $answer;
}
But when I try to execute the code, I end up with the following error:
Starting the migration process!
Undefined subroutine &main::promt called at migrate_mysql.pl line 26.
Enter the source server address, make sure you enter the FQDN of the server
For writing the Prompt function, I followed the tutorial mentioned in the post here: http://perlmaven.com/subroutines-and-functions-in-perl
I do not know why am I getting this error here. Do I have to include some packages?
Also it would be nice if you could comment on the system block of the code:
system("mysqldump --single-transaction -u root -p$source_password --force -h $source_address -A -R -E --triggers
--routines --max_allowed_packet=512M | gzip -c >$current_dir/old_db_dump.sql") or die "system call to create Mysqldump failed: $?";
system("pt-show-grants -uroot -p$source_password -h $source_address > $current_dir/old_grants.sql") or die "system call to create grant failed: $?";
system("mysql -u root -p$destination_password -h $destination_address < $current_dir/old_db_dump.sql") or die "System call to import the sqldump failed: $?";
system("mysql -u root -p$destination_password -h $destination_address < $current_dir/old_grants.sql") or die "System call to import the grants failed: $?";
Am I doing it in the right way? Am I passing the variable values in a correct manner?
From this error message:
Undefined subroutine &main::promt called at migrate_mysql.pl line 26.
You should look at line 26. Which is odd, because your error isn't on line 26, but here:
$source_address = promt ("Source server address: ");
If I run your code I get:
Undefined subroutine &main::promt called at line 9.
You've got "promt" not "prompt" which is a subroutine that is undefined.
You should really also add use strict; to your code, and then rejig it - it'll generate a lot more errors initially, but it'll avoid some real gotchas in future if you spell a variable incorrectly.
It's quite easy in your code - just put my in front of the first use of a variable - you've been good with scoping otherwise, but otherwise it means that once you first use $string_to_check it remains visible to the rest of the program, which is just a bit messy and can lead to some odd bugs.
Related
I can currently connect to an SFTP server using a username/password combination:
print "Attempting connection...\n";
open( my $LFTP,'|-', "lftp -u $ftpuser,'$ftppwd' -e open -p $ftpport $ftpserver" ) or die "Cannot open lftp: $!";
print $LFTP <<"END";
ls
END
close($LFTP); # die unless lftp exit code is 0
exit 0;
How can change this code to connect to a different server using an SSH key which is encrypted with a passphrase?
This is what I've tried:
print "Attempting connection...\n";
# $ftppwd is blank now!
open( my $LFTP,'|-', "lftp -u $ftpuser,'$ftppwd' -e 'set sftp:connect-program \"ssh -a -x -i $keypath\"; open $ftpserver;'" ) or die "Cannot open lftp: $!";
print $LFTP <<"END";
ls
END
close($LFTP); # die unless lftp exit code is 0
exit 0;
The output is stuck at:
Attempting connection...
`ls' at 0 [Connecting...]
Thank you in advance for any help..
Add -u option to the open command inside -e argument and use the pass phrase as the password. You should also use url syntax to select the sftp protocol, e.g. sftp://user:phrase#server
I want to send some commands to windows command prompt using 'PERL' script.
the command is:
putty.exe -ssh -2 -l username -pw password "ip address"
this command will open an SSH session (console)to the mentioned ip address (server) for me.
after getting the new console, I want to pass commands to and perform operations in the new console.How can I do that as well?
Please help
You can use 'system' or 'exec' command.
system:
#args = ("command", "arg1", "arg2");
system(#args) == 0
or die "system #args failed: $?"
http://perldoc.perl.org/functions/system.html
exec:
exec '/bin/echo', 'Your arguments are: ', #ARGV;
exec "sort $outfile | uniq";
http://perldoc.perl.org/functions/exec.html
Please notice the difference between them.
I have a script that makes of stdin. It also includes internal calls to curl, that are constructed based on the stdin data, and that require password authentication via form variables in the url.
I'd like to be able to type my password when I run the script, rather than storing it somewhere, but stdin is "taken". What's a good way to write a script like this? I'd be interested in either a good way to keep it in the filesystem or if there's some conceivable way to get it as live input without fouling up the incoming pipe.
Read it from the TTY:
if terminal=$(tty < /dev/tty || tty || tty 0<&1 || tty 0<&2) 2> /dev/null
then
echo "Enter password: " > "$terminal"
IFS= read -r password < "$terminal"
else
echo "There is no terminal to read a password from." >&2
exit 1
fi
This tries to get the terminal associated with /dev/tty, or stdin/stdout/stderr if the OS doesn't support it, and uses it to read and write directly to the user.
If it doesn't have to be portable, e.g. when using use Bash on Linux or FreeBSD, you can simplify and improve this:
if ! IFS= read -rs -p "Enter password: " password < /dev/tty 2> /dev/tty
then
echo "Password entry failed"
exit 1
fi
At risk of muddying the question, I needed to switch over to perl and thought it might be useful to some people who find themselves here if I posted a perl translation of "that other guy"'s answer. (Don't know if this is the cleanest way, but it worked for me.)
open (TTY, "+< /dev/tty" )
or eval 'sub Term::ReadLine::findConsole { ("&STDIN", "&STDERR") }';
die $# if $#;
print TTY "Enter your password: ";
use Term::ReadKey;
ReadMode('noecho', *TTY);
my $password = ReadLine(0, *TTY);
chomp $password;
ReadMode('normal', *TTY);
print TTY "\n";
close (TTY);
This is my perl script code. in this i'm getting error like "bareword found where operator expected at $cmd"
my $path = $folder."/".$host."_".$database_name.".bak";
$cmd .= "-U $user_name -P $password -S $host -d master -Q "BACKUP DATABASE [$database_name] TO DISK = N'$path'" ";
any one help me?
When a string has double quotes within it, you need to escape them with \.
$cmd .= "-U $user_name -P $password -S $host -d master -Q \"BACKUP DATABASE [$database_name] TO DISK = N'$path'\" ";
Also, Perl lets you use other characters for quote delimiters. qq followed by almost any character is the same as double quotes. So you could do things like this to avoid the need of backslashes:
$cmd .= qq(-U $user_name -P $password -S $host -d master -Q "BACKUP DATABASE [$database_name] TO DISK = N'$path'" );
$cmd .= qq|-U $user_name -P $password -S $host -d master -Q "BACKUP DATABASE [$database_name] TO DISK = N'$path'" |;
And so on...
Update: How to execute a system command in Perl. There are three basic ways:
system($cmd); #Goes through the shell if shell metacharacters are detected.
system(#command_and_args); #first element is the command, the rest are arguments
system executes a command and waits for it to return. The return value is the exit status of the program.
my #results = `$cmd`; #Always goes through shell.
Backticks execute a command and return its output. You should only use this if you actually need the output; otherwise, it is better to go with system.
exec $cmd;
exec #command_and_args;
exec is exactly like system, except that it never returns. It effectively ends your program by calling another program.
Use the one that is most appropriate to your situation. Or in this case, since you are executing SQL, consider using the DBI module. It's definitely a better approach for anything more than a couple of simple commands.
Looks like you have your " characters in the wrong place. I'm not sure where they should be.
In your second line, the string literal:
"-U $user_name -P $password -S $host -d master -Q "
is immediately followed by the bareword
BACKUP
I want to call my perl script as a command from command line.
Example lets say I have a perl file like following
#!/usr/local/bin/perl -w
#args =("mvn","package");
system(#args) == 0
or die "system #args failed"
I right not call this using package.pl
I tried doing the following
#!/bin/sh
eval 'exec /bin/perl –x -S $0 ${1+"$#"}'
if 0;
#!/usr/local/bin/perl -w
#args =("mvn","package");
system(#args) == 0
or die "system #args failed"
and then name the file 'package' .Do chmod on package
When I try to run package, then I get the error
"Can't open perl script []x:No such file or directory
Can someone please point me out , as to how to do this properly??
Thanks
Neeraj
Change to the name you want to use and make it executable:
cp package.pl package
chmod +x package
Run it:
package
or:
./package
Changed single quotes to double quotes and escaped inner double quotes. Also, there seems to be some problem with paths. Try calling your script with absolute path. I tried adding "./" and it worked:
#!/bin/sh
echo "This is shell"
eval "exec /usr/bin/perl -x -S ./$0 ${1+\"$#\"}"
if 0;
#!/usr/bin/perl -w
print "This is Perl\n";