What's the difference between sendmail via CGI vs. Perl? - perl

I am using sendmail in perl and noticed (after much banging of head against wall) that when the script is run at the command line it needs you to leave out the \n(s) after your e-mail and the recipient's email address in order to format the mail correctly, but when running via CGI if those \n(s) aren't there it returns an error stating that the recipient's e-mail is malformed.
Has anyone else encountered this? What are the two doing differently?

I am betting that you are getting data from prompts in on the commandline and not chomping them like this:
my $send_to = <>;
This means $send_to will already have a "\n". To make them both work the same way chomp the variables:
my $send_to = <>;
chomp($send_to);
or just
chomp(my $send_to = <>);

In a couple of your comments you mention that you're running the script from the command line with the -l option (perl -l foo.cgi).
The -l option enables automatic line-ending processing, and as your problem is with line endings, I suggest you try it without the -l.

Where is the data coming from? Hard coded in the script, or from a web form?
Just as an aside, if you get the recipient's email address from a web form, your form will be used by spammers. It's a 100% guarantee.

The term "CGI" is broad, if you mean your perl script run as a CGI versus yur perlscript run at the command line, I would look toward the pathing that the script has and its general inherited environment. Especially if your running it as different userids. If the webserver is in a chroot, etc.
use Data::Dumper;
warn(Dumper(\%ENV));

So I'm guessing that you have something like this for running it via the command line:
my $your_email = "you#foo.bar";
my $recipient_email = "them#foo.bar";
and this when "running via CGI":
my $your_email = "you#foo.bar\n";
my $recipient_email = "them#foo.bar\n";
So the question I would ask you then is how you're calling sendmail with the above variables, and also what you mean when you say "running via CGI" versus running via the command line? Are you just adding CGI code and still running via the command line or by visiting its URL in a web browser?

Related

How to send stderr in email shell script (ash)

I wrote a shell script that I use under ash, and I redirect stderr and stdout to a log file. I would like that log file to be emailed to me only if stderr is not empty.
I tried:
exec >mylog.log 2>&1
# Perform various find commands
if [TEST_IF_STDERR_NOT_EMPTY]; then
/usr/bin/mail -s "mylog" email#mydomain.com < mylog.log
fi
My question is twofold:
1- I get a -sh: /usr/bin/mail: not found error. It seems that the mail command doesn't exist under ash (or at least under my linux box, which is a Synology NAS), what would be the alternative? Worst case, perl is available, but I would prefer to use standard sh commands.
2- How to I test that stderr is not empty?
Thanks
How to check if file is empty in bash
As for the first question, in your code you are calling mail but lower in the post you are calling email. Check your code and make sure it is mail.
Use which mail to get the full path. Maybe it is not installed in /usr/bin/.
Use find to locate mail.
If you can go to another shell, run it and then execute which mail to get the full path of mail in case the path is set up in the alternative shells.

Perl command-line based script, running it on a website?

I have a Perl script that works perfectly when I run it from my command prompt. But when I upload it to the cgi-bin folder on my website, it doesn't work. Is there a special format it needs to be or something? I'm totally new to Perl.
Also note: the test hello page Perl script works.
When you run your perl script under cgi (which you indicated is working), the query is passed to your script as STDIN, and the output of your script is sent to the browser.
There will not be a prompt, or anything like that, you need something else (such as a web page) to prompt the user for anything you need and submit it to your script.
The next page on from Bill's link (http://www.lies.com/begperl/form_to_email.html) deals with this.

Export PATH using NET::SSH:PERL

I am writing a shell script to automate some of the tedious tasks that we perform. I need to ssh to a server and change the PATH variable remotely, have that variable persist for the next commands to be executed. Code below;
sub ab_tier{
my $ssh=Net::SSH::Perl->new($host);
$ssh->login($user2,$user2);
my $PATH;
my($stdout,$stderr,$exit)=$ssh->cmd("export
PATH=/usr/bin/sudo:/local/perl-5.6.1/bin:$PATH");
my($PATH, $stderr, $exit)=$ssh->cmd("echo $PATH");
print $PATH; # Check the path for correctness : does not change
}
However the PATH does not change. Is there another way to implement this or am I doing something wrong. I need to automate tasks so dont think $ssh->shell would help here. Please suggest.
I made changes as per suggestions and everything works fine. However I am noticing another issue, which is occurring when trying to display environment variables.
my $cmd_ref_pri={
cmd0=>"echo $ENV{'HOME'}",
cmd1=>"chmod 777 $ENV{'COMMON_TOP'}/temp"
};
Now I am connecting to a remote server using Net::SSH::Perl and the value returned by $ENV{"HOME"} is the value of the my home directory and not of the remote server. However if I add a command as in :
my $cmd_ref_pri={
cmd0=>"whoami ; echo $ENV{'HOME'}",
cmd1=>"chmod 777 $ENV{'COMMON_TOP'}/temp"
};
Then the user id displayed is of the user using which I ssh to the remote server. I do not have other modules installed and the only one available is Net:SSh:perl hence I am forced to use this.
routine for executing command
sub ssh_cmd{
#$cmd_sub - contains command, $ssh contains object ref
my ($cmd_sub,$ssh)=#_;
my($stdout, $stderr, $exit)=$ssh->cmd("bash",$cmd_sub);
if( $exit !=0){
print $stdout;
print "ERROR-> $stderr";
exit 1;
}
return 0;
}
Any suggestions as to why this could happen ?
cmd() is not passing your commands into one shell. It executes them in separate shells (or without any shell - manual is not clear about it). As soon as you finish your export PATH the shell exits and the new PATH is lost.
Looks like it is possible to pass all the relevant commands to a single shell process as separate lines of $stdin?
my $stdin='export A=B
echo $A
';
$ssh->cmd("bash",$stdin);
This would work just like on interactive login (but without terminal control, so commands that talk directly to terminal would likely fail).
Anyway Net::SSH::Perl does not look like the best tool for the job. I would rather use expect for automation.
Set PATH on every command call:
$ssh->cmd('PATH=/usr/bin/sudo:/local/perl-5.6.1/bin:$PATH echo $PATH');
And BTW, Net::SSH::Perl is not being maintained anymore, nowadays Net::SSH2 and Net::OpenSSH are better alternatives.
Write commands to a remote temp file, then execute that one. Or, skip the $PATH thing and use the full path for subsequent commands (assuming you know it).

How do use perl to trigger another perl scipt running on another machine?

Need a way to have a perl script running on one machine run a perl script running on another.
The remote machine config is:
CentOS-5.5,
it's on the same network is the requesting machine,
has a DNS,
ports-open(SSH,HTTP)
Questions, feedback, comments -- just comment, thanks!!
Is this what you want?
system("ssh user#remotemachine perl <remote script's full path>");
will run the script on remote machine.
you may want to ssh without password, check: http://linuxproblem.org/art_9.html
As #Nylon Smile mentioned, you can use system to invoke the system's ssh client. If you want to do this without relying on external binaries (in particular because you want to handle password authentication differently), try Net::SSH::Perl, available from CPAN.
use Net::SSH::Perl;
my $ssh = Net::SSH::Perl->new('host');
$ssh->login('username', 'password');
my ($stdout, $stderr, $exit_code) = $ssh->cmd(
'perl some_script.pl --with=some_args',
'optionally, some stdin for that script'
);
Net::SSH::Perl can be a bit of a pain to install, but there are several other CPAN modules (most of which rely on an installed OpenSSH) and are a bit easier to deal with while providing a similar api. See also Net::SSH and Net::OpenSSH.
The above answers are fine for a one-off, but if you're doing this sort of thing a lot, you may want to look into some sort of messaging system like AMPQ (e.g. RabbitMQ) and set up queue listeners.

Why doesn't my shell script work when I run it from Perl?

I have this command that I load (example.sh) works well in the unix command line.
However, if I execute it in Perl using the system or ` syntax, it doesn't work.
I am guessing certain settings like environment variables and other external sh files weren't loaded.
Is there an example coding to ensure it will work?
More Updates on coding execution failure (I have been trying with different codes):
push (#JOBSTORUN, "cd $a/$b/$c/$d; loadproject cats; sleep 60;");
...
my $pm = new Parallel::ForkManager(3);
foreach my $job (#JOBSTORUN) {
$pm->start and next;
print(`$job`);
$pm->finish;
}
print "\n\n[DONE] FINISHED EXECUTING JOBS\n";
Output Messages:
sh: loadproject: command not found
Can you show us what you have tried so far? How are you running this program?
My first suspicion wouldn't be the environment if you are running it from a login shell. any Perl script you start (well, any program, really) inherits the same environment. However, if you are running the program through cron, then that's a different story.
The other mistakes I usually make in these situations is specifying the relative paths incorrectly. The paths are fine from the command line, but my Perl script has some other current working directory.
For general advice, see Interact with the system when Perl isn't enough. There's also a chapter in Learning Perl about this.
That's about the best advice you can hope for given the very limited information you've shared with us.