tee(2)
Duplicate data from one pipe into another without consuming it from the source.
- Since
- Linux 2.6.17check your kernel →
- glibc
- glibc 2.5
- System
- Linux
- Man page
- tee(2)
Synopsis
#define _GNU_SOURCE
#include <fcntl.h>
ssize_t tee(int fd_in, int fd_out, size_t size, unsigned int flags);Rod's take
tee(1) reads stdin and writes it twice, through userspace both times. tee(2) does it inside the kernel: it duplicates what's sitting in one pipe into another without consuming the source, so a following splice can still drain the original. Both ends must be pipes. Log fanout is tee into a scratch pipe, splice the original to one place, splice the copy to the other, and nobody forks a shell pipeline. Only page pointers get duplicated, never the pages. Small, obscure, and exactly right for the job.
Flags and arguments that matter
| Name | What it does |
|---|---|
| SPLICE_F_NONBLOCK | Do not block on I/O; see splice(2). |
| SPLICE_F_MOVE | Currently has no effect for tee(). |
| SPLICE_F_MORE | Currently has no effect for tee(); may be implemented in future. |
| SPLICE_F_GIFT | Unused for tee(); see vmsplice(2). |
Errors you will actually hit
| errno | Meaning |
|---|---|
| EINVAL | fd_in or fd_out is not a pipe, or both refer to the same pipe. |
| EAGAIN | SPLICE_F_NONBLOCK or O_NONBLOCK set and the operation would block. |
| ENOMEM | Out of memory. |
Example
/* stdin and stdout are pipes; also copy everything to logfd */
for (;;) {
ssize_t n = tee(STDIN_FILENO, STDOUT_FILENO, INT_MAX, SPLICE_F_NONBLOCK);
if (n < 0 && errno == EAGAIN)
continue; /* real code: poll() first */
if (n < 0)
err(1, "tee");
if (n == 0)
break;
while (n > 0) { /* consume what tee duplicated */
ssize_t s = splice(STDIN_FILENO, NULL, logfd, NULL, n, 0);
if (s <= 0)
err(1, "splice");
n -= s;
}
}Trimmed from the full walkthrough in splice and tee: zero-copy data movement, 2.6.17 edition.
BSD equivalent
none
The long version, from the console
Sources
Version numbers are read off the cited man pages, not memory. Spot one that's wrong? Tell Rod.
