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.
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 Aug 28 '23 at 19:29