Is there any way to redirect err to a variable or not?

i am wrighting a script

ping=$( ping -c 2  $Host | grep 'received' | awk -F',' '{ print $2 }' | awk '{ print $1 }'  ) 2 >> $err

echo "$ping $err"

but it doesn work
is there any way to redirect err to a variable
ive tried to google but no luck ..
Maybe there is another way to do it

if i put file in works

ping=$( ping -c 2  $Host | grep 'received' | awk -F',' '{ print $2 }' | awk '{ print $1 }'  ) 2 >> /root/errors.log

echo "$ping $err"

But i need it in separate varible not file

In sqm-scripts we use the following construct successfully:

LAST_ERROR=$( ${CMD_BINARY} "$@" 2>&1 )

May this will also work fotr your case?

So do the assignment of 2 to a variable inside the $( ) and echo that variable back....

You could use:

{ var="$( { command; } 2>&1 1>&3 3>&- )"; } 3>&1;

Then $? has the command return value and $var has stderr.

If you switch to bash you could use this formulation:

#!/bin/bash
exec 3>&1
coproc SEDo ( sed "s/^/STDOUT: /" >&3 )
exec 4>&2-
coproc SEDe ( sed "s/^/STDERR: /" >&4 )
eval $@ 2>&${SEDe[1]} 1>&${SEDo[1]}
eval exec "${SEDo[1]}>&-"
eval exec "${SEDe[1]}>&-"

Won't this retain a mixture of the stdout of the command and stderr?

1 Like

Yes, the example was not meant to solve his problem fully, but just show that the redirection should happen inside the $( ) part.

2 Likes

For capturing both stdout and stderr, I think this formulation looks promising:

OUTPUT=`{ ERROR=$(command 2>&1 1>&$out); } {out}>&1`

But looking at your command from the first post you set up several pipes - presumably to capture the number of ping responses? So what do you want to capture any errors from? The ping command itself?

If so, then this formulation should provide what you desire:

OUTPUT=`{ ERROR=$(ping -c 2  $Host 2>&1 1>&$out); } {out}>&1 | grep 'received' | awk -F',' '{ print $2 }' | awk '{ print $1 }'`

Please advise, and if this post solves your query then please consider marking it as the 'solution' for this thread for the benefit of any future readers.

Did the above work for you @ZebraOnPC?

1 Like

i tried to adapt the script using your code but no luck

Host="ya.ru"

OUTPUT=`{ ERROR=$(ping -c 2  $Host 2>&1 1>&$out); } {out}>&1 | grep 'received' | awk -F',' '{ print $2 }' | awk '{ print $1 }'`

echo "$OUTPUT and $ERROR"

console

root@my:~# /root/test.sh
/root/test.sh: line 29: syntax error: bad fd number
 and
root@my:~#

curently i am just redirect 2 to a file
but it would give more option if i could get it in varible

You're not using bash so just change '$out' to '3' and 'out' to '3'.

ive changed it like this

....

OUTPUT=`{ ERROR=$(ping -c 2  $Host 2>&1 1>3); } {3}>&1 | grep 'received' | awk -F',' '{ print $2 }' | awk '{ print $1 }'`

....

console

(ya.ru)
root@my:~# /root/test.sh
 and
(yac.3ru)
root@my:~# /root/test.sh
 and

root@my:~#

You dropped an '&'.

1 Like

... and. @ZebraOnPC? Did it work?

 i tried like this
OUTPUT=`{ ERROR=$(ping -c 2  $Host 2>&1 1>&3); } {3}>&1 | grep 'received' | awk -F',' '{ print $2 }' | awk '{ print $1 }'`
 

and like this 
OUTPUT=`{ ERROR=$(ping -c 2  $Host 2>&1 1>&3); } {&3}>&1 | grep 'received' | awk -F',' '{ print $2 }' | awk '{ print $1 }'`



the result is the same , epmpty variables
well this works it shows both outputs

ERROR=$(ping -c 2  $Host 2>&1)

but if like this

ERROR=$(ping -c 2  $Host 2>&1 1>&3)

output

root@my:~# /root/test.sh
 and /root/test.sh: line 30: 3: Bad file descriptor
root@my:~#

Also this one would work

pinga=$( ping -c $Numba $Host 2>&1)
num=$( echo -e $pinga  | grep 'received' | awk -F',' '{ print $2 }' | awk '{ print $1 }' )

	if  [ -z $num ]; then 
echo "pinga ==  $pinga =="
else
echo "num == $num =="
      fi

but this script is wrong on at least 2 lvls
some programs can give output and erors at the same time
grep word can be in erors and output

I wonder why this doesn't work.

Not sure why the first one doesn't work.

I tested in bash and it worked fine.

Maybe try:

OUTPUT=`{ ERROR=$(ping -c 2  $Host 2>&1 1>&3); } 3>&1 | grep 'received' | awk -F',' '{ print $2 }' | awk '{ print $1 }'`

OUTPUT=`{ ERROR=$(ping -c 2  $Host 2>&1 1>&3); } 3>&1 | grep 'received' | awk -F',' '{ print $2 }' | awk '{ print $1 }'`


echo "=== $OUTPUT === $ERROR === "


root@my:~# /root/test.sh
=== 2 ===  ===
root@my:~# /root/test.sh
===  ===  ===
root@my:~#

it doesnt show errors

Are you looking for the most complicated solution?

If you need stderr stored into a variable, just store the contents of the file into a variable.

root@Home:~# OUTPUT=$(ls file1 file2 2>/tmp/stderr); ERROR=$(cat /tmp/stderr); echo "OUTPUT: $OUTPUT"; echo "ERROR: $ERROR"
OUTPUT: file1
ERROR: ls: file2: No such file or directory

@pavel looks like file descriptor 3 in the formulation above hadn't been opened. So how about:

mkfifo /tmp/fifo
exec 3>/tmp/fifo
OUTPUT=`{ ERROR=$(ping -c 2  $Host 2>&1 1>&3); } 3>&1 | grep 'received' | awk -F',' '{ print $2 }' | awk '{ print $1 }'`

Or alternatively:

OUTPUT=`{ ERROR=$(ping -c 2  $Host 2>&1 1>/tmp/stdout); } /tmp/stdout>&1 | grep 'received' | awk -F',' '{ print $2 }' | awk '{ print $1 }'`
root@my:~# /root/test.sh
^C/root/test.sh: line 18: can't create /tmp/fifo: Interrupted system call

root@my:~#


root@my:~# /root/test.sh
mkfifo: /tmp/fifo: File exists
^C/root/test.sh: line 20: can't create /tmp/fifo: Interrupted system call

root@my:~#

well, googling about this subject didnt gave much too. i gues there is no way to make it workble in ash

Absolutely possible. Just requires a little perseverance.

the qwestion is why it is so hard all that needs is redirect 2 in a variable not in file
it actually works if it redirect to a file...