Home > Software design >  Why does redirecting stderr to file work, but redirecting to stderr to stdout does not work? (linux
Why does redirecting stderr to file work, but redirecting to stderr to stdout does not work? (linux

Time:08-28

I have been having some issues redirecting stderr to stdout with linux shell The following does work:

$ sh -c "./some-binary" < ./my_input 2>test.txt
$ cat test.txt
Error
$

(The output is saved to file)

But this does not for me:

$ sh -c "./some-binary" < ./my_input 2>&1
$

(There is not output)

I don't understand why this is. Could someone please clarify?

Note: I have tried with both bash and sh and there is the same behavior

For context: I am trying to run this binary and capture the output from an existing program

Edit: I think it is using /dev/fd/2 for stderr in case that has any effect

Edit 2: I dockerized the issue to make it repoducable: Dockerfile:

FROM ubuntu:focal-20220801
RUN apt update
RUN apt install wget freeglut3 libxft2 libxext6 libxinerama1 libxcursor-dev -y
RUN wget https://github.com/grapa-dev/grapa/raw/master/bin/grapa-ubuntu64.tar.gz
RUN tar -xvf grapa-ubuntu64.tar.gz -C /usr/local/bin
docker run -it $(docker build -q .) /bin/bash
root@db9abeca8b5f:/# grapa -ccmd '$file().set("/dev/fd/2","Error\n")' >/dev/null 2>test.txt
root@db9abeca8b5f:/# cat test.txt 
Error
root@db9abeca8b5f:/# grapa -ccmd '$file().set("/dev/fd/2","Error\n")' >/dev/null 2>&1      
root@db9abeca8b5f:/# 

CodePudding user response:

The redirection is fine. Grapa just doesn't support canonical file IO.

Here's the documentation for Grapa's $file().set:

Updates the column in a row. By default the $VALUE column is updated. But an alternate column can be specified.

As suggested, it's meant for structured file IO. Here's the source code:

        u64 size = pValue.mLength;
        err = mFile.SetSize(size);
        err = mFile.Write(0, 0, 0, size, pValue.mBytes);
        mFile.Purge(size, 1);
        err = mFile.Close();

And the Write function:

    err = GetSize(fileSize);
    if (err)
        return((GrapaError)-1);
    [...]
    endPos = lseek(mFp, (blockPos*blockSize   offset), SEEK_SET);
    if (endPos != (blockPos*blockSize   offset))
        return((GrapaError)-1);

As you can see, it strongly assumes the file is seekable, and bails if it isn't. This means you can't use this function to write to terminals, pipes, or anything that's not a basic file.

The class says "This class/libraries will be enhanced over time to support navigating data types beyond the file system and the grapa database". You can consider filing a feature request.

  • Related