POSIX shell (sh) redirect stderr to stdout and capture stderr and stdout into variables - TagMerge
4POSIX shell (sh) redirect stderr to stdout and capture stderr and stdout into variablesPOSIX shell (sh) redirect stderr to stdout and capture stderr and stdout into variables

POSIX shell (sh) redirect stderr to stdout and capture stderr and stdout into variables

Asked 5 months ago
0
4 answers

Well I'm doing this in busybox's ash shell and my options are rather limited, but this is what I came up with that works.

tmpfile=/tmp/some_prefix_stderr.$$
out=$(my_cmd) 2>$tmpfile
result=$?
err=$(cat $tmpfile)
rm $tmpfile

It's not the prettiest, but it works. In general, replace some_prefix with something specific to help avoid collisions, but just having the PID on there will solve that unless you are running multiple threads.

If you can rely upon your program exiting non-zero when there's something to show in stderr, you can simplify it a little:

tmpfile=/tmp/some_prefix_stderr.$$
if ! out=$(my_cmd) 2>$tmpfile; then
    # specific behavior here
    cat $tmpfile >&2
fi
rm $tmpfile

This is all POSIX compliant. Just be sure to clean up your temp file.

Source: link

0

What one would expect ls -l file missingfile >out.txt 2>out.txt to output:
-rw-r--r-- 1 blah blah 0 Jun  3 13:18 file
ls: cannot access 'missingfile': No such file or directory
What is actually output:
-rw-r--r-- 1 blah blah 0 Jun  3 13:18 file
le or directory

Source: link

0

Je voudrais rediriger stderr vers stdout afin qu'un terminal les imprime tous les deux lors de l'exécution d'une commande, mais je voudrais également les capturer tous les deux dans des variables distinctes. J'ai réussi à y parvenir dans Bash (version 4.4.20(1)-release):
#!/bin/bashecho "terminal:"{ err="$(find / -maxdepth 2 -iname 'tmp' -type d 2>&1 1>&3 3>&- | tee /dev/stderr)"; ec="$?"; } 3>&1 | tee /dev/fd/4 2>&1; out=$(cat /dev/fd/4)echo "stdout:" && echo "$out"echo "stderr:" && echo "$err"
cela donne souhaité:
terminal:find: '/root': Permission denied/tmp/var/tmpfind: '/lost+found': Permission deniedstdout:/tmp/var/tmpstderr:find: '/root': Permission deniedfind: '/lost+found': Permission denied
mais j'ai un problème pour convertir ce script en POSIX sh/bin/sh
#!/bin/shecho "terminal:"{ err="$(find / -maxdepth 2 -iname 'tmp' -type d 2>&1 1>&3 3>&- | tee /dev/stderr)"; ec="$?"; } 3>&1 | tee /dev/fd/4 2>&1; out=$(cat /dev/fd/4)echo "stdout:" && echo "$out"echo "stderr:" && echo "$err"
donne:
terminal:tee: /dev/fd/4: No such file or directoryfind: '/root': Permission denied/tmp/var/tmpfind: '/lost+found': Permission deniedcat: /dev/fd/4: No such file or directorystdout:stderr:
Eh bien, je le fais dans le ashshell de busybox et mes options sont plutôt limitées, mais c'est ce que j'ai trouvé qui fonctionne.
tmpfile=/tmp/some_prefix_stderr.$$out=$(my_cmd) 2>$tmpfileresult=$?err=$(cat $tmpfile)rm $tmpfile

Source: link

0

I would like to redirect stderr to stdout so a terminal prints both of them during a command execution but I would like also to capture both of them into separate variables. I managed to achieve that in Bash (version 4.4.20(1)-release):
#!/bin/bash

echo "terminal:"
{ err="$(find / -maxdepth 2 -iname 'tmp' -type d 2>&1 1>&3 3>&- | tee /dev/stderr)"; ec="$?"; } 3>&1 | tee /dev/fd/4 2>&1; out=$(cat /dev/fd/4)
echo "stdout:" && echo "$out"
echo "stderr:" && echo "$err"
that gives desired:
terminal:
find: ‘/root’: Permission denied
/tmp
/var/tmp
find: ‘/lost+found’: Permission denied
stdout:
/tmp
/var/tmp
stderr:
find: ‘/root’: Permission denied
find: ‘/lost+found’: Permission denied
but I have a problem converting that script into POSIX sh /bin/sh
#!/bin/sh

echo "terminal:"
{ err="$(find / -maxdepth 2 -iname 'tmp' -type d 2>&1 1>&3 3>&- | tee /dev/stderr)"; ec="$?"; } 3>&1 | tee /dev/fd/4 2>&1; out=$(cat /dev/fd/4)
echo "stdout:" && echo "$out"
echo "stderr:" && echo "$err"
gives:
terminal:
tee: /dev/fd/4: No such file or directory
find: ‘/root’: Permission denied
/tmp
/var/tmp
find: ‘/lost+found’: Permission denied
cat: /dev/fd/4: No such file or directory
stdout:

stderr:
Here is my script:
#!/bin/sh
purple='\e[0;35m'
red='\033[0;31m'
neutre='\e[0;m'
echo "${purple}CREATE USER${neutre}"
if grep "flush:" /etc/group > /dev/null;
then
    echo "${red}GROUP FLUSH ALREADY EXIST${neutre}"
else
    groupadd -r flush
fi
if grep "flush:" /etc/passwd > /dev/null;
then
    echo "${red}USER FLUSH ALREADY EXIST${neutre}"
else
    useradd -g flush -m flush -s /bin/bash -d /home/flush
    echo "flush:$PASSWORD" | chpasswd
    echo "root:$PASSWORD" | chpasswd
    chown -R flush:flush /home/flush
    chgrp -R flush /var/www/html
    chmod -R 700 /home/flush
fi
if grep "flush-user:" /etc/group > /dev/null;
then
    echo "${red}GROUP FLUSH-USER ALREADY EXIST${neutre}"
else
    groupadd -g 501000 -r flush-user
fi
if grep "flush-user:" /etc/passwd > /dev/null;
then
    echo "${red}USER FLUSH-USER ALREADY EXIST${neutre}"
else
    if ls /bin/rbash > /dev/null
    then
        echo "${red}rbash exist !${neutre}"
        rm -Rf /bin/rbash
        ln -s /bin/bash /bin/rbash
    else
        ln -s /bin/bash /bin/rbash
    fi
    useradd -rm -u 501000 -g flush-user -s /bin/rbash -c "Unprivileged User" -d /home/flush-user/ flush-user
    echo "flush-user:flush-user" | chpasswd
    mkdir -p /home/flush-user/bin
    chown -R flush-user:flush-user /home/flush-user/
    echo PATH=/home/flush-user/bin > /home/flush-user/.bash_profile
#     export PATH=/home/flush-user/bin
    chown root:root /home/flush-user/.bash_profile
    chmod 755 /home/flush-user/.bash_profile
fi
mkdir -p var/cache var/log

Source: link

Recent Questions on sh

    Programming Languages