I have the following script to update one of my FTP passwords every 15 days through a cronjob and e-mail the appropriate people after the attempt has been made. It randomly will fail and so I will run it again manually and it will work. I can't seem to find where it's going wrong.
The script is connecting to a local mysql database grabbing the login and password for an account and then changing that password on FTP. Everything is successful up until the changing the password part. Again it's random, sometimes it works, sometime it doesn't.
Thanks!
#!/usr/bin/perl -w
#
use DBI;
use Net::FTP;
our $dbh = DBI->connect('DBI:mysql:database:127.0.0.1','user','password') or die "Aargh $!\n";
$transquery=q{SELECT dest_login,dest_password FROM list where id=123};
$sth=$dbh->prepare($transquery);
$sth->execute();
while($co=$sth->fetchrow_hashref){
$login=$co->{'dest_login'};
$pass=$co->{'dest_password'};
}
$changeresult='FAIL';
$actionlog='';
$newstring='';
$upperchars='ABCDEFGHIJKLMNOPQRSTUVWXYZ';
$lowerchars='abcdefghijklmnopqrstuvwxyz';
$allowedchars='ABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789##$';
$l=length($upperchars);
$newstring.=substr($upperchars,int(rand($l)),1);
$newstring.=substr($lowerchars,int(rand($l)),1);
$l=length($allowedchars);
for ($i=0;$i<6;$i++){
$newstring.=substr($allowedchars,int(rand($l)),1);
}
print "$newstring\n";
$actionlog .= "Setting Password for $login from $pass to $newstring\n";
$username=
eval{
$ftp=Net::FTP->new('x.x.x.x',Timeout=>480,Debug=>1) or die "Error connecting FTP $!\n";
$changepassword="$pass/$newstring/$newstring";
$ftp->login($login,$changepassword) or die "Error changing password $!\n";
#If we are here, time to update the password
$changeresult='SUCCESS';
$actionlog .= "Password successfully updated\n";
$transquery=q{UPDATE list set dest_password=(?) where id=123};
$sth=$dbh->prepare($transquery);
$sth->execute($newstring);
};
if ($#) {
$actionlog = $actionlog . "$#\n";
};
if($actionlog ne ""){
#print $actionlog;
#my $send_to = "To: someone\#example.com\n";
my $send_to = "To: databaseusers\#example.com\n";
my $sendmail = "/usr/sbin/sendmail -t";
open(SENDMAIL, "|$sendmail") or die "Cannot open $sendmail: $!";
print SENDMAIL "Reply-to: databasepassword\#example.com\n";
print SENDMAIL "Subject: Password Change Information [$changeresult]\n";
print SENDMAIL $send_to;
print SENDMAIL "Content-type: text/plain\n\n";
print SENDMAIL $send_to;
print SENDMAIL "Content-type: text/plain\n\n";
print SENDMAIL $actionlog;
close(SENDMAIL);
$actionlog='';
}
else{
#print "Nothing done this session\n";
USUW might tell you something. ( use strict; use warnings; )
Does anything print?
You don't do much error checking in the DBI part at the beginning, perhaps you're getting a connect error. AIX boxes used to have this problem of getting a client port that the system was unsure about whether or not it was in use. When that happened, it would just fail to connect to the database.
I finally fixed that problem for our scripts by examining the $OS_ERROR ( aka $! ) for that particular code ( Errno::EADDRINUSE ) and then waiting and retrying, with an exponential falloff ( wait 2 seconds, then 4, then 8 ... ).
If your script "dies for some reason" then it's important the script can tell you that reason. I would investigate the topic of error reporting in the various modules you are using.
For example Net::FTP allows you to pass a Debug => 1 switch, and then you'll see the whole conversation.
And I know that there is a whole lot more with DBI where you can get error reporting.
Related
I am writing a CGI program that prints a database query result in the browser. The script looks like this
#!/usr/bin/perl
use strict;
use warnings;
use DBI;
print "Content-type: text/html\n\n";
my $driver = "mysql";
my $database = "DBname";
my $ip = "127.0.0.1";
my $db = "DBI:$driver:DBNAME:$ip:database=$database";
my $username = "user";
my $password = "pass";
print "Connecting ...";
my $connection = DBI->connect($db, $username, $password)
or print "Couldn't connect to database: " . DBI->errstr . "\n\n";
print "Successful connection\n";
my $query = $connection->prepare("SELECT id FROM table");
$query->execute() or die $DBI::errstr;
while ( my #row = $query->fetchrow_array() ) {
my ($id) = #row;
print "ID = $id \n";
}
$query->finish();
Well, my problem is that when I run it from terminal using
perl test.cgi
it works fine, and I get the print results properly. The CGI script is located in /Library/Webserver/CGI-Executables/ and it is configured by default /cgi-bin/ in /etc/apache2/httpd.conf
If I execute it via the web browser, I just get the first print Connecting and nothing else, not even the or print from DBI->connect. I have been trying to realize what the error is, but I am unable to get a useful solution.
From your final comment it is as I suspected: the perl that the server is using simply doesn't have DBD::mysql installed, whereas your command-line perl does
Simply get that driver module installed on the server and all should be well
Note that is doesn't need to be "configured for Apache", it is simply that the copy of perl that is used by the CGI code doesn't have that module
By the way, the content type should be text/plain, not text/html: you're not generating HTML
I have created the following PowerShell script.
$root = 'C:\Backups\My Website\Database Dumps\'
$dateString = (Get-Date).ToString("yyyy-MM-dd")
$fileName = $dateString + "-MyWebsiteDbBackup.sql"
$backupFilePath = ($root + $fileName)
$command = ("mysqldump -u root wpdatabase > " + "`"$backupFilePath`"")
Write-Host $command
Invoke-Expression $command
Its function is supposed to be making a daily backup of a MySQL database for my WordPress website.
When I run the script in PowerShell ISE, it runs fine and the MySQL dump file is created with no problems.
However, in Task Scheduler, it was stuck on running with a code 0x00041301.
For the credentials, I am using the my.cnf technique described here. And I've set the task to run whether a user is logged on or not.
CODE UPDATE
Based on vonPryz's answer.
$root = 'C:\Backups\My Website\Database Dumps\'
$dateString = (Get-Date).ToString("yyyy-MM-dd")
$fileName = $dateString + "-MyWebsiteDbBackup.sql"
$backupFilePath = ($root + $fileName + " 2>&1")
$command = ("mysqldump -u root wpdatabase > " + "`"$backupFilePath`"")
Write-Host $command
$output = Invoke-Expression $command
$output | Out-File C:\mysqlBackupScriptOutput.txt
This now give me an error saying illegal character in path
What am I doing wrong?
Task Scheduler's code 0x00041301 means that the task is running. This is likely to mean that mysqldump is prompting for something. Maybe a password or some confirmation dialog. Which user account is the task being run on?
In order to debug, you'd need to capture the process' output to see what's going on. Try using Tee-Object to send a copy to a file.
just got the DFrobot relay and trying to communicate with it using json commands
pdf is here
any help please how to send an on/off command from terminal?
That is pretty easy, just open a telnet to the device, an example:
telnet 192.168.1.10 2000
and copy paste one of the JSON commands from their pdf document, like:
{"relay1":"on","relay2":"on","relay3":"off","relay4":"off","relay5":"off", "relay6":"off","relay7":"off","relay8":"off"}
and hit enter. In case if you want more than telnet commands you can check this Github project.
please check : https://github.com/Dzduino/DFRobot-RLY-8-Web-Control/blob/master/index.php
You can use PHP Socket like bellow in an html or PHP page, please note that you have to use some local php server (Ex: XAMPP) to test it:
<?php
$addr = "192.168.1.10"; // RLY-8 Default Adress
$port = 2000; // RLY-8 Default port
$timeout = 30; // Connection Time out in Sec
if (isset($_POST["cmd"])){ // check if a submit was done, otherwise the communicatino will start after page loading
$cmd = $_POST["cmd"] ; // Capture the input Command
$fp = fsockopen ($addr, $port, $errno, $errstr, $timeout ); // initiate a socket connection
if (!$fp) {
echo "($errno) $errstr\n"; // return the error if no connection was established
} else {
fwrite ($fp, $cmd); // Send the command to the connected device
echo fread($fp, 128); // Echo the return string from the device
fclose ($fp); // close the connection
}
}
?>
This is my perl code for a registration web page. It should append values to a csv page. It compiles perfectly but when I conncet it to my HTML program the web pae actually displays an error. This is the page
http://cs.mcgill.ca/~zviran1/register.html
HELP
#!/usr/loca/bin/perl
use CGI;
my $q = CGI->new();
use strict;
my $username = $q->param('username');
my $name = $q->param('name');
my $password = $q->param('password');
my #array = ($name, $username, $password, "\r");
my $line = join(' , ', #array);
print "Content-type: text/html \n\n";
my $file = 'Members.csv';
open (FILE, '+>>$file') or die "Cannot open file";
my $inputLine = <FILE>;
while($inputLine = <FILE>)
{
if(index($line, $username) != 4){
print "<HTML>\n";
print "<HEAD>\n";
print "<TITLE> Error Page </TITLE> \n";
print "</HEAD>\n";
print "<BODY>\n";
print "The username you have entered is already in use.";
print "<br>Home Page \n";
print "<br>Registration Page \n";
print "</BODY>\n";
close(FILE);
}
else {
#seeking to the end of the file to append
seek(FILE, 0, 2);
print FILE $line;
}
}
close(FILE);
Are you sure your Perl interpreter is where you want it to be? Your shebang line is
#!/usr/loca/bin/perl
which is probably missing an 'l'. When you run the script locally via perl myscript.pl it ignores that line but when you run it under a webserver like Apache, it's actually used to find the Perl interpreter.
Other than that, have a look at your web server log (you should be able to access the error log even on simple hosting providers) because the error page your browser gets is merely the web server saying 'Hey, something went wrong there'.
I have a Perl script that reads in data from a database and prints out the result in HTML forms/tables. The form of each book also contains a submit button.
I want Perl to create a text file (or read into one already created) and print the title of the book that was inside the form submitted. But I can't seem to get param() to catch the submit action!
#!/usr/bin/perl -w
use warnings; # Allow for warnings to be sent if error's occur
use CGI; # Include CGI.pm module
use DBI;
use DBD::mysql; # Database data will come from mysql
my $dbh = DBI->connect('DBI:mysql:name?book_store', 'name', 'password')
or die("Could not make connection to database: $DBI::errstr"); # connect to the database with address and pass or return error
my $q = new CGI; # CGI object for basic stuff
my $ip = $q->remote_host(); # Get the user's ip
my $term = $q->param('searchterm'); # Set the search char to $term
$term =~ tr/A-Z/a-z/; # set all characters to lowercase for convenience of search
my $sql = '
SELECT *
FROM Books
WHERE Title LIKE ?
OR Description LIKE ?
OR Author LIKE ?
'; # Set the query string to search the database
my $sth = $dbh->prepare($sql); # Prepare to connect to the database
$sth->execute("%$term%", "%$term%", "%$term%")
or die "SQL Error: $DBI::errstr\n"; # Connect to the database or return an error
print $q->header;
print "<html>";
print "<body>";
print " <form name='book' action='bookcart.php' method=post> "; # Open a form for submitting the result of book selection
print "<table width=\"100%\" border=\"0\"> ";
my $title = $data[0];
my $desc = $data[1];
my $author = $data[2];
my $pub = $data[3];
my $isbn = $data[4];
my $photo = $data[5];
print "<tr> <td width=50%>Title: $title</td> <td width=50% rowspan=5><img src=$photo height=300px></td></tr><tr><td>Discreption Tags: $desc</td></tr><tr><td>Publication Date: $pub</td></tr><tr><td>Author: $author</td></tr><tr><td>ISBN: $isbn</td> </tr></table> <br>";
print "Add this to shopping cart:<input type='submit' name='submit' value='Add'>";
if ($q->param('submit')) {
open(FILE, ">>'$ip'.txt");
print FILE "$title\n";
close(FILE);
}
print "</form>"; # Close the form for submitting to shopping cart
You haven't used use strict, to force you to declare all your variables. This is a bad idea
You have used remote_host, which is the name of the client host system. Your server may not be able to resolve this value, in which case it will remain unset. If you want the IP address, use remote_addr
You have prepared and executed your SQL statement but have fetched no data from the query. You appear to expect the results to be in the array #data, but you haven't declared this array. You would have been told about this had you had use strict in effect
You have used the string '$ip'.txt for your file names so, if you were correctly using the IP address in stead of the host name, your files would look like '92.17.182.165'.txt. Do you really want the single quotes in there?
You don't check the status of your open call, so you have no idea whether the open succeeded, or the reason why it may have failed
I doubt if you have really spent the last 48 hours coding this. I think it is much more likely that you are throwing something together in a rush at the last minute, and using Stack Overflow to help you out of the hole you have dug for yourself.
Before asking for the aid of others you should at least use minimal good-practice coding methods such as applying use strict. You should also try your best to debug your code: it would have taken very little to find that $ip has the wrong value and #data is empty.
Use strict and warnings. You want to use strict for many reasons. A decent article on this is over at perlmonks, you can begin with this. Using strict and warnings
You don't necessarily need the following line, you are using DBI and can access mysql strictly with DBI.
use DBD::mysql;
Many of options are available with CGI, I would recommend reading the perldoc on this also based on user preferences and desired wants and needs.
I would not use the following:
my $q = new CGI;
# I would use as so..
my $q = CGI->new;
Use remote_addr instead of remote_host to retrieve your ip address.
The following line you are converting all uppercase to lowercase, unless it's a need to specifically read from your database with all lowercase, I find this useless.
$term =~ tr/A-Z/a-z/;
Next your $sql line, again user preference, but I would look into sprintf or using it directly inside your calls. Also you are trying to read an array of data that does not exist, where is the call to get back your data? I recommend reading the documentation for DBI also, many methods of returning your data. So you want your data back using an array for example...
Here is an untested example and hint to help get you started.
use strict;
use warnings;
use CGI qw( :standard );
use CGI::Carp qw( fatalsToBrowser ); # Track your syntax errors
use DBI;
# Get IP Address
my $ip = $ENV{'REMOTE_ADDR'};
# Get your query from param,
# I would also parse your data here
my $term = param('searchterm') || undef;
my $dbh = DBI->connect('DBI:mysql:db:host', 'user', 'pass',
{RaiseError => 1}) or die $DBI::errstr;
my $sql = sprintf ('SELECT * FROM Books WHERE Title LIKE %s
OR Description LIKE %s', $term, $term);
my $sth = $dbh->selectall_arrayref( $sql );
# Retrieve your result data from array ref and turn into
# a hash that has title for the key and a array ref to the data.
my %rows = ();
for my $i ( 0..$#{$sth} ) {
my ($title, $desc, $author, $pub, $isbn, $pic) = #{$sth->[$i]};
$rows{$title} = [ $desc, $author, $pub, $isbn, $pic ];
}
# Storing your table/column names
# in an array for mapping later.
my #cols;
$cols[0] = Tr(th('Title'), th('Desc'), th('Author'),
th('Published'), th('ISBN'), th('Photo'));
foreach (keys %rows) {
push #cols, Tr( td($_),
td($rows{$_}->[0]),
td($rows{$_}->[1]),
td($rows{$_}->[2]),
td($rows{$_}->[3]),
td(img({-src => $rows{$_}->[4]}));
}
print header,
start_html(-title => 'Example'),
start_form(-method => 'POST', -action => 'bookcart.php'), "\n",
table( {-border => undef, -width => '100%'}, #cols ),
submit(-name => 'Submit', -value => 'Add Entry'),
end_form,
end_html;
# Do something with if submit is clicked..
if ( param('Submit') ) {
......
}
This assumes that you're using the OO approach to CGI.pm, and that $q is the relevant object. This should work, assuming that you have $q = new CGI somewhere in your script.
Can you post the rest of the script?
I've created a mockup to test this, and it works as expected:
#!/usr/bin/perl
use CGI;
my $q = new CGI;
print $q->header;
print "<form><input type=submit name=submit value='add'></form>\n";
if ($q->param('submit')) {
print "submit is \"" . $q->param('submit') . "\"\n";
}
After the submit button is clicked, the page displays that submit is "add" which means the evaluation is going as planned.
I guess what you need to do is make sure that $q is your CGI object, and move forward from there.