Both cat and strings, and most similar utilities¹, read a little bit of input at a time, process it, then read more input, and so on. So in your case, cat only reads what less displays, plus a little more that's in transit.
In more detail, the basic operation of cat is:
- Reserve a few kilobytes of memory for use as a buffer.
- While there's more input available:
- Read up to N bytes of input into the buffer. (This overwrites data that was written out in a previous cycle.)
- Write the buffer content to the output.
The write operation blocks until there's a place to copy the output. When the output of a pipe, the pipe itself consumes a little memory in the kernel, which is called the pipe buffer. Once that's full, if cat tries to write to the pipe, the write attempt blocks until there's room. There can be room in the pipe buffer when the process on the read end of the pipe reads some data.
The strings program works in the same way as cat, except that it doesn't copy its whole input, only selected parts.
The less program works a bit differently: it keeps everything that it's read in memory. It doesn't recycle its buffer, it keeps growing it as long as more input keeps coming in. The read part is similar, however, in that less only reads data when it needs it: it only reads up to the last line that it displays, plus a little more that it reads in anticipation if available.
So when you run sudo cat /dev/sda | strings | less, what's been read from /dev/sda consists of:
- Data that
less has already displayed (or scrolled past).
- Up to a few kB of data that
less has read but not yet displayed.
- Up to a few kB in the pipe buffer between
strings and less.
- Up to a few kB in the memory of
strings.
- Up to a few kB in the pipe buffer between
cat and strings.
- Up to a few kB in the memory of
cat.
You can watch when each program reads and writes data by tracing its system calls:
sudo strace -e read,write -o cat.strace cat /dev/sda | strace -e read,write -o cat.strace strings | strace -e read,write -o less.strace less
and watch the *.strace files. You can also check how much cat has read by checking the file offset, for example with lsof -p1234 or with head /proc/1234/fdinfo/0 where 1234 is the process ID of cat.
¹ Among the basic text processing utility, the main exception is sort, which can't emit any output until it's read the whole input: for all it knows, the first line of output may well be the last line of input that it reaches.
yes hallo baby | lessdoes not first load the infinite output ofyesbefore piping it toless. This strange notion of commands in a pipeline being run sequentially certainly has its origin in some lousy textbook or tutorial, I don't think that so many people fell in the same trap by themselves. – Apr 02 '20 at 14:09