Solved

backtick variable substitution

Posted on 2004-04-22
8
3,058 Views
Last Modified: 2012-06-27
Hi all,

Hopefully someone can help me out with this one.

I have a perl script that runs rsh commands to monitor a remote server.  To minimize time and bandwidth I need to maximize the processing that is done on the remote server and minimize the number of rsh commands done.

My question is, how can I place a while loop within a system call so that the loop variable is substituted correctly?  Here is an example:


$THE_ERRORS =
`rsh remote_box "cat -n app_error.log | grep 'error' |
cut -f 1 | while read x; do head -\$x app_error.log | tail -2; done"`;

Basically, I'm trying to get the error message line and the line before it returned into $THE_ERRORS.  The problem is that $x is not being interpreted correctly by the head command.

For simplicity, we can take the whole rsh out of the picture and use this as an example:

$THE_ERRORS =
`cat -n app_error.log | grep 'error' |
cut -f 1 | while read x; do head -\$x app_error.log | tail -2; done`;


Thanks for any suggestions.
0
Comment
Question by:hmdan
[X]
Welcome to Experts Exchange

Add your voice to the tech community where 5M+ people just like you are talking about what matters.

  • Help others & share knowledge
  • Earn cash & points
  • Learn & ask questions
8 Comments
 
LVL 84

Expert Comment

by:ozo
ID: 10894618
$THE_ERRORS =
`cat -n app_error.log | grep 'error' | cut -f 1 | while read x; do head -\$x app_error.log | tail -2; done`;

seems to work for me.
what error are you getting?
0
 

Author Comment

by:hmdan
ID: 10895498
$x seems to be null or blank so the head command fails.

It works at a ksh prompt:

harold$ cat -n app_system.log.7 | grep 'period' | cut -f 1 | while read x; do head -$x app_system.log.7 | tail -2

15-APR-2004 10:49:03  PI-I-PI_Log_Report_Period
  Report period 01/01 00:00 - 04/15 23:59. From time 1072933200 to 1082087940.
15-APR-2004 10:49:54  PI-I-PI_Log_Report_Period
  Report period 01/01 00:00 - 04/15 23:59. From time 1072933200 to 1082087940.
15-APR-2004 12:54:30  PI-I-PI_Log_Report_Period
  Report period 01/01 00:00 - 04/15 23:59. From time 1072933200 to 1082087940.
15-APR-2004 12:54:59  PI-I-PI_Log_Report_Period
  Report period 01/01 00:00 - 04/15 23:59. From time 1072933200 to 1082087940.
15-APR-2004 12:55:32  PI-I-PI_Log_Report_Period
  Report period 01/01 00:00 - 04/15 23:59. From time 1072933200 to 1082087940.


When run from my perl script I get this.

harold$ /home/harold/bin/search.pl
Usage: head [-Count | -n Number | -c Number] [File...]
Usage: head [-Count | -n Number | -c Number] [File...]
Usage: head [-Count | -n Number | -c Number] [File...]
Usage: head [-Count | -n Number | -c Number] [File...]
Usage: head [-Count | -n Number | -c Number] [File...]

Adding a "echo $x" line only displays blank lines.  Hmmm...  I wonder why yours works and mine doesn't.  
0
 
LVL 48

Expert Comment

by:Tintin
ID: 10895558
Do you actually have any Perl in your Perl script?

It's a serious question.  Perhaps it would be much better written as a shell script.  If you find you are using a whole bunch of external commands in your Perl script, you're either not aware of the Perl functions to perform the tasks, or it should be written as a shell script.
0
What does it mean to be "Always On"?

Is your cloud always on? With an Always On cloud you won't have to worry about downtime for maintenance or software application code updates, ensuring that your bottom line isn't affected.

 
LVL 12

Expert Comment

by:stefan73
ID: 10897479
Hi hmdan,
> cat -n app_error.log | grep 'error' | cut -f 1 | while read x; do head -\$x app_error.log | tail -2; done

Put your while loop in ():

cat -n app_error.log | grep 'error' | cut -f 1 | ( while read x; do head -\$x app_error.log | tail -2; done )

Cheers,
Stefan
0
 
LVL 12

Expert Comment

by:stefan73
ID: 10897520
Tintin,
> Do you actually have any Perl in your Perl script?

Good one. As one of Perl's strenghts is that the number of created external processes is reduced, you're throwing away your best speed advantage.

Use Perl to parse your error file:

open (ERRLOG,"<app_system.log") or die "Can't open app_system.log";
while($line=<ERRLOG>){
    if($line =~ /period/){
        print $line;
        $printnext=1;
    } elsif ($printnext){
        print $line;
        $printnext=0;
    }
}
close ERRLOG;
   

Stefan
0
 

Author Comment

by:hmdan
ID: 10900063
>  Do you actually have any Perl in your Perl script?

Yes, I do.  This is just one portion of a much larger monitoring script.

> you're either not aware of the Perl functions to perform the tasks, or it should be written as a shell script.

You are correct:  I am not aware of an rsh function for perl, but the existing perl script is written and functioning fine.  It sure would be a hassle to re-write the whole thing as a shell script just to get this one command to work.  The only external commands in the script are rsh commands.

> Put your while loop in ():
Thanks for the suggestion, but it did not work.

> Use Perl to parse your error file:
The error file is on a remote server - that's why I need the rsh command.  



0
 
LVL 12

Accepted Solution

by:
stefan73 earned 125 total points
ID: 10900572
hmdan,
> The error file is on a remote server - that's why I need the rsh command
Aha. This changes things.

Check that you properly escape everything which is to run on the remote side. Example:

rsh host cat -n app_error.log | grep 'error'
is a lot different from
rsh host cat -n app_error.log "|" grep 'error'

In the first example, the entire cat output is transferred from the remote machine to you local machine and filtered there.
In the second example, grep filtering is done one the remote machine and only the result is transferred.
(The | ends the rsh command in the first line, but is interpreted as a normal argument in the 2nd.)
The same applies to ";".


Everything which should be quoted must be quoted twice, as you have both the local sh and the remote sh commands interpreting it.

So your command should be something like

rsh host cat -n app_error.log "|" grep error "|" cut -f 1 "|" while read x";" do head '-\$x' app_error.log "|" tail -2";" done


Stefan
0
 

Author Comment

by:hmdan
ID: 10901160
> rsh host cat -n app_error.log "|" grep error "|" cut -f 1 "|" while read x";" do head '-\$x' app_error.log "|" tail -2";" done

THANK YOU!

Kick ass... it worked.  You made my Friday, Stefan.  

Have a great weekend.

-harold
0

Featured Post

Want Experts Exchange at your fingertips?

With Experts Exchange’s latest app release, you can now experience our most recent features, updates, and the same community interface while on-the-go. Download our latest app release at the Android or Apple stores today!

Question has a verified solution.

If you are experiencing a similar issue, please ask a related question

Email validation in proper way is  very important validation required in any web pages. This code is self explainable except that Regular Expression which I used for pattern matching. I originally published as a thread on my website : http://www…
I have been pestered over the years to produce and distribute regular data extracts, and often the request have explicitly requested the data be emailed as an Excel attachement; specifically Excel, as it appears: CSV files confuse (no Red or Green h…
Explain concepts important to validation of email addresses with regular expressions. Applies to most languages/tools that uses regular expressions. Consider email address RFCs: Look at HTML5 form input element (with type=email) regex pattern: T…
Six Sigma Control Plans

626 members asked questions and received personalized solutions in the past 7 days.

Join the community of 500,000 technology professionals and ask your questions.

Join & Ask a Question