-1

Pipe (|) and redirections (<, <<, >, >>) both using standard streams (stdin, stdout, stderr), but although only pipe can keep sudo privileges, why?

Works:

sudo echo "hello" | tee /root/test

Doesn't work:

sudo echo "hello" > /root/test
1
  • 3
    sudo echo "hello" | tee /root/test doesn't work to access the file if sudo is needed for that. In each of the cases, consider which program is opening the file?
    – ilkkachu
    Commented Aug 28, 2023 at 19:29

2 Answers 2

1

Pipe (|) and redirections (<, <<, >, >>) both using standard streams (stdin, stdout, stderr), but altough only pipe can keep sudo prividgles, why?

That's simply not true. You must be mixing things up

sudo echo "hello" | tee /root/test

here echo is run as root, but tee is run as your current user, which doesn't seem to be root.

This would be different

echo "hello" | sudo tee /root/test

here, the tee program is executed as root, and hence gets access to /root/test as file

3
  • Oh, I was so dumb...
    – linuxer
    Commented Aug 28, 2023 at 20:52
  • 1
    @linuxer Don't be hard on yourself. It is surprisingly easy to assume sudo applies to the complete command line. Commented Aug 29, 2023 at 8:29
  • Yes! Paul is right, I can very much understand how you could assume that. Commented Aug 29, 2023 at 9:11
0

Redirection (>, <, etc) and piplines (|, etc) are initialized by the parent process before any of your commands is run.

Once the parent process decides to run something, e.g. sudo ls /root | grep test, it creates two processes, setting their Standard I/O Steams (STDIN,STDOUT, STDERR) appropriately.

For the process that will tun sudo, its STDOUT is connected to the STDIN of the process that will run grep.

After this setup (using the parent process's UID:GID) the sudo and grep binaries are loaded into their processes and executed.

Programs can simply read STDIN, write STDOUT, and send errors to STDERR, and leave the "plumbing" to the parent process.

This is a major design feature of Unix/Linux. I've programmed systems with Job Control Languages that made me specify all those inter-program connections via temporary storage. Ugh.

14
  • Before? If I run e.g. sudo ls /root | grep test, how parent process can know the output before sudo ls /root is ran?
    – linuxer
    Commented Aug 29, 2023 at 16:30
  • @linuxer Expanded my answer with a slightly more detailed, handwavey explation of How It Works.
    – waltinator
    Commented Aug 29, 2023 at 17:13
  • Very good explanation, but are you sure that bash initializes all redirection and pipeslines before any binary is executed? AFAIK bash doesn't limit the length of the commands so pipelines can be hunderds. Then IMO is more reasonable that bash run firstly ls command, fork() new process, copy the ls commands stdout to new process stdin, exec() grep "in" that new process. And yeah, is the way, that you explained or this me, grep doesn't get sudo privileges ...I was just stupid :D
    – linuxer
    Commented Aug 29, 2023 at 17:36
  • @linuxer, yes, it's the shell that processes redirections, and they're processed before the commands involved are executed. But the shell does fork a new child process first, so it can set up the redirections there, and then execute the command to run in that child process. Also the shell doesn't copy or otherwise touch any data that passes between the two. It just sets up the connection. I can't tell what you're referring with "the length of the commands" in the context of pipes.
    – ilkkachu
    Commented Aug 29, 2023 at 21:09
  • @linuxer Everything has limits, that's why we have xargs. Do: xargs --show-limits
    – waltinator
    Commented Aug 31, 2023 at 0:33

Not the answer you're looking for? Browse other questions tagged .