LinuxQuestions.org
Help answer threads with 0 replies.
Go Back   LinuxQuestions.org > Forums > Linux Forums > Linux - General
User Name
Password
Linux - General This Linux forum is for general Linux questions and discussion.
If it is Linux Related and doesn't seem to fit in any other forum then this is the place.

Notices


Reply
  Search this Thread
Old 03-18-2019, 10:01 AM   #1
nicedreams
Member
 
Registered: Jun 2003
Location: Phoenix, AZ
Posts: 92

Rep: Reputation: 15
Bash script that can read output of last command and pipe to it


I'm trying to write a bash script where I can send the error output using $? from the previous command ran from shell prompt and pipe that to my bash script which will decide what to do from there. Like how you pipe output to grep and it does it's thing.

The issue I'm having is that $? is only working from within the script and it won't find the output of last command before bash script was ran. So if I put $? at the beginning of my bash script $? always returns 0 since the bash script itself completed properly.

My script would see if $? is 0 and would run commands if successful. It would run a different set of command if $? was not 0.

In it's simple form:

ls -l ; error-processing.sh

if [ $? -eq 0 ]; then
echo "It worked"
else
echo "It didn't work"
fi
 
Old 03-18-2019, 10:11 AM   #2
berndbausch
Senior Member
 
Registered: Nov 2013
Location: Tokyo
Distribution: Redhat/Centos, Ubuntu, Raspbian, Fedora, Alpine, Cirros, OpenSuse/SLES
Posts: 2,853

Rep: Reputation: 738Reputation: 738Reputation: 738Reputation: 738Reputation: 738Reputation: 738Reputation: 738
The problem is that error-processing.sh runs in a different shell, therefore the $? in the script is not the exit code of the ls command. The only solution is running the code in the same shell as the ls command.

Try
Code:
ls -l
source error-processing.sh
 
Old 03-18-2019, 10:26 AM   #3
rtmistler
Moderator
 
Registered: Mar 2011
Location: MA, USA
Distribution: MINT Debian, Angstrom, SUSE, Ubuntu, Debian
Posts: 7,579
Blog Entries: 13

Rep: Reputation: 3104Reputation: 3104Reputation: 3104Reputation: 3104Reputation: 3104Reputation: 3104Reputation: 3104Reputation: 3104Reputation: 3104Reputation: 3104Reputation: 3104
I was thinking of an alias or a function call.

This one-line if test seems to work, but unsure how to make it an alias:
Code:
if [ $? -eq 0 ]; then echo "it worked"; else echo "it didn't work"; fi
 
Old 03-18-2019, 11:52 AM   #4
nicedreams
Member
 
Registered: Jun 2003
Location: Phoenix, AZ
Posts: 92

Original Poster
Rep: Reputation: 15
Quote:
Originally Posted by berndbausch View Post
The problem is that error-processing.sh runs in a different shell, therefore the $? in the script is not the exit code of the ls command. The only solution is running the code in the same shell as the ls command.

Try
Code:
ls -l
source error-processing.sh


Tried but didn't work. Still getting 0 every time and understand why, but was hoping a way around it. Guess it's time to finally learn python for this type of stuff.
 
Old 03-18-2019, 12:21 PM   #5
BW-userx
LQ Guru
 
Registered: Sep 2013
Location: MID-SOUTH USA
Distribution: Slackware 14.2 current / Linux Mint / Debian / Void Linux
Posts: 8,315

Rep: Reputation: 1741Reputation: 1741Reputation: 1741Reputation: 1741Reputation: 1741Reputation: 1741Reputation: 1741Reputation: 1741Reputation: 1741Reputation: 1741Reputation: 1741
Code:
#!/bin/bash

ls -l
source errorprocessing
if [ $? -eq 0 ]; then
echo "It worked"
else
echo "It didn't work"
fi
----

 ./checky
total 8
-rwxr-xr-x 1 userx userx 109 Mar 18 11:19 checky
-rwxr-xr-x 1 userx userx  34 Mar 18 11:19 errorprossing
mkdir: created directory '/goody'
It worked
userx@voided.net:~/Documents
$ ./checky
total 8
-rwxr-xr-x 1 userx userx 109 Mar 18 11:19 checky
-rwxr-xr-x 1 userx userx  30 Mar 18 11:20 errorprossing
mkdir: cannot create directory ‘/goody9’: Permission denied
It didn't work
are you putting something in your error-processing.sh to return an error?

Last edited by BW-userx; 03-18-2019 at 12:24 PM.
 
Old 03-18-2019, 04:17 PM   #6
scasey
Senior Member
 
Registered: Feb 2013
Location: Tucson, AZ, USA
Distribution: CentOS 7.6
Posts: 2,744

Rep: Reputation: 937Reputation: 937Reputation: 937Reputation: 937Reputation: 937Reputation: 937Reputation: 937Reputation: 937
Quote:
Originally Posted by nicedreams View Post
Tried but didn't work. Still getting 0 every time and understand why, but was hoping a way around it. Guess it's time to finally learn python for this type of stuff.
Near as I can tell
Code:
ls -l
will always be successful and return 0
I was only able to get a non-zero return with
Code:
ls -l /nosuchdir
 
Old 03-18-2019, 04:57 PM   #7
david.ledger
LQ Newbie
 
Registered: Nov 2009
Location: Gloucester UK
Posts: 5

Rep: Reputation: 1
Not sure what kind of error processing you're wanting to do, but saving the return code immediately after the command is the usual technique. You can then use the saved value as you wish.

Code:
ls -l
rc=$?
Then you write a script that takes an error code argument, and supply it with $rc.

Code:
errorprocessing $rc
OR

Code:
ls -l || errorprocessing
errorprocessing will only be run if the ls -l fails.


where errorprocessing is a script that first saves the value of $? and then processes the saved value.
 
1 members found this post helpful.
Old 03-18-2019, 06:52 PM   #8
randdeveloper
LQ Newbie
 
Registered: Jun 2013
Distribution: linux mint xfce
Posts: 27

Rep: Reputation: Disabled
Write a bash script that takes as an argument the command you want to run, run the command, then evaluate the command and process your evaluation:

report.sh
Code:
#!/bin/bash
$@
if [$? -eq 0]; then
 echo "success"
else
 echo "failed on error code: " $?
fi
Code:
./report.sh somecommand with any number of arguments
 
Old 03-18-2019, 07:09 PM   #9
freemedia2018
Member
 
Registered: Mar 2019
Distribution: various automated remasters
Posts: 100
Blog Entries: 1

Rep: Reputation: 50
Quote:
Originally Posted by nicedreams View Post
Like how you pipe output to grep and it does it's thing.
The trick is not getting the data from the pipe, it is getting the EOF to let you know it has received everything from the previous command.

I tried a few ways to capture EOF (Python makes it trivial with sys.stdin) using bash, finally for the demo I just told it what line is the last line. EOF would be better, because then it works with other commands that weren't made just for this command. (Like find | ./in where you don't know what the content will be.)

The echo command writes to stdout and the read command gets information from stdin.

You can do the same in Python with print() and sys.stdin().

The following is not a script, it is typed at the command line. You can certainly cut and paste it into scripts.

Code:
$ cat > out
#!/bin/bash
echo 1
echo 2
echo 3

$ cat > in
#!/bin/bash
while [[ "$p" != "3" ]]
do read p
echo $p
done

$ chmod 755 in 
$ chmod 755 out
$ ./out | ./in
1
2
3
$

Last edited by freemedia2018; 03-18-2019 at 07:10 PM.
 
Old 03-18-2019, 08:08 PM   #10
padeen
Member
 
Registered: Sep 2009
Location: Perth, W.A.
Distribution: Slackware, Debian, Gentoo, FreeBSD, OpenBSD
Posts: 205

Rep: Reputation: 40
just to note, `ls` isn't a good test case because it doesn't return an error when you think it should. Try a different command. Also, you might be able to get what you want by redirecting /dev/stderr to another file descriptor (named pipe?) which blocks, then passing the fd to the script which reads it. Dunno, thinking aloud here, might work. Or piping stderr to a blocking cat/tee, there is one out there, I used it years ago. But with these methods you would have to test for the presence of text on the fd to check if an error actually occurred.
 
Old 03-18-2019, 08:17 PM   #11
freemedia2018
Member
 
Registered: Mar 2019
Distribution: various automated remasters
Posts: 100
Blog Entries: 1

Rep: Reputation: 50
I should mention that if you only want to process a single line of text, this works:

Code:
$ cat > out
#!/bin/bash
echo hello there!

$ cat > in
#!/bin/bash
read p
echo the other script told me: $p

$ ./out | tail -1 | ./in
 
Old 03-18-2019, 08:42 PM   #12
JeremyBoden
Senior Member
 
Registered: Nov 2011
Location: London, UK
Distribution: Debian
Posts: 1,480

Rep: Reputation: 303Reputation: 303Reputation: 303Reputation: 303
Is the history command of any use?

For example !-1 will re-execute the prior command line.
Probably, not exactly what you want.
 
Old 03-18-2019, 11:15 PM   #13
ehartman
Member
 
Registered: Jul 2007
Location: Delft, The Netherlands
Distribution: Slackware
Posts: 469

Rep: Reputation: 198Reputation: 198
Quote:
Originally Posted by nicedreams View Post
I'm trying to write a bash script where I can send the error output using $? from the previous command ran from shell prompt and pipe that to my bash script which will decide what to do from there.
Why don't you pass the exit code to the script as an argument, like this
./script $?

Then you won't have the problem that $? is changing all of the time (as $1 does NOT).

Code:
if [ -z "$1" ]
then  echo "No exit code given"
      exit 1
elif [ $1 = 0 ]
then  echo "Succesfull execution!"
      <some other things to do>
else  echo "Command returned error code $1"
fi
 
Old 03-19-2019, 05:01 AM   #14
josephj
Member
 
Registered: Nov 2007
Location: Northeastern USA
Distribution: kubuntu
Posts: 180

Rep: Reputation: 95
david.ledger got it right

There are a lot of ways to do things in Linux and bash and some are simpler than others.

Since $? gets set by the most recently run command, it's perishable, so it's often best to save it in a variable. Then, you can do whatever else you need to do and the value will be preserved until you get around to looking at it. It's also handy if you want to report its value as part of error processing.

Once you have it, there are lots of ways to use it. You can pass it as an argument to another script (or function) as david.ledger does. You can export it so called scripts have it available in their environments. You can even write it to a file, pipe, or named pipe. Of course, you can just use it in the current script.

I'm fond of the following construction:

Code:
some_command
rc=$?
if (( rc ))
then
  ## process the error here
  echo "some_command failed with error code [$rc]"
fi
If the error condition has a particular meaning in the code, you can name the variable to reflect that:

Code:
file_reading_command
read_error=$?
if (( read_error ))
...
This is particularly useful if you have to deal with multiple conditions because this makes each one human readable.

Most of the other answers add complexity which opens the possibility for errors.
 
Old 03-19-2019, 08:04 AM   #15
DGPickett
LQ Newbie
 
Registered: Jan 2012
Posts: 12

Rep: Reputation: Disabled
One can run:

XXxX >so.txt 2> se.txt ; echo $? >rc

Now you have complete access to stout, syderr, and the return code. Using variables poses the problem of which subshells/processes inherit even exported variables. Pipes are nice, but only support one stream. Named pipes can support many streams but the processes cannot see what each other gets. You could encode each stream for combination in one pipe, but then you must decode the stream. BTW, ">(...)" is just a named pipe into a subshell.

She'll programming has its challenges. Process isolation can be enemy or friend. In a multithreaded single process, threads can manage command running and return, standard out, standard in, standard error into/from variables or files visible to all threads, but in return for the visibility you have thread management and state communication challenges. TANSTAAFL
 
  


Reply


Thread Tools Search this Thread
Search this Thread:

Advanced Search

Posting Rules
You may not post new threads
You may not post replies
You may not post attachments
You may not edit your posts

BB code is On
Smilies are On
[IMG] code is On
HTML code is Off



Similar Threads
Thread Thread Starter Forum Replies Last Post
Get first day of last month and last day of last month in bash xowl Linux - Software 18 02-09-2017 09:49 AM
How can I pipe output of a command into arguments of a script HGeneAnthony Linux - General 3 12-26-2007 06:24 AM
Read the output from a pipe with bash ? fluppi Linux - Software 3 01-13-2004 12:59 PM

LinuxQuestions.org > Forums > Linux Forums > Linux - General

All times are GMT -5. The time now is 11:49 AM.

Main Menu
Advertisement
My LQ
Write for LQ
LinuxQuestions.org is looking for people interested in writing Editorials, Articles, Reviews, and more. If you'd like to contribute content, let us know.
Main Menu
Syndicate
RSS1  Latest Threads
RSS1  LQ News
Twitter: @linuxquestions
Facebook: linuxquestions Google+: linuxquestions
Open Source Consulting | Domain Registration