LinuxQuestions.org
Download your favorite Linux distribution at LQ ISO.
Home Forums Tutorials Articles Register
Go Back   LinuxQuestions.org > Forums > Linux Forums > Linux - Newbie
User Name
Password
Linux - Newbie This Linux forum is for members that are new to Linux.
Just starting out and have a question? If it is not in the man pages or the how-to's this is the place!

Notices


Reply
  Search this Thread
Old 10-22-2011, 08:18 AM   #1
veeruk101
Member
 
Registered: Mar 2005
Distribution: Ubuntu 12.04 LTS
Posts: 249

Rep: Reputation: 16
Testing against output of stderr in bash


I need to do something in the event that 'svn status' command returns the following:

svn: warning: '/path/to/file' is not a working copy

Now ridiculously (in the latest version of svn too) if I do 'echo $?' it returns 0 even though this is an error situation, so I can't test against the return value. I need to do a string comparison to see if the output starts with "svn: warning: ". So I tried the following, which printed 'no warning' when it should have printed warning:

Code:
MSG=$(svn status /path/to/file)
if [[ $MSG == "svn: warning: "* ]]; then
  echo warning
else
  echo no warning
fi
Then I figured maybe it's printing to stderr instead of stdout, so I tried the following, which worked:

Code:
MSG=$(svn status /path/to/file 2>&1)
But then it was still printing to the screen. Because this is being run from a script and the output doesn't need to be shown, I tried to suppress it by doing the following, but then it again printed 'no warning', and I don't know why.

Code:
MSG=$(svn status /path/to/file >/dev/null 2>&1)
I'm new to all this output redirection stuff, so I'm sure I'm making a basic error. If someone could point out my mistake I'd appreciate it. Thanks
 
Old 10-22-2011, 08:47 AM   #2
colucix
LQ Guru
 
Registered: Sep 2003
Location: Bologna
Distribution: CentOS 6.5 OpenSuSE 12.3
Posts: 10,509

Rep: Reputation: 1983Reputation: 1983Reputation: 1983Reputation: 1983Reputation: 1983Reputation: 1983Reputation: 1983Reputation: 1983Reputation: 1983Reputation: 1983Reputation: 1983
Code:
if [[ $MSG == "svn: warning: "* ]]
After the == comparison operator, the * is interpreted literally. You need the =~ regexp operator:
Code:
if [[ $MSG =~ "svn: warning: " ]]
and yes, redirecting standard error to standard output is the right way to go.
 
Old 10-22-2011, 09:09 AM   #3
catkin
LQ 5k Club
 
Registered: Dec 2008
Location: Tamil Nadu, India
Distribution: Debian
Posts: 8,578
Blog Entries: 31

Rep: Reputation: 1208Reputation: 1208Reputation: 1208Reputation: 1208Reputation: 1208Reputation: 1208Reputation: 1208Reputation: 1208Reputation: 1208
Quote:
Originally Posted by veeruk101 View Post
I'm new to all this output redirection stuff, so I'm sure I'm making a basic error. If someone could point out my mistake I'd appreciate it. Thanks
What you showed looks fine. Some programs write specifically to the terminal instead of stderr so redirecting stdout and stderr does not affect them.

Here's a demo at the command prompt:
Code:
$ cat ./LQ-4505161.sh
#!/bin/bash
unalias -a
echo 'stdout' >&1
echo 'stderr' >&2
echo 'tty' > /dev/tty
$ ./LQ-4505161.sh >/dev/null 2>&1
tty
A workaround is to use the script command to capture what is sent to the terminal and examine that for the error message. script's output includes control codes.
 
1 members found this post helpful.
Old 10-22-2011, 06:23 PM   #4
veeruk101
Member
 
Registered: Mar 2005
Distribution: Ubuntu 12.04 LTS
Posts: 249

Original Poster
Rep: Reputation: 16
Few follow up questions:

Is there a difference between the 2 following statements (note the extra space)? Because I've seen some one way and some the other way.

echo text >/dev/null
echo text > /dev/null

OR

echo text >&1
echo text > &1


Is there a quick way to tell whether some text that's shown on the screen was printed to stderr vs stdout? Meaning, is there a way I can configure the terminal to output stderr text in a different colour, for example?


I tried the demo script shown in the previous message and yes writing to /dev/tty did print to the terminal. But my terminal output /dev/pts/4 when I ran the 'tty' command. So then I tried writing to /dev/pts/4 and that worked (in fact writing to /dev/pts/3 printed to the OTHER terminal, which was interesting.) But then I tried writing to /dev/console and nothing happened. So what is /dev/console, and /dev/tty, and why did writing to /dev/tty output to /dev/pts/4 but writing to /dev/console do nothing?
 
Old 10-23-2011, 04:38 AM   #5
David the H.
Bash Guru
 
Registered: Jun 2004
Location: Osaka, Japan
Distribution: Arch + Xfce
Posts: 6,852

Rep: Reputation: 2037Reputation: 2037Reputation: 2037Reputation: 2037Reputation: 2037Reputation: 2037Reputation: 2037Reputation: 2037Reputation: 2037Reputation: 2037Reputation: 2037
Redirection certainly is a rather complex subject. I'm still working out all its mysteries myself.

http://tldp.org/LDP/abs/html/io-redirection.html
http://wiki.bash-hackers.org/syntax/redirection

Spaces between a redirection and a filename don't have any effect, but I believe that you can't have any between a redirection and an file descriptor reference, such as 2>&1.

(Tip: one thing that confused me for a long time is that &1 doesn't mean "stdout", it means "the current target of FD1". "&" specifies a reference to a file descriptor; kind of like a variable that holds the current setting, if you will.).

Also, a space is necessary when redirecting to or from a process substitution in bash.

http://mywiki.wooledge.org/ProcessSubstitution

Speaking of which, you can use process substitution with something like this script I just worked up to colorize your stderr output. The example is in the header info.

Code:
#!/bin/bash

###########################################################################################
# colorizeit.bash
#
# A small script that colorizes input fed to it from stdin.
# It can take an optional color argument (case insensitive).
# If the argument is "list" then a list of available colors is printed.
# It requires bash v.4 due to the use of a associate array and lowercase expansion.
#
# Usage example: print the stderr of a command in red, (uses bash's process substitution )
#
#	command 2> >( colorizeit.bash red )
#
###########################################################################################

# set the default color and force the input argument to lowercase.
default="red"
color="${1,,}"

#define the color codes used in an associative array.

declare -A colors
colors=(

	[reset]='\e[0m'		[black]='\e[1;30m'	[red]='\e[1;31m'
	[green]='\e[1;32m'	[yellow]='\e[1;33m'	[blue]='\e[1;34m'
	[magenta]='\e[1;35m'	[cyan]='\e[1;36m'	[white]='\e[1;37m'

)

# If argument is "list", then print list of available colors, and exit.
# Else cat the input with the chosen color enabled.

if [[ "$1" == "list" ]]; then

	echo "${!colors[@]}"
	exit 1

else

	echo -en "${colors[${color:-$default}]}"
	cat
	echo -en "${colors[reset]}"

fi

exit
 
Old 10-23-2011, 06:41 AM   #6
catkin
LQ 5k Club
 
Registered: Dec 2008
Location: Tamil Nadu, India
Distribution: Debian
Posts: 8,578
Blog Entries: 31

Rep: Reputation: 1208Reputation: 1208Reputation: 1208Reputation: 1208Reputation: 1208Reputation: 1208Reputation: 1208Reputation: 1208Reputation: 1208
Quote:
Originally Posted by veeruk101 View Post
Is there a difference between the 2 following statements (note the extra space)? Because I've seen some one way and some the other way.

echo text >/dev/null
echo text > /dev/null
According to bash shell operation, bash parses its input into words and operators separated by metacharacters. Both space and > are metacharacters so the two forms are equivalent, as would echo text>/dev/null be.
Quote:
Originally Posted by veeruk101 View Post
OR

echo text >&1
echo text > &1
By the same parsing rules they should also be equivalent but experimentation shows they are not! Perhaps the whole redirection group, not just the > is treated as a metacharacter but it is more likely that I have misunderstood than that the list of metacharacters in the bash reference is wrong.
Quote:
Originally Posted by veeruk101 View Post
Is there a quick way to tell whether some text that's shown on the screen was printed to stderr vs stdout? Meaning, is there a way I can configure the terminal to output stderr text in a different colour, for example?
No quick way. Relevant discussion on Greg's Wiki here and here. If you have two screens then
Code:
command > /dev/pts/3 2> /dev/pts/4
Quote:
Originally Posted by veeruk101 View Post
So what is /dev/console, and /dev/tty, and why did writing to /dev/tty output to /dev/pts/4 but writing to /dev/console do nothing?
/dev/console is the terminal device used during boot. AFAIK only root can write to it.
/dev/tty is a convenience device which maps to the same terminal as the tty command reports.
 
  


Reply



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 Off
HTML code is Off



Similar Threads
Thread Thread Starter Forum Replies Last Post
bash output stderr to 2 files and stdout vascot Linux - Software 1 04-05-2011 08:04 AM
[SOLVED] Redirecting output from stderr mwilner Linux - Newbie 5 12-02-2010 07:25 AM
How to get stderr output when using a ::system() call tmc3011 Programming 2 01-25-2008 04:17 AM
Using stderr output for decision making MeelaPo Programming 6 10-20-2004 08:21 PM
captumring output from STDERR rajatgarg Programming 2 01-30-2004 10:35 AM

LinuxQuestions.org > Forums > Linux Forums > Linux - Newbie

All times are GMT -5. The time now is 02:39 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
Open Source Consulting | Domain Registration