LinuxQuestions.org

LinuxQuestions.org (/questions/)
-   Programming (https://www.linuxquestions.org/questions/programming-9/)
-   -   Error codes in a for loop (https://www.linuxquestions.org/questions/programming-9/error-codes-in-a-for-loop-842100/)

genderbender 11-03-2010 06:16 AM

Error codes in a for loop
 
I've got a 'nested' for loop which has a grep in it, if the grep fails there's no output - however the error code is still $0 and the second for loop is still entered, there's also a grep in the second for loop.

I guess ultimately what i need to know is whether there's a way of making grep generate an error code. when no results are found?

choogendyk 11-03-2010 06:25 AM

You'll probably have to show a script segment. If you just do a grep on the command line and then immediately echo $?, you will see that it returns a code. You need to capture that code in your script before anything else is done that changes $?.

crts 11-03-2010 06:26 AM

Hi,

from the manpage:
Quote:

EXIT STATUS
Normally, the exit status is 0 if selected lines are found and 1
otherwise
. But the exit status is 2 if an error occurred, unless the
-q or --quiet or --silent option is used and a selected line is found.
Note, however, that POSIX only mandates, for programs such as grep,
cmp, and diff, that the exit status in case of error be greater than 1;
it is therefore advisable, for the sake of portability, to use logic
that tests for this general condition instead of strict equality
with 2.

genderbender 11-03-2010 06:31 AM

Yeah - that does seem accurate actually (works on my tests). I have two subsequent greps though, perhaps this is effecting the code :S

Code:

xe vm-list | grep -A1 NOTREAL | grep power | awk '{print $5}'
[root@MYSERVER ]# echo $?
0
xe vm-list | grep -A1 REAL | grep uuid | awk '{print $5}'
offline
[root@MYSERVER ]# echo $?
0


crts 11-03-2010 06:35 AM

Quote:

Originally Posted by genderbender (Post 4147881)
Yeah - that does seem accurate actually (works on my tests). I have two subsequent greps though, perhaps this is effecting the code :S

Code:

xe vm-list | grep -A1 NOTREAL | grep power | awk '{print $5}'
[root@MYSERVER ]# echo $?
0
xe vm-list | grep -A1 REAL | grep uuid | awk '{print $5}'
offline
[root@MYSERVER ]# echo $?
0


Actually, it is the return code of the last awk command that returns 0.

genderbender 11-03-2010 06:36 AM

Oh, suddenly it's clicking! Thanks :D Will google a bit before I ask my next obvious question :S

crts 11-03-2010 06:42 AM

Try also including PIPESTATUS in your google search.

genderbender 11-03-2010 09:36 AM

OK, managed to handle this with perl - however it doesn't work with my for loops now :(

genderbender 11-03-2010 06:38 PM

Gonna need some help with this, will post 'similar' code tomorrow but basically my oneliner enters a for loop which grabs a uuid (have some perl to echo a none zero exit code if theres no match) this uuid is then used in another for loop (again using perl for the none zero exit code thing) to list virtual server snapshots (specificall the snapshot uuid). This then reverts to a specified snapshot - essentially it's a one liner to rewind xen snapshots, but if insert incorrect info in either of my for loops the exit code is always zero - if I run the code outside the for loop the exit code is always nonezero. Hard to explain without an example... This is psuedocode, expect something which actually works tomorrow at some point:

Code:

for uuid in `list virtual servers | grep 'correct-server' | perl -alne '{ print $F[4] } END { exit($.==0) }'`;
        do
                for snapshotuuid in `list virtual snapshot | grep $uuid | grep snaoshotname | perl -alne '{ print $F[4] } END { exit($.==0) }'`;
                do
                        revert $uuid to $snapshotuuid;
                done;
        done;


genderbender 11-04-2010 05:09 AM

Code:


for UID in `xe vm-list | grep -B1 VMNAME | grep uuid | perl -alne '{ print $F[4] } END { exit($.==0) }'`; do for SNAP in `xe snapshot-list snapshot-of=$UID | grep -B1 SNAPSHOTNAME | grep uuid | perl -alne '{ print $F[4] } END { exit($.==0) }'`; do xe snapshot-revert uuid=$SNAP; done; done;

VMNAME and SNAPSHOTNAME are legitimate values. With the correct values my exit status is 0, with incorrect values - my exit status is still 0... I'm happy for people to find alternative methods of achieving the same thing, but it really needs to be as short as possible.

choogendyk 11-04-2010 06:29 AM

Quote:

Originally Posted by genderbender (Post 4147881)
Code:

xe vm-list | grep -A1 NOTREAL | grep power | awk '{print $5}'

In any sequence like that, the exit status after the sequence is going to be that of the last command in the sequence. No way around that. So, you have to break it up if you want an intermediate exit status.

Something like:
Code:

if xe vm-list | grep -A1 NOTREAL > scratch; then
  cat scratch | grep power | awk '{print $5}';
else
  ...
fi

The exit status of the `grep -A1 NOTREAL` controls the if, and it's output goes to the file scratch. Then in the next line you can continue with `cat scratch` piped to whatever else you wanted to do.

genderbender 11-04-2010 06:32 AM

Quote:

Originally Posted by choogendyk (Post 4148951)
In any sequence like that, the exit status after the sequence is going to be that of the last command in the sequence. No way around that. So, you have to break it up if you want an intermediate exit status.

Something like:
Code:

if xe vm-list | grep -A1 NOTREAL > scratch; then
  cat scratch | grep power | awk '{print $5}';
else
  ...
fi

The exit status of the `grep -A1 NOTREAL` controls the if, and it's output goes to the file scratch. Then in the next line you can continue with `cat scratch` piped to whatever else you wanted to do.

I solved this with my perl code above. I can do it without 'breaking it up'. The perl doesn't work with my loop though (each individual line does, but just not the loop itself).

catkin 11-04-2010 09:05 AM

crts gave good advice in post 7

genderbender 11-05-2010 09:09 AM

Quote:

Originally Posted by catkin (Post 4149077)
crts gave good advice in post 7

pipestatus was always 0 :(

The issue is the loop, the loop continues to function if the exit status is 1 :(

Code:

[root@localhost ~]# xe vm-list | grep -B1 WRONGVMNAME | grep uuid | perl -alne '{ print $F[4] } END { exit($.==0) }'
[root@localhost ~]# echo $?
1
[root@localhost ~]# xe snapshot-list snapshot-of=1234:1234:1234:1234 | grep -B1 WRONGNAME | grep uuid | perl -alne '{ print $F[4] } END { exit($.==0) }'
[root@localhost ~]# echo $?
1


ntubski 11-05-2010 12:56 PM

Code:

$ help for
for: for NAME [in WORDS ... ] ; do COMMANDS; done
...
    Exit Status:
    Returns the status of the last command executed.

From a few tests I ran, it seems that "last command" refers only to commands in the body of the loop (i.e. COMMANDS). I think the easiest way to solve this problem is to use a flag variable:
Code:

status=1
for uuid in ...
        do
                for snapshotuuid in ...
                do
                        revert $uuid to $snapshotuuid && status=0
                done;
        done;

exit $status



All times are GMT -5. The time now is 04:57 PM.