Solved

backtick variable substitution

Posted on 2004-04-22
8
3,046 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
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
 
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
Is Your Active Directory as Secure as You Think?

More than 75% of all records are compromised because of the loss or theft of a privileged credential. Experts have been exploring Active Directory infrastructure to identify key threats and establish best practices for keeping data safe. Attend this month’s webinar to learn more.

 
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

Is Your Active Directory as Secure as You Think?

More than 75% of all records are compromised because of the loss or theft of a privileged credential. Experts have been exploring Active Directory infrastructure to identify key threats and establish best practices for keeping data safe. Attend this month’s webinar to learn more.

Question has a verified solution.

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

Suggested Solutions

Many time we need to work with multiple files all together. If its windows system then we can use some GUI based editor to accomplish our task. But what if you are on putty or have only CLI(Command Line Interface) as an option to  edit your files. I…
Checking the Alert Log in AWS RDS Oracle can be a pain through their user interface.  I made a script to download the Alert Log, look for errors, and email me the trace files.  In this article I'll describe what I did and share my script.
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…
When you create an app prototype with Adobe XD, you can insert system screens -- sharing or Control Center, for example -- with just a few clicks. This video shows you how. You can take the full course on Experts Exchange at http://bit.ly/XDcourse.

930 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

Need Help in Real-Time?

Connect with top rated Experts

14 Experts available now in Live!

Get 1:1 Help Now