Recent from talks
Nothing was collected or created yet.
Tee (command)
View on Wikipedia| tee | |
|---|---|
| Developers | AT&T Bell Laboratories, Mike Parker, Richard Stallman, David MacKenzie, Microware, Jim Hall, JP Software, Microsoft |
| Initial release | June 1974 |
| Written in | C |
| Operating system | Unix, Unix-like, Plan 9, Inferno, OS-9, FreeDOS, Windows, ReactOS, IBM i |
| Platform | Cross-platform |
| Type | Command |
| License | FreeDOS: GPL-2.0-or-later ReactOS: GPLv2 Plan 9: MIT License |
tee is shell command that copies data from standard input to one or more files in addition to standard output; duplicating the input to each output.[1] The name derives from the tee pipe fitting even though the tee command duplicates the input into each output instead of dividing the input into portions for each output.[2] The command is often used with pipes and filters. Similar behaving commands are provided by many shells although syntax varies.
The command is provided in Unix and Unix-like systems, OS-9,[3] DOS (e.g. 4DOS, FreeDOS), Windows (e.g. 4NT, PowerShell, UnxUtils[4]), ReactOS[5] and IBM i.[6]
The Linux version was written by Mike Parker, Richard Stallman, and David MacKenzie.[7]
The FreeDOS version was developed by Jim Hall and is licensed under the GPL.[8]
Additionally the sponge[9] command offers similar capabilities.
Unix
[edit]The typical syntax on a Unix-based system can be described as:
tee [-a] [-i] [file...]
file...One or more names for files to receive the command input data-aAppend to a file rather than overwriting-iIgnore interrupts
Process substitution lets more than one process read the standard output of the originating process.[10].
If a write to any file is not successful, writes to other files and standard output continue, but the exit status will indicate failure with a value greater than 0.
Examples
[edit]The following both displays the output of the lint program.c command and saves the output to a file named program.lint; overwriting it if it already existed.
lint program.c | tee program.lint
The following does the same as the previous example, except for appending the output to an existing file instead of overwriting it. The file is created if it was not pre-existing.
lint program.c | tee -a program.lint
The following bypasses a limitation of the sudo command which is unable to pipe standard output to a file. By dumping its stdout stream into /dev/null, output to the console suppressed. This gives the current user root access to a server over ssh, by installing the user's public key to the server's key authorization list.
cat ~/.ssh/id_rsa.pub | ssh admin@server "sudo tee -a /root/.ssh/authorized_keys2 > /dev/null"
In Bash, the output can be filtered before being written to the file—without affecting the output displayed—by using process substitution. The following removes common ANSI escape codes before writing to ls.txt, but retains them for display.[11]
ls --color=always | tee >(sed "s/\x1b[^m]*m//g" > ls.txt)
4DOS and 4NT
[edit]The syntax on 4DOS and 4NT can be described as:
TEE [/A] file...
fileOne or more names for files to receive the command input data/AAppend to a file rather than overwriting
When used with a pipe, the output of the previous command is written to a temporary file. When that command finishes, tee processes the temporary file; copying it to the file argument(s) and standard output.
Examples
[edit]This example searches the file wikipedia.txt for any lines containing the string "4DOS", makes a copy of the matching lines in 4DOS.txt, sorts the lines, and writes them to the output file 4DOSsorted.txt:
>find "4DOS" wikipedia.txt | tee 4DOS.txt | sort > 4DOSsorted.txt
PowerShell
[edit]Powershell is not suitable for binary and raw data, always treats the stream as text, and modifies the data as it is transferred.
The syntax on PowerShell can be described as:
tee [-FilePath] <String> [-InputObject <PSObject>] tee -Variable <String> [-InputObject <PSObject>]
-InputObject <PSObject>Specifies the object input to the cmdlet. The parameter accepts variables that contain the objects and commands or expression that return the objects.-FilePath <String>Specifies the file where the cmdlet stores the object. The parameter accepts wildcard characters that resolve to a single file.-Variable <String>A reference to the input objects will be assigned to the specified variable.
The command is implemented as a ReadOnly command alias that invokes the cmdlet named Microsoft.PowerShell.Utility\Tee-Object.
Examples
[edit]The following displays the standard output of command ipconfig in the console window, and simultaneously saves a copy of it in the file OutputFile.txt.
ipconfig | tee OutputFile.txt
The following shows that the piped input for tee can be filtered and that tee is used to display that output, which is filtered again so that only processes owning more than 1000 handles are displayed, and writes the unfiltered output to the file ABC.txt. To display and save all running processes, filtered so that only programs starting with svc and owning more than 1000 handles are output:
Get-Process | Where-Object { $_.Name -like "svc*" } | Tee-Object ABC.txt | Where-Object { $_.Handles -gt 1000 }
See also
[edit]- GNU Core Utilities – Collection of standard, Unix-based utilities from GNU
- List of POSIX commands
- syslog – Network event logging system and protocol
References
[edit]- ^ "Man Page for tee (posix Section 1)". IEEE Std 1003.1, 2003 Edition, Standard for Information Technology -- Portable Operating System Interface (POSIX), The Open Group Base Specifications Issue 6. Retrieved 1 December 2013.
- ^ "In Unix, what do some obscurely named commands stand for?". Archived from the original on 27 November 2005. Retrieved 3 February 2012.
- ^ Paul S. Dayan (1992). The OS-9 Guru - 1 : The Facts. Galactic Industrial Limited. ISBN 0-9519228-0-7.
- ^ "Native Win32 ports of some GNU utilities". unxutils.sourceforge.net.
- ^ "reactos/reactos". GitHub. 3 January 2022.
- ^ IBM. "IBM System i Version 7.2 Programming Qshell" (PDF). IBM. Retrieved 5 September 2020.
- ^ "tee: read from standard input and write to standard output and files". www.mankier.com.
- ^ "ibiblio.org FreeDOS Package -- tee (Unix-like)". www.ibiblio.org.
- ^ "sponge(1): soak up stdin/write to file - Linux man page". linux.die.net.
- ^ GNU Coreutils, tee invocation
- ^ "GNU Coreutils: tee invocation". Retrieved 3 February 2016.
Further reading
[edit]- McElhearn, Kirk (2006). The Mac OS X Command Line: Unix Under the Hood. John Wiley & Sons. ISBN 978-0470113851.
External links
[edit]- An introduction on Linux I/O Redirection "Linux I/O Redirection" Archived 10 June 2012 at the Wayback Machine with tee
- GNU tee manual
- : duplicate standard input – Shell and Utilities Reference, The Single UNIX Specification, Version 5 from The Open Group
- – Plan 9 Programmer's Manual, Volume 1
- – Inferno General commands Manual
- Delphi-Tee - Delphi (software) OpenSource implementation
Tee (command)
View on Grokipediatee command is a standard utility that reads data from standard input and writes it simultaneously to both standard output and one or more specified files, effectively duplicating the input stream.[1] The command's name derives from the T-splitter fitting used in plumbing, which divides a single flow into two directions.[2] Originating from Version 6 Unix developed at Bell Labs Research in June 1974, tee has become a core component of Unix pipelines for tasks like logging and monitoring output without interrupting data flow.[3]
As defined in the POSIX standard (IEEE Std 1003.1-2017), tee copies standard input to standard output and zero or more files without buffering output, overwriting files by default unless the -a (append) option is specified.[1] The basic synopsis is tee [-ai] [file...], where -i ignores interrupt signals like SIGINT to prevent premature termination.[1] In GNU Coreutils implementations, which are widely used in Linux distributions, additional options such as -p or --output-error allow control over error handling for write failures, and specifying - as a filename duplicates output to standard output again.[4]
The tee command is particularly valuable in shell scripting and command-line workflows for splitting output streams, such as capturing verbose program logs to a file while displaying them on the terminal—for instance, ps aux | tee processes.log lists running processes and saves the result to a file.[4] It supports process substitution in shells like Bash for parallel operations, such as computing checksums or compressing data in multiple directions.[4] Exit status is 0 on success and nonzero on failure, ensuring reliable integration in automated scripts.[4]
Overview
Purpose and Functionality
Thetee utility reads from standard input (stdin) and writes the data simultaneously to standard output (stdout) as well as to one or more specified files, effectively duplicating the input stream without altering its original flow.[1] This dual-output mechanism allows users to capture and persist data to files while continuing to process it through pipelines or further commands.[1]
A core function of tee is the non-destructive duplication of data streams, which facilitates real-time monitoring, logging, or archiving in command-line workflows without interrupting the primary data path. By preserving the integrity of stdout, tee ensures that downstream processes receive the complete input as if no duplication occurred, while independently handling file writes to enable persistent storage.[1]
In operation, tee processes input from stdin in a linear fashion: it reads blocks of data, echoes them verbatim to stdout to maintain pipeline continuity, and concurrently appends or overwrites the same data to target files, thereby adding persistence without affecting error streams like stderr, which remain separate.[1] This behavior supports seamless integration in Unix-like environments, where tee is standardized under POSIX for portable use across compliant systems.[1]
The command derives its name from the T-junction in plumbing, symbolizing its role in branching a single input flow to multiple outputs, a concept originating from early Unix tools designed for efficient stream manipulation.
Historical Development
The tee command originated as part of the early Unix operating system developed at Bell Labs in the 1970s by Ken Thompson and Dennis Ritchie, forming a key component of the initial Unix toolkit designed for efficient data processing and pipeline integration.[5][6] It first appeared in the Fifth Edition of Unix in 1974, and was included in Version 7 Unix, released in 1979, among the standard utilities for duplicating input streams.[7][8] The command's design reflected the minimalist philosophy of early Unix, enabling simple yet powerful I/O manipulations without complex buffering. Standardization efforts began in the late 1980s to promote portability across Unix-like systems, with POSIX.1-1988 formally defining the core behavior of tee, including its requirement to copy standard input to standard output and files without buffering.[9] This specification ensured consistent implementation in diverse environments, establishing tee as a foundational utility for compliant systems. Subsequently, the command was incorporated into the Single UNIX Specification (SUS) across its versions, from SUSv1 onward, reinforcing its role in ensuring interoperability in modern BSD and Linux distributions.[1] In parallel, the GNU Project extended tee's functionality starting in the 1980s through its core utilities suite, with significant evolution in the merged GNU coreutils package formalized in 2002 from earlier components like shellutils. GNU implementations include the POSIX-standard options as well as extensions beyond the baseline, such as--output-error for controlling error handling on write failures.[4] These developments maintained backward compatibility while enhancing utility for logging and incremental data handling in GNU environments.
Syntax and Options
Core Syntax
The core syntax of thetee command follows the form tee [options] [file ...], where it reads data from standard input (stdin) and simultaneously writes that data to standard output (stdout) as well as to each specified file.[1] This structure adheres to the POSIX standard, enabling consistent behavior across compliant systems.[1]
The positional arguments [file ...] represent one or more target files to which the input is copied; if no files are provided, tee simply passes the input through to stdout without additional writes.[1] By default, tee overwrites the content of any existing target files with the new data, truncating them if necessary to start writing from the beginning.
In Unix-like environments, tee integrates seamlessly into pipelines, such as command | tee file, where the output from the preceding command flows into tee via stdin, allowing duplication to a file while preserving the stream to subsequent commands or stdout.[1] When multiple files are specified (e.g., tee file1 file2), tee writes the identical input content to each file in the order listed, ensuring synchronized duplication unless modified by options.[10]
Standard Options
Thetee utility supports a limited set of standard options as mandated by the POSIX specification, which ensure portability across compliant systems. These options modify the behavior of file output handling and signal processing without introducing implementation-specific extensions.[1]
The -a or --append option directs tee to append the input data to the specified files rather than overwriting their existing contents, thereby preserving prior data in those files. This is particularly useful for accumulating output over multiple invocations without data loss. When specified, -a applies uniformly to all file operands provided on the command line.[1]
The -i or --ignore-interrupts option causes tee to disregard the SIGINT signal, typically generated by an interrupt such as Ctrl+C from the terminal, allowing the command to continue processing input until completion or another termination condition. This ensures uninterrupted operation in interactive environments where accidental signals might otherwise halt the utility prematurely. Like -a, the -i option takes effect globally for the entire invocation.[1]
In accordance with POSIX utility syntax guidelines, options such as -a and -i must precede any file arguments on the command line, facilitating predictable parsing and avoiding ambiguity between options and operands. This requirement guarantees that all options influence the handling of every specified output file consistently, promoting reliable behavior in scripts and pipelines across POSIX-compliant implementations.[1][11]
Implementation-Specific Options
The GNU implementation of thetee command, as provided in coreutils for Linux systems, extends the POSIX standard with several additional options for enhanced usability and diagnostics. These include --help, which displays a brief usage summary and exits, and --version, which outputs version information including the build date and copyright details. Furthermore, the -p or --output-error[=MODE] option allows configuration of error handling when writing to pipes or files fails, with modes such as warn (diagnose errors writing to any output, continue writing to remaining outputs, and set exit status to indicate failure if any output errors occurred), warn-nopipe (default: diagnose errors writing to any output not a pipe, but on a pipe error exit immediately), exit (exit immediately on error writing to any output), and exit-nopipe (exit immediately on error writing to any output not a pipe, but on a pipe error exit immediately). This option directs diagnostic messages to standard error, preserving the integrity of the primary data stream to standard output and files.[4]
In contrast, BSD variants such as FreeBSD adhere closely to the POSIX specification, supporting only the standard -a (append) and -i (ignore interrupts) options without GNU's extensions like --help, --version, or -p.
The BusyBox implementation, designed for embedded systems and resource-constrained environments, further trims options to maintain a small footprint, supporting solely -a for appending output and -i for ignoring interrupt signals, omitting non-essential features like help or version displays.[12]
The -p option in GNU tee particularly aids debugging in complex pipelines by isolating error diagnostics to standard error, allowing developers to monitor issues such as broken pipes without corrupting the forwarded data stream—for instance, in scenarios where a subsequent command in the pipeline fails unexpectedly.[13]
Usage Examples
Basic Redirection
Thetee command facilitates basic input/output redirection by reading from standard input and simultaneously writing the data to both standard output (for immediate display) and one or more specified files.[10] This duplication allows users to capture output without interrupting the normal flow of command results to the terminal.[4]
A simple example demonstrates this functionality: executing echo "Hello" | tee output.txt sends the string "Hello" to both the screen (via stdout) and the file output.txt, creating or overwriting the file with the content.[10] Similarly, cat file.txt | tee backup.txt reads the contents of file.txt and duplicates them to both the terminal display and backup.txt, effectively creating a copy while showing the original data.[4] By default, tee overwrites any existing target files, which can be verified post-execution using commands like ls to confirm the file's presence and size or cat backup.txt to inspect its contents.[10]
This overwrite behavior makes tee particularly useful for quick logging, such as saving the output of a command to a file for later review while continuing to observe it in real-time on the display.[14] For scenarios requiring addition to existing files rather than replacement, the -a (append) option can be used, as detailed in the standard options section.[4]
Pipeline Integration
Thetee command serves as a key component in Unix pipelines by acting as a non-terminating splitter that duplicates standard input to both standard output—for continued processing downstream—and one or more files, thereby enabling efficient branching in sequential command flows without interrupting the data stream.[1] This functionality allows upstream commands to generate output that is simultaneously captured for persistent storage and passed to subsequent commands for further manipulation, such as filtering or sorting. In essence, tee facilitates the creation of "T-shaped" data paths in pipelines, mirroring the plumbing fitting from which it derives its name, and supports real-time processing by writing data without full buffering to ensure low-latency propagation through the chain.[1]
A practical illustration of this integration is the pipeline ls -l | tee listing.txt | grep ".txt", where ls -l generates a detailed directory listing, tee saves the complete output to listing.txt while forwarding it unchanged, and grep then filters the stream to display only lines containing ".txt" for text files.[14] Similarly, ps aux | tee processes.log | sort -k1 captures the full process list from ps aux into processes.log for logging purposes, then sorts the output by the first field (typically the user) to organize the data for analysis.[15] These examples highlight tee's role in maintaining pipeline continuity, as the command does not consume or alter the data stream, allowing downstream utilities to operate on the original input.[10]
Particularly in long-running processes, [tee](/page/Tee) enhances efficiency by enabling simultaneous monitoring and archival without performance bottlenecks, as seen in tail -f /var/log/syslog | tee monitor.log, which continuously tails the system log in real-time, duplicates the output to monitor.log for offline review, and permits further piping if needed—all while adhering to unbuffered I/O to minimize delays in interactive sessions.[16] This approach is especially valuable in system administration tasks, where preserving the full data flow for both immediate display and historical records prevents the need for separate invocations or complex scripting.[17]
Error Handling Scenarios
Thetee command handles errors encountered during output operations in a manner that prioritizes continuity for standard output while signaling failures appropriately. For instance, when attempting to write to a protected file without sufficient permissions, such as in the command echo "data" | tee /root/protected.txt, tee will output an error message to standard error indicating "permission denied" for the file, but it will still successfully duplicate the input "data" to standard output, allowing the pipeline to proceed.[10] This default behavior ensures that non-pipe outputs (like files) do not halt the overall process unless explicitly configured otherwise via the --output-error option.
In scenarios involving write failures, such as running out of disk space while appending to a file, tee will diagnose the error (e.g., "No space left on device") and exit with a non-zero status code to indicate failure, but it preserves any partial output already written to the file and continues directing input to standard output and other valid destinations.[10] This partial preservation is crucial for logging applications where complete data loss is undesirable, though the non-zero exit status can be trapped in scripts for error handling, such as command | tee log.txt || echo "Error occurred".
Interruptions, like those from Ctrl+C (SIGINT), can also affect tee's operation, but the -i or --ignore-interrupts option allows it to persist through such signals. For example, executing yes | tee -i output.txt and then pressing Ctrl+C will cause tee to ignore the interrupt, continuing to write the infinite "y" output to the file without termination.[10] Without this option, the interrupt would stop tee immediately, potentially leaving incomplete output.
Platform Implementations
Unix-like Systems
The tee command is installed by default at/usr/bin/tee on most Unix-like systems, forming a core component of essential utilities. In Linux environments, it is provided by the GNU coreutils package, ensuring consistent availability across distributions such as Ubuntu and Fedora.[4] In BSD systems like FreeBSD, tee is part of the base system installation, accessible without additional packages and aligned with POSIX standards for portability.[18]
Implementations in Unix, Linux, and BSD strictly follow the POSIX specification, which mandates that tee copies standard input to both standard output and one or more files while avoiding output buffering to maintain real-time processing.[19] This adherence ensures predictable behavior, including overwriting files by default or appending with the -a option, and continuing operations despite errors on individual outputs. Atomic writes are supported where feasible through underlying system calls, particularly for data sizes up to the PIPE_BUF limit when piping to or from tee.[19] The POSIX definition of tee traces back to early Unix standards, providing a foundation for its role in command-line workflows.
In Linux with the GNU tee implementation, newly created files receive permissions masked by the current process umask, typically resulting in modes like 0644 for regular files unless overridden, to prevent unintended access. FreeBSD's tee operates within the system's enhanced security model, where file flags—such as append-only or immutable attributes set via chflags—offer additional protections that restrict writes or deletions even if standard permissions permit them.[20] For integration with shells like bash, tee handles UTF-8 encoded input and output natively when the locale is set to UTF-8 (e.g., via LANG=en_US.[UTF-8](/page/UTF-8)), preserving character integrity in pipelines without requiring special flags.
Windows Environments
The Windows Command Prompt (CMD) does not include a native tee command among its built-in utilities, requiring users to seek emulations or third-party implementations for duplicating standard input to both output and files.[21] Common emulations in CMD involve batch scripts that approximate tee's behavior, such as Tee.bat, which redirects piped input to the console while appending it to a specified file without blocking the pipeline. For instance, a command likedir | teebat log.txt displays the directory listing on screen and saves it to log.txt simultaneously. These scripts leverage native redirection operators like > and type but may introduce minor delays or require synchronous execution in simpler variants.[22]
Third-party ports provide more faithful reproductions of tee; the GNU Coreutils package via GnuWin32 has offered a Windows-native tee.exe since version 5.3.0, released in April 2005, allowing POSIX-like syntax in CMD or other shells.[23] Additionally, starting with Windows 10 version 2004 (build 19041) and Windows 11, the Windows Subsystem for Linux (WSL) integrates full Unix command sets, including the standard tee from distributions like Ubuntu, enabling seamless use within a Linux environment on Windows without additional installations.[24]
These ported implementations generally adhere to POSIX standards for input/output handling but adapt to Windows file systems by supporting drive letters and backslash paths; for example, ipconfig | tee C:\network_log.txt captures network configuration output to a file on the C: drive while displaying it in the console. However, cross-platform scenarios introduce challenges with line endings, as Windows defaults to carriage return-line feed (CRLF) sequences (\r\n) for newlines, while Unix employs line feed (LF) alone (\n). Tee commands preserve the input stream's byte-for-byte format, so Unix-sourced input with LF endings written via a Windows port may produce files that render incorrectly in native Windows text editors or scripts expecting CRLF, necessitating tools like dos2unix for conversion.[25]
DOS and Legacy Shells
In DOS-based environments, thetee functionality was implemented as a built-in command in enhanced command-line interpreters like 4DOS, developed by JP Software and first released in 1989 as a replacement for the standard COMMAND.COM shell in MS-DOS systems.[26] This command duplicated standard input to standard output while simultaneously writing it to specified files, enabling piping operations in resource-constrained legacy setups where Unix-like tools were unavailable.[27] 4DOS's TEE supported basic redirection similar to its Unix counterpart, allowing users to capture pipeline output for logging or further processing within MS-DOS batch files and scripts, with options like /A for appending to files.[28]
The successor to 4DOS, 4NT, introduced in the early 1990s for Windows NT environments, retained and expanded the TEE command with deeper integration into batch file processing.[29] This allowed for more flexible duplication of stdout in automated tasks, building on 4DOS's foundation while adapting to NT's command processor (CMD.EXE) limitations.[30] Both implementations emphasized compatibility with MS-DOS piping, making TEE a key tool for developers working in command.com replacement environments.[31]
Behaviorally, TEE in these shells supported an append mode (via options like /A) to add output to existing files without overwriting, but operations were constrained by DOS's inherent limit of 255 maximum open file handles per process, which could lead to errors in complex pipelines involving multiple files.[28] This restriction stemmed from the underlying MS-DOS architecture, where file handle allocation was managed globally and could not exceed 255 without custom extensions or memory managers.[32] As a result, users in legacy DOS setups often optimized TEE usage to avoid exhausting handles during batch executions or multi-file logging.[33]
FreeDOS, an open-source DOS-compatible operating system first released in 1998 and maintained as of 2025, includes a standard tee command in its base utilities package. This implementation reads from standard input, writes to standard output, and copies to one or more files, with syntax tee [options] [file], supporting append mode via options and adhering to basic Unix-like behavior for legacy compatibility.[34]
PowerShell Variant
In PowerShell, the equivalent functionality to the Unixtee command is provided by the Tee-Object cmdlet, which was introduced in PowerShell 1.0 in November 2006 as part of the Microsoft.PowerShell.Utility module.[35][36] This cmdlet redirects pipeline input to both a specified destination—such as a file or variable—and the console output, while preserving the original data flow for further processing. Unlike traditional text-based tee implementations, Tee-Object operates on .NET objects, enabling it to handle structured data like arrays, custom objects, or process information without immediate serialization to plain text, thus maintaining object properties throughout the pipeline.[36]
The basic syntax for Tee-Object includes parameters such as -FilePath for writing to a file, -Variable for storing in a variable, -Append (introduced in PowerShell 3.0 for appending to existing files rather than overwriting), and -InputObject to specify objects directly rather than relying solely on pipeline input.[36] For instance, the command Get-Process | Tee-Object -FilePath log.txt | Sort-Object retrieves running processes, saves them to log.txt while displaying and sorting them in the console, demonstrating seamless integration with PowerShell's object-oriented pipeline.[36] This object-aware behavior allows for advanced scenarios, such as teeing an array of custom objects for parallel logging and filtering: $data = [PSCustomObject]@{Name='Item1'; Value=10}, [PSCustomObject]@{Name='Item2'; Value=20}; $data | Tee-Object -Variable backup | Where-Object {$_.Value -gt 15}, where the full object structure is retained in both the backup variable and the filtered output.[36]
PowerShell's Tee-Object enhances scripting flexibility by leveraging the language's type system, where input objects are serialized only when written to files (using UTF-8 encoding by default in PowerShell 6 and later), but remain fully functional .NET instances when assigned to variables or passed downstream.[36] This contrasts with stream-based tools by supporting pipeline-aware operations on complex data types, making it particularly useful in automation tasks involving structured output from cmdlets like Get-Process or Get-Service.[36]
Common Pitfalls and Best Practices
Security Considerations
One significant security risk associated with thetee command is its default behavior of overwriting existing files when writing output, which can lead to unintended data loss for critical system or log files if not carefully managed.[14] To mitigate this, users should verify file existence and permissions prior to invocation, such as by employing a conditional check like test -f file in scripts before piping to tee.[10] The append option (-a) provides a straightforward mitigation by adding content to the end of files rather than replacing them, preserving prior data.[14]
In multi-user Unix-like environments, tee operates under the invoking user's permissions, inheriting the process's effective user ID and group ID, which can expose sensitive files to modification if output is piped from untrusted or malicious sources.[15] For instance, in scenarios involving unverified input pipelines, an attacker could inject harmful content into privileged files, emphasizing the need to avoid tee in setuid (SUID) contexts or with untrusted streams to prevent unauthorized exposure or escalation.
When elevating privileges, tee should be used with sudo judiciously, such as in command | sudo tee /path/to/root/file, to write to protected locations, but this amplifies risks if input is not sanitized; instead, prefer direct redirection operators like > for logging root-owned files to minimize pipeline exposure.[37]
Performance Implications
Thetee command is specified to operate without buffering output, meaning it performs writes immediately rather than accumulating data in buffers, which supports timely processing in pipelines but allows implementations to optimize beyond single-byte operations for efficiency.[1] This unbuffered behavior ensures that data flows through without artificial delays from tee itself, though real-time performance in Unix pipelines can still be affected by buffering in preceding commands, leading to potential stalls until buffers fill. To address this, the stdbuf utility can enforce line buffering (e.g., stdbuf -oL command | tee file), flushing output after each newline for more responsive handling in interactive or monitoring scenarios.[38][39]
In high-volume data scenarios, GNU tee's resource usage remains low in terms of CPU overhead, as it primarily involves duplicating input streams to multiple destinations without complex computation. However, when writing to multiple files, the I/O load scales linearly with the number of outputs, since each file requires a separate write operation, effectively multiplying disk throughput demands—for instance, directing output to two files doubles the total data written to storage compared to a single output. This disk I/O intensification is the primary performance bottleneck, particularly in pipelines processing large datasets, where it can extend execution times proportional to the output count and storage speed.[4]
For scalability implications, tee performs adequately on modern hardware but can introduce overhead in resource-constrained environments, such as embedded systems with limited memory, where the primary costs are I/O-related rather than memory usage. In such cases, the BusyBox variant optimizes for minimal footprint and low-resource operation, making it suitable for embedded Linux deployments despite potential trade-offs in raw throughput for I/O-heavy tasks. As detailed in Unix-like system implementations, this unbuffered design underpins tee's efficiency in standard pipelines.[40][41]
Alternatives Comparison
Thetee command differs from standard output redirection operators such as > file and >> file, which direct a command's output solely to a file while suppressing display on standard output (stdout), thereby preventing real-time monitoring or further piping; in contrast, tee duplicates the input stream to both stdout and one or more files, enabling simultaneous logging and continuation in pipelines.[4][42]
Unlike the script command, which records an entire interactive terminal session—including user input, control characters, and timing information for potential replay—tee focuses exclusively on duplicating stdout (or combined stderr via redirection) without capturing terminal-specific artifacts like tty interactions.[43][4]
In scripting scenarios, a one-off use of tee processes a single command's output, whereas employing exec > >(tee log) at the script's outset redirects the entire shell's stdout persistently to both the terminal and a log file via process substitution, allowing comprehensive session logging without repeated invocations.[44][45]
Tools like multitail build upon tee-like functionality by supporting colored, filtered output to multiple files or commands, with options to write pre- or post-filtered streams, thus extending tee for advanced multi-file monitoring and visualization.[46]